如何创建具有键盘焦点的非活动下拉列表
本文关键字:焦点 键盘 非活动 下拉列表 何创建 创建 | 更新日期: 2023-09-27 18:02:20
我想创建一个下拉控件,它应该是不活动的,并有键盘输入焦点。所以我创建了一个控件,如下所示:
public class DropDownEdit : UserControl
{
[DllImport("user32.dll")]
public static extern IntPtr SetParent(IntPtr hWndChild, IntPtr hWndNewParent);
private const int WS_EX_TOOLWINDOW = 0x00000080;
private const int WS_EX_TOPMOST = 0x00000008;
private const int WS_EX_NOACTIVATE = 0x08000000;
private const int WS_CHILD = 0x40000000;
private const int WS_POPUP = unchecked((int)0x80000000);
private TextBox text = new TextBox();
public DropDownEdit()
{
this.BackColor = Color.FromArgb(44, 68, 107);
this.Controls.Add(text);
this.Margin = Padding.Empty;
this.Padding = new Padding(0);
text.Multiline = true;
text.ScrollBars = ScrollBars.Both;
text.Size = new Size(this.Width, this.Height);
}
protected override CreateParams CreateParams
{
get
{
CreateParams createParams = base.CreateParams;
createParams.Style &= ~WS_CHILD;
createParams.Style |= WS_POPUP;
createParams.ExStyle |= WS_EX_TOOLWINDOW;
createParams.ExStyle |= WS_EX_TOPMOST;
createParams.ExStyle |= WS_EX_NOACTIVATE;
return createParams;
}
}
public void ShowWindow(Point point)
{
text.Focus();
this.Capture = true;
SetParent(this.Handle, IntPtr.Zero);
this.Location = point;
Show();
}
protected override void OnMouseCaptureChanged(EventArgs e)
{
base.OnMouseCaptureChanged(e);
this.Hide();
}
}
当我像下面这样显示上面的下拉窗口时,
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
Point point = this.PointToScreen(button1.Location);
DropDownEdit window = new DropDownEdit();
window.ShowWindow(new Point(point.X, point.Y + 20));
}
}
显示DropDownEdit
时,Form1
闪烁。我认为DropDownEdit
被活化,Form1
失去活化。如何避免Form1
中的闪烁?
NB:-我需要输入焦点在TextBox
下拉控件。
我找到解决办法了。
在显示我的下拉窗口时,它将被激活,而Windows将停用主窗口。解决这个问题的方法是向父程序发送WM_NCACTIVATE
消息,在不改变其激活状态的情况下更新其视觉外观。下面的代码是在DropDownEdit
类更新,以解决我的问题。
private const int WM_NCACTIVATE = 0x86;
[DllImport("user32.dll", CharSet = CharSet.Auto)]
public static extern IntPtr SendMessage(IntPtr hWnd, int msg, IntPtr wParam, IntPtr lParam);
protected override void WndProc(ref Message m)
{
// The popup needs to be activated for the user to interact with it,
// but we want to keep the owner window's appearance the same.
if ((m.Msg == WM_NCACTIVATE) && !_activating && (m.WParam != IntPtr.Zero))
{
// The popup is being activated, ensure parent keeps activated appearance
_activating = true;
SendMessage(this.Owner.Handle, WM_NCACTIVATE, (IntPtr) 1, IntPtr.Zero);
_activating = false;
// Call base.WndProc here if you want the appearance of the popup to change
}
else
{
base.WndProc(ref m);
}
}