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

标签 c# .net winforms user-controls focus

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

结构是这样的:

enter image description here

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

enter image description here

但我无法将 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/

相关文章:

c# - 如何使用 EF 4 和 SQL Server CE 3.5 对查询结果进行分页

c# - 按顺序使用相同的静态对象执行测试

encryption - 在 C# .NET Core 中,我应该如何使用在 HSM 中创建的签名对 CSR 进行签名?

winforms - 如何编写大型 WinForms 应用程序?

c# - 获取浏览器中打开的标签页的 URL

c# - Unity3D C# 中的相机旋转问题(可能很容易修复)

c# - SetupDi API : Control Device Manager functionality programmatically

.net - 为子查询提供表达式

.net - 解析程序集合格名称?

c# - 检查是否按下了 PAGEUP 或 PAGEDOWN