[英]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.