我有一个表单,其中包含一个面板,我在其中放置了一个用户控件。
我希望当按下 Ctrl+F 键组合时,我的 UserControl 的子级 TextBox 控件获得焦点。
结构是这样的:
到目前为止,我已尝试处理 KeyPreview
和 KeyDown
事件。我可以显示一个 MessegeBox:
但我无法将 TextBox 聚焦在我的 UserControl 中。
我该如何解决这个问题?
最佳答案
你也许可以实现 IMessageFilter并处理您想要的按键组合。
然后你必须使用 Application.AddMessageFilter()添加消息过滤器和 Application.RemoveMessageFilter()当不再需要时将其删除。
这里,UserControl 的 DesignMode属性被选中,因此过滤器仅在运行时添加。
可能的话,添加一个可以添加/删除/更改键组合的公共(public)属性,以防与其他控件发生冲突。
GetAncestor()函数用于判断触发按键组合的Form是否是该UserControl实例的Parent Form。
PreFilterMessage()当以应用程序的任何形式生成消息时调用。
如果您想在任何情况下执行操作,即使组合是在另一个打开的表单中生成的(并且可能将父表单弹出在前面),只需删除该检查即可。
过滤器Control + F。
如果您需要更多过滤器,如上所述,请使用集合来处理这些组合。
何时 WM_KEYDOWN收到后,WParam
包含虚拟 key 代码。虚拟键值相当于 Keys枚举器。
ModifierKeys属性包含当前事件的键修饰符(此处仅测试 Control 键,当然您可以添加其他使用的快捷键,例如 CTRL+SHIFT)。
using System.ComponentModel;
using System.Runtime.InteropServices;
public partial class SomeUserControl : UserControl, IMessageFilter
{
public SomeUserControl() => InitializeComponent();
public bool PreFilterMessage(ref Message m) {
if (m.Msg == WM_KEYDOWN) {
if (GetAncestor(m.HWnd, GA_PARENT).Equals(ParentForm.Handle)) {
if (m.WParam.ToInt32() == (int)Keys.F && ModifierKeys == Keys.Control) {
someChildTextBox.Focus();
}
}
}
return false;
}
protected override void OnHandleCreated(EventArgs e) {
base.OnHandleCreated(e);
if (!DesignMode) Application.AddMessageFilter(this);
}
protected override void OnHandleDestroyed(EventArgs e) {
if (!DesignMode) Application.RemoveMessageFilter(this);
base.OnHandleDestroyed(e);
}
private const int WM_KEYDOWN = 0x0100;
private const int GA_PARENT = 0x0002;
[DllImport("user32.dll", SetLastError = true)]
private static extern IntPtr GetAncestor(IntPtr hWnd, uint flags);
}
关于c# - 按下组合键时聚焦用户控件的子控件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68908788/