按下组合键时聚焦用户控件的子控件
Focus a child Control of a User Control when a combination of keys is pressed
我有一个包含面板的表单,我在其中放置了一个 UserControl。
我希望当按下 Ctrl+F 组合键时,我的 UserControl 的子 TextBox 控件获得焦点。
结构是这样的:
到目前为止,我已尝试处理 KeyPreview
和 KeyDown
事件。我可以显示一个消息框:
但我无法将 TextBox 聚焦在我的 UserControl 中。
我该如何解决这个问题?
您或许可以实现 IMessageFilter 并处理您想要的组合键。
然后,您必须在不再需要时使用 Application.AddMessageFilter() to add the message filter and Application.RemoveMessageFilter() 将其删除。
这里勾选了UserControl的DesignMode 属性,所以只在run.time添加过滤器。
可能,添加一个 public 属性 可以添加/删除/更改键的组合,以防与其他控件发生冲突。
GetAncestor()函数用于判断触发组合键的Form是否为本UserControl实例的Parent Form
PreFilterMessage() 在应用程序的任何表单中生成消息时调用。
如果您在任何情况下都想执行某个操作,即使组合是在另一个打开的表单中生成的(并且可能弹出前面的父表单),只需删除该检查即可。
滤镜Control + F.
如前所述,如果您需要更多过滤器,请使用集合来处理这些组合。
当 WM_KEYDOWN is received, WParam
contains the virtual Key Code. The Virtual Key value is equivalent to the 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);
}
我有一个包含面板的表单,我在其中放置了一个 UserControl。
我希望当按下 Ctrl+F 组合键时,我的 UserControl 的子 TextBox 控件获得焦点。
结构是这样的:
到目前为止,我已尝试处理 KeyPreview
和 KeyDown
事件。我可以显示一个消息框:
但我无法将 TextBox 聚焦在我的 UserControl 中。
我该如何解决这个问题?
您或许可以实现 IMessageFilter 并处理您想要的组合键。
然后,您必须在不再需要时使用 Application.AddMessageFilter() to add the message filter and Application.RemoveMessageFilter() 将其删除。
这里勾选了UserControl的DesignMode 属性,所以只在run.time添加过滤器。
可能,添加一个 public 属性 可以添加/删除/更改键的组合,以防与其他控件发生冲突。
GetAncestor()函数用于判断触发组合键的Form是否为本UserControl实例的Parent Form
PreFilterMessage() 在应用程序的任何表单中生成消息时调用。
如果您在任何情况下都想执行某个操作,即使组合是在另一个打开的表单中生成的(并且可能弹出前面的父表单),只需删除该检查即可。
滤镜Control + F.
如前所述,如果您需要更多过滤器,请使用集合来处理这些组合。
当 WM_KEYDOWN is received, WParam
contains the virtual Key Code. The Virtual Key value is equivalent to the 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);
}