简体   繁体   English

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

[英]How can I prevent a form from stealing focus while still receiving mouse clicks?

I'm attempting to create a custom AutoCompleteTextBox control in WinForms. 我正在尝试在WinForms中创建自定义AutoCompleteTextBox控件。 The AutoComplete provided by the basic TextBox provides results only with (string).StartsWith as opposed to (string).Contains . 基本TextBox提供的AutoComplete仅提供(string).StartsWith而不是(string).Contains

I am displaying the Auto-Complete search results in a ListBox docked in a separate Form . 我在一个单独的Form停靠的ListBox显示自动完成搜索结果。 I can prevent the Form from stealing focus initially using via: 我可以阻止Form最初使用via窃取焦点:

protected override bool ShowWithoutActivation
{
   get { return true; }
}

Then, I can prevent the Form from gaining focus entirely by overriding the WndProc method via: 然后,我可以通过覆盖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;
    }

When I do this, the ListBox contained in the Form will receive MouseMoved events, but not MouseClicked events. 当我这样做时, Form包含的ListBox将接收MouseMoved事件,但不接收MouseClicked事件。

Chaning MA_NOACTIVATEANDEAT to just MA_NOACTIVATE will pass the mouse events to the ListBox , but then will cause the clicks on the ListBox to steal focus from the Form the ListBox resides in - passing it to the 'floating' Form the ListBox is in. Chaning MA_NOACTIVATEANDEAT只是MA_NOACTIVATE将通过鼠标事件的ListBox ,但随后会导致对的点击ListBox ,从偷焦点FormListBox位于-它传递给“浮动” FormListBox在不在。

Is there any way I can prevent the 'floating' Form from steeling focus from the 'main' Form while still getting MouseClick events within the ListBox ? 有没有什么办法可以阻止'浮动' Form从'main' Form获得焦点,同时仍然在ListBox获取MouseClick事件?

Convert your floating form into a Usercontrol as below :- Pull a ListBox on it to & hook onto Click event to simulate your scenario of Focus. 将您的浮动表单转换为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");

        }
    }
}

Code in the MainForm (with a button and its click handler attached):- MainForm中的代码(附带一个按钮及其点击处理程序): -

This invokes the floating control with ListBox. 这将使用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();
        }
    }
}

When you show the UserControl (borderless form) as your floating form, you will notice that it wont receive focus even if you clicked (selected) any of its children . 当您将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 In this case, the child is a ListBox on the usercontrol. 在这种情况下,子节点是usercontrol上的ListBox。

Refer here and here . 请参考此处此处

In addtion to previous answer by Angshuman Agarwal: If you want the main form does not deactive when the UserControl show as floating form, modify some code to your 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);
}

I've created something similiar and my solution is similar to what lAbstract suggests. 我创造了类似的东西,我的解决方案与lAbstract建议的类似。 The floatin form has an event DoReturnFocus wich the custom TextBox (the AutoCompleteTextBox control in this case) subscribes to, and simply sets focus back to itself. floatin表单有一个事件DoReturnFocus,它自定义TextBox(在这种情况下是AutoCompleteTextBox控件)订阅,并简单地将焦点设置回自身。 To prevent the main form to appear in front of the floating form I set the main form as the Owner of the floating form, as owned forms are never displayed behind their owner form.. 为了防止主窗体出现在浮动窗体的前面,我将主窗体设置为浮动窗体的所有者 ,因为拥有的窗体永远不会显示在它们的所有者窗体后面。

More on Form.Owner Property 有关Form.Owner Property的更多信息

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM