winforms UserControl不检测按键

本文关键字:检测 UserControl winforms | 更新日期: 2023-09-27 18:02:35

关于这个问题有很多(一,二,三,四,五),但我尝试了所有的修复,它们要么不起作用,要么不适合我的目的。下面是我的基本结构:

User Control
|-Panel
  |-Picture Box (several of them, created at runtime, do not exist at design time)

因为我认为这是相关的,面板有它的dock设置为"填充"和调整大小设置为"增长和缩小",所以它总是覆盖整个用户控件。图片框总是覆盖面板的一部分,但通常不是全部(尽管这是可能的)。

我特别在听Ctrl + C,我需要一种方法,无论哪个孩子有焦点,都可以响应。我想要一个可以监听任意按键的方法,这样我以后就可以扩展它了。

链接页面上的一个答案建议为这些按键制作一个全局监听器,我不想这样做,因为我不希望它在后台应用程序中关闭。另一个建议在顶级表单中检测它并将其过滤到我的用户控件中。问题是,向下的用户控制被构建为一个DLL,我不想强迫使用它的应用程序必须实现监听Ctrl + C,这是它应该自己处理的事情。

为什么上面的链接对我不起作用

1)我没有KeyPreview属性设置为true在我的UserControl。关于这个问题的第二个答案建议重写ProcessCmdKey,我这样做了,但是无论我怎么尝试都不会调用回调。

2)这个也建议重写ProcessCmdKey。如我所说,它永远不会被调用。

3)没有接受按钮让我设置为true。

4) KeyDownPreviewKeyDown回调都实现了,但都没有被调用。

5)也建议ProcessCmdKey。

如何检测用户控制级别的关键事件而不考虑焦点?或者,如果我尝试的上述方法应该工作,我错过了什么设置阻止它工作?

winforms UserControl不检测按键

OP:我特别听Ctrl + C,我需要一个方法,可以无论哪个孩子有焦点,都要回应。

如果你想处理一个键组合,如Ctrl+C从你的控件,即使它没有焦点或它是不可选择的,你可以添加一个不可见的MenuStrip到你的用户控件,并添加一个项目,并分配快捷方式给它。然后处理点击事件的项目和做你需要的。

每次用户按Ctrl+C时,即使控件不包含焦点,也会引发单击事件。

你也可以这样做:

public UserControl1()
{
    InitializeComponent();
    var menu = new MenuStrip();
    var item = new ToolStripMenuItem();
    item.ShortcutKeys = System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.C;
    item.Click += item_Click;
    menu.Items.Add(item);
    menu.Visible = false;
    this.Controls.Add(menu);
}
void item_Click(object sender, EventArgs e)
{
    MessageBox.Show("Ctrl + C");
}

注意

你不能在没有焦点的情况下处理键事件,但是使用MenuStrip,你可以使用上述方法捕获你想要的快捷键。

使其工作的原因是,FormContainerControlContainerControl调用ProcessCmdKey中的ToolStripManager.ProcessCmdKey方法,导致ToolStripManager的所有非上下文菜单条的处理快捷方式。
更多信息请看ContainerControl.ProcessCmdKey的源代码

在具有焦点的控件上触发击键事件。您选择的控件不喜欢获得焦点,不显示焦点,并且对击键本身没有用处。这就引出了一个问题,你的应用程序的用户怎么可能知道 Ctrl+C要做什么。

我假设Ctrl+C应该复制图片框中的图像到剪贴板。所以最好的办法是从PB派生你自己的类并修改它,这样它就可以被选择并显示焦点。向项目添加一个新类,并粘贴如下所示的代码。编译。从工具箱的顶部拖动它,替换用户控件中的PB。

using System;
using System.Windows.Forms;
using System.Drawing;
class SelectablePictureBox : PictureBox {
    public SelectablePictureBox() {
        this.SetStyle(ControlStyles.Selectable, true);
        this.TabStop = true;
    }
    protected override void OnMouseDown(MouseEventArgs e) {
        if (e.Button == MouseButtons.Left) this.Focus();
        base.OnMouseDown(e);
    }
    protected override void OnEnter(EventArgs e) {
        this.Invalidate();
        base.OnEnter(e);
    }
    protected override void OnLeave(EventArgs e) {
        this.Invalidate();
        base.OnLeave(e);
    }
    protected override void OnPaint(PaintEventArgs e) {
        base.OnPaint(e);
        if (this.Focused) {
            var rc = this.DisplayRectangle;
            rc.Inflate(new Size(-2, -2));
            ControlPaint.DrawFocusRectangle(e.Graphics, rc);
        }
    }
}