按下组合键时聚焦用户控件的子控件

Focus a child Control of a User Control when a combination of keys is pressed

我有一个包含面板的表单,我在其中放置了一个 UserControl。
我希望当按下 Ctrl+F 组合键时,我的 UserControl 的子 TextBox 控件获得焦点。

结构是这样的:

到目前为止,我已尝试处理 KeyPreviewKeyDown 事件。我可以显示一个消息框:

但我无法将 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);
}