C# 如何防止窗体在仍然收到鼠标单击的情况下窃取焦点?

C# 如何防止窗体在仍然收到鼠标单击的情况下窃取焦点?,c#,winforms,C#,Winforms,我正在尝试在WinForms中创建自定义AutoCompleteTextBox控件。基本文本框提供的自动完成功能仅提供带有(字符串)的结果。与(字符串)相反,StartsWith。包含 我在一个单独的表单中停靠的列表框中显示自动完成的搜索结果。我可以通过以下方式防止表单最初窃取焦点: protected override bool ShowWithoutActivation { get { return true; } } 然后,我可以通过以下方式覆盖WndProc方法,防止表单完全获得

我正在尝试在WinForms中创建自定义AutoCompleteTextBox控件。基本文本框提供的自动完成功能仅提供带有
(字符串)的结果。与
(字符串)相反,StartsWith
。包含

我在一个单独的
表单中停靠的
列表框中显示自动完成的搜索结果。我可以通过以下方式防止
表单
最初窃取焦点:

protected override bool ShowWithoutActivation
{
   get { return true; }
}
然后,我可以通过以下方式覆盖
WndProc
方法,防止
表单
完全获得焦点:

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;
    }
执行此操作时,
表单中包含的
列表框
将接收
MouseMoved
事件,但不会接收
MouseClicked
事件

MA_NOACTIVATE和at
更改为just
MA_NOACTIVATE
将鼠标事件传递到
列表框
,但随后将导致点击
列表框
表单
中窃取焦点
列表框
所在位置-将其传递到
列表框
所在的“浮动”表单


是否有任何方法可以防止“浮动”
表单
从“主”
表单
中转移焦点,同时在
列表框
中仍然获得
鼠标单击
事件?

将浮动表单转换为
用户控件
,如下所示:- 在它上面拉一个列表框来钩住点击事件,以模拟您的焦点场景(&H)

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");

        }
    }
}
主窗体中的代码(附带按钮及其单击处理程序):-

这将使用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(无边框窗体)显示为浮动窗体时,您会注意到,
即使您单击(选择)它的任何子窗体,它也不会收到焦点。在本例中,子对象是usercontrol上的列表框


除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控件)订阅该事件,并将焦点设置回自身。为了防止主窗体出现在浮动窗体前面,我将主窗体设置为浮动窗体的所有者,因为拥有的窗体从不显示在其所有者窗体后面


更多关于

我认为,在列表框中收到单击后,您将被迫将焦点放回主窗体上……或者您使用鼠标移动事件来确定悬停在哪个列表框项目上。HitTest(IIRC)将为您提供一个ListBoxItem。@lAbstract将焦点移回的问题是,下次您要显示浮动窗体时,它将导致主窗体出现在浮动窗体的前面。然后在浮动窗体上调用BringToFront会让它集中注意力-再次从主窗体中窃取它…啊,明白了:那么,如果你能够监视鼠标从主窗体的移动,你能在主窗体上获取
HitTestInfo
?如果您可以这样做,那么您实际上可以从浮动表单接收所选项目……我认为。;)这假定主窗体负责这些事情。这是一个自定义控件类,将以多种其他形式使用-因此,从重用的角度来看,这有点不可行。的可能重复