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) KeyDown
和PreviewKeyDown
回调都实现了,但都没有被调用。
5)也建议ProcessCmdKey。
如何检测用户控制级别的关键事件而不考虑焦点?或者,如果我尝试的上述方法应该工作,我错过了什么设置阻止它工作?
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
,你可以使用上述方法捕获你想要的快捷键。
使其工作的原因是,Form
是ContainerControl
和ContainerControl
调用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);
}
}
}