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

llew8vvj  于 2022-11-16  发布在  其他
关注(0)|答案(1)|浏览(169)

我有一个窗体,其中包含一个放置了UserControl的面板。
我希望在按下Ctrl+F组合键时,UserControl的子控件TextBox控件获得焦点。
其结构是这样的:

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

但无法聚焦UserControl内的TextBox。
我怎样才能解决这个问题?

dw1jzc5e

dw1jzc5e1#

您可能可以实现IMessageFilter并处理所需的键组合。
然后,您必须使用Application.AddMessageFilter()添加消息过滤器,并使用Application.RemoveMessageFilter()删除不再需要的消息过滤器。
在这里,UserControl的DesignMode属性被选中,因此筛选器仅在运行时添加。
可能的话,添加一个可以添加/删除/更改键组合的公共属性,以防与其他控件发生冲突。
GetAncestor()函数用于确定触发Keys组合的窗体是否是此UserControl示例的父窗体。
在应用程序的任何表单中生成消息时,将调用PreFilterMessage()
相反,如果您希望在任何情况下执行某个操作,即使该组合是在另一个打开的窗体中生成的(并且可能在前面弹出父窗体),只需取消该复选框。
过滤器控制+ F。
如果您需要更多的筛选条件,请使用集合来行程这些组合。
当收到WM_KEYDOWN时,WParam包含虚拟键码。虚拟键值相当于Keys枚举器。
ModifierKeys属性包含当前活动的键修饰符(此处仅测试Ctrl键,当然您可以添加其他使用的快捷键,例如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);
}

相关问题