[英]How can I prevent a form from stealing focus while still receiving mouse clicks?
我正在嘗試在WinForms中創建自定義AutoCompleteTextBox控件。 基本TextBox提供的AutoComplete僅提供(string).StartsWith
而不是(string).Contains
。
我在一個單獨的Form
停靠的ListBox
顯示自動完成搜索結果。 我可以阻止Form
最初使用via竊取焦點:
protected override bool ShowWithoutActivation
{
get { return true; }
}
然后,我可以通過覆蓋WndProc
方法來阻止Form
完全獲得焦點:
protected override void WndProc( ref Message m )
{
base.WndProc( ref m );
switch ( m.Msg )
{
case WM_MOUSEACTIVATE:
m.Result = ( IntPtr ) MA_NOACTIVATEANDEAT;
break;
default:
break;
}
當我這樣做時, Form
包含的ListBox
將接收MouseMoved
事件,但不接收MouseClicked
事件。
Chaning MA_NOACTIVATEANDEAT
只是MA_NOACTIVATE
將通過鼠標事件的ListBox
,但隨后會導致對的點擊ListBox
,從偷焦點Form
的ListBox
位於-它傳遞給“浮動” Form
的ListBox
在不在。
有沒有什么辦法可以阻止'浮動' Form
從'main' Form
獲得焦點,同時仍然在ListBox
獲取MouseClick
事件?
將您的浮動表單轉換為Usercontrol
,如下所示: - 在其上拉一個ListBox以掛鈎到Click事件以模擬您的Focus場景。
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;
namespace WindowsFormsApplication3
{
public partial class InactiveForm : UserControl
{
private const int WS_EX_TOOLWINDOW = 0x00000080;
private const int WS_EX_NOACTIVATE = 0x08000000;
private const int WS_EX_TOPMOST = 0x00000008;
[DllImport("user32")]
public static extern int SetParent
(IntPtr hWndChild, IntPtr hWndNewParent);
[DllImport("user32")]
public static extern int ShowWindow
(IntPtr hWnd, int nCmdShow);
protected override CreateParams CreateParams
{
get
{
CreateParams p = base.CreateParams;
p.ExStyle |= (WS_EX_NOACTIVATE | WS_EX_TOOLWINDOW | WS_EX_TOPMOST);
p.Parent = IntPtr.Zero;
return p;
}
}
public InactiveForm()
{
InitializeComponent();
}
public new void Show()
{
if (this.Handle == IntPtr.Zero) base.CreateControl();
SetParent(base.Handle, IntPtr.Zero);
ShowWindow(base.Handle, 1);
}
private void OnListBoxClicked(object sender, EventArgs e)
{
MessageBox.Show("Clicked List Box on floating control");
}
}
}
MainForm中的代碼(附帶一個按鈕及其點擊處理程序): -
這將使用ListBox調用浮動控件。
namespace WindowsFormsApplication3
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
InactiveForm f = new InactiveForm();
f.Show();
}
}
}
當您將UserControl(無邊框形式)顯示為浮動窗體時, it wont receive focus even if you clicked (selected) any of its children
,您也會注意到it wont receive focus even if you clicked (selected) any of its children
。 在這種情況下,子節點是usercontrol上的ListBox。
除了Angshuman Agarwal之前的回答之外:如果您希望當UserControl顯示為浮動窗體時主窗體不會失效,請將一些代碼修改為您的UserControl:
private Control _mControl;
[DllImport("user32.dll")]
static extern IntPtr SendMessage(IntPtr hwnd, int wMsg, IntPtr wParam, IntPtr lParam);
public new void Show(Control c)
{
if (c == null) throw new ArgumentNullException();
_mControl = c;
if (this.Handle == IntPtr.Zero) base.CreateControl();
SetParent(base.Handle, IntPtr.Zero);
ShowWindow(base.Handle, 1);
}
protected override void WndProc(ref Message m)
{
if (m.Msg == 0x86) //WM_NCACTIVATE
{
if (m.WParam != IntPtr.Zero) //activate
{
SendMessage(_mControl.Handle, 0x86, (IntPtr)1, IntPtr.Zero);
}
this.DefWndProc(ref m);
return;
}
base.WndProc(ref m);
}
我創造了類似的東西,我的解決方案與lAbstract建議的類似。 floatin表單有一個事件DoReturnFocus,它自定義TextBox(在這種情況下是AutoCompleteTextBox控件)訂閱,並簡單地將焦點設置回自身。 為了防止主窗體出現在浮動窗體的前面,我將主窗體設置為浮動窗體的所有者 ,因為擁有的窗體永遠不會顯示在它們的所有者窗體后面。
有關Form.Owner Property的更多信息
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.