如何在仍然接收鼠标点击时阻止表单窃取焦点?

Ant*_*ony 5 c# winforms

我正在尝试在WinForms中创建自定义AutoCompleteTextBox控件.基本TextBox提供的AutoComplete仅提供结果(string).StartsWith而不是(string).Contains.

ListBox在一个单独的对接中显示自动完成搜索结果Form.我可以防止Form最初使用via窃取焦点:

protected override bool ShowWithoutActivation
{
   get { return true; }
}
Run Code Online (Sandbox Code Playgroud)

然后,我可以Form通过覆盖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;
    }
Run Code Online (Sandbox Code Playgroud)

当我这样做时,ListBox包含在Form将会收到MouseMoved事件,但不是MouseClicked事件.

Chaning MA_NOACTIVATEANDEAT只是MA_NOACTIVATE将通过鼠标事件的ListBox,但随后会导致点击上ListBox偷焦点从FormListBox居住在-它传递给"浮动" FormListBox是英寸

有什么方法可以阻止"漂浮" Form从"主要"加强焦点,Form同时仍然在其中MouseClick发生事件ListBox

Ang*_*wal 0

将您的浮动表单转换为Usercontrol如下所示:- 在其上拉出一个列表框并挂接到 Click 事件以模拟您的焦点场景。

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

        }
    }
}
Run Code Online (Sandbox Code Playgroud)

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();
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

当您将 UserControl(无边框表单)显示为浮动表单时,您会注意到it wont receive focus even if you clicked (selected) any of its children. 在本例中,子项是用户控件上的列表框。

请参阅此处此处