6

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

我将自动完成搜索结果显示在ListBox停靠在单独的Form. 我可以防止Form最初使用通过以下方式窃取焦点:

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

然后,我可以通过以下方式覆盖该方法来防止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;
    }

当我这样做时,ListBox包含在Form将接收MouseMoved事件,但不接收MouseClicked事件。

更改MA_NOACTIVATEANDEAT为只会MA_NOACTIVATE将鼠标事件传递给ListBox,但随后会导致单击以从驻留中ListBox窃取焦点- 将其传递给“浮动”所在。FormListBoxFormListBox

有什么办法可以防止“浮动”Form从“主要”集中注意力,Form同时仍然在MouseClick内部获取事件ListBox

4

3 回答 3

0

除了 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);
}
于 2013-01-29T15:58:50.907 回答
0

我创建了一些类似的东西,我的解决方案与 lAbstract 建议的类似。floatin 表单有一个事件 DoReturnFocus ,自定义 TextBox(在本例中为 AutoCompleteTextBox 控件)订阅了该事件,并将焦点设置回自身。为了防止主窗体出现在浮动窗体的前面,我将主窗体设置为浮动窗体的所有者,因为拥有的窗体永远不会显示在其所有者窗体的后面。

更多关于Form.Owner 属性

于 2014-01-30T16:08:12.913 回答
0

将您的浮动表单转换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. 在这种情况下,子项是用户控件上的 ListBox。

请参阅此处此处

于 2012-06-21T22:33:15.657 回答