.net 在UserControl中捕获KeyDown事件
我有一个用户控件和几个子控件。我需要用户界面对按键做出反应,所以我决定将处理代码放入MainControl\u KeyDown事件中。但是,当我按下应用程序中的某个键时,此事件不会触发.net 在UserControl中捕获KeyDown事件,.net,winforms,c#-2.0,.net,Winforms,C# 2.0,我有一个用户控件和几个子控件。我需要用户界面对按键做出反应,所以我决定将处理代码放入MainControl\u KeyDown事件中。但是,当我按下应用程序中的某个键时,此事件不会触发 我已经通过一个依赖于使用Windows API的搜索引擎找到了一个解决方案,我希望避免这种情况,因为对于一个应该由.NET framework正确支持的函数来说,这似乎有些过分。也许您应该在本地处理所有事件,然后触发虚拟事件以与主控件通信 或者这可能是一个焦点问题;如果有许多子控件,并且其中只有一个是焦点,那么其
我已经通过一个依赖于使用Windows API的搜索引擎找到了一个解决方案,我希望避免这种情况,因为对于一个应该由.NET framework正确支持的函数来说,这似乎有些过分。也许您应该在本地处理所有事件,然后触发虚拟事件以与主控件通信 或者这可能是一个焦点问题;如果有许多子控件,并且其中只有一个是焦点,那么其他控件将不会对按键按下操作作出反应
也许您可以在这里发布一些代码片段以确保这一点。您可以为用户控件中的每个子控件添加一个KeyDown事件处理程序,并在每个子控件中激发用户控件的KeyDown事件,如下所示:
private void textBox1_KeyDown(object sender, KeyEventArgs e)
{
this.OnKeyDown(e);
}
下面是一个循环抛出表单中的每个控件以附加KeyDown事件的示例。这与本帖前面的答案类似,但处理的案例更多:
using Microsoft.VisualBasic;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Data;
using System.Diagnostics;
public class UserControlKeyboardProcessor
{
private void Control_KeyDown(object sender, System.Windows.Forms.KeyEventArgs e)
{
base.OnKeyDown(e);
}
private void UserControlKeyboardProcessor_Disposed(object sender, System.EventArgs e)
{
foreach (System.Windows.Forms.Control control in this.GetAllControls(this)) {
control.KeyDown -= Control_KeyDown;
}
}
private void UserControlKeyboardProcessor_Load(object sender, System.EventArgs e)
{
foreach (System.Windows.Forms.Control control in this.GetAllControls(this)) {
control.KeyDown += Control_KeyDown;
}
}
public Generic.List<System.Windows.Forms.Control> GetAllControls(System.Windows.Forms.Control control)
{
Generic.List<System.Windows.Forms.Control> controls = new Generic.List<System.Windows.Forms.Control>();
foreach (System.Windows.Forms.Control subControl in control.Controls) {
controls.Add(subControl);
controls.AddRange(this.GetAllControls(subControl));
}
return controls;
}
public UserControlKeyboardProcessor()
{
Load += UserControlKeyboardProcessor_Load;
Disposed += UserControlKeyboardProcessor_Disposed;
}
}
使用Microsoft.VisualBasic;
使用制度;
使用系统集合;
使用System.Collections.Generic;
使用系统数据;
使用系统诊断;
公共类UserControlKeyboardProcessor
{
私有无效控件\u KeyDown(对象发送方,System.Windows.Forms.KeyEventArgs e)
{
base.OnKeyDown(e);
}
私有void UserControlKeyboardProcessor_已处置(对象发送方,System.EventArgs e)
{
foreach(this.GetAllControls(this))中的System.Windows.Forms.Control控件){
control.KeyDown-=control\u KeyDown;
}
}
私有void UserControlKeyboardProcessor_加载(对象发送方,System.EventArgs e)
{
foreach(this.GetAllControls(this))中的System.Windows.Forms.Control控件){
control.KeyDown+=control_KeyDown;
}
}
公共泛型.List GetAllControls(System.Windows.Forms.Control)
{
Generic.List控件=新建Generic.List();
foreach(Control.Controls中的System.Windows.Forms.Control子控件){
控制。添加(分包控制);
controls.AddRange(this.GetAllControls(subcrol));
}
返回控制;
}
公共用户控制键盘处理器()
{
Load+=用户控制键盘处理器\u Load;
Disposed+=UserControlKeyboardProcessor\u Disposed;
}
}
我知道这个线程有点旧,但我遇到了类似的问题,并以不同的方式处理:在主窗口中,我将KeyPreview属性更改为true。 我在用户控件中注册了主窗口的KeyDown事件处理程序
this.Parent.KeyDown += new KeyEventHandler(MyControl_KeyDown);
这会阻止我将每个子控件的KeyDown事件路由到我的用户控件。当然,在卸载用户控件时删除事件处理程序很重要
this.Parent.KeyDown += new KeyEventHandler(MyControl_KeyDown);
我希望这能帮助现在面临类似问题的人。我有一个窍门
UcBase
继承自UserControl
UcSub1
和UcSub2
继承自UcBase
。
UcSuperClass
也继承自UcBase
UcSub1
,UcSub2
在UcSuperClass
中使用
I madUcSub1
和UcSub2
调用ProcessCmdKey
代码:
public class UcBase : UserControl
{
public delegate bool ProcessCmdKeyHandler(Keys keyData);
public ProcessCmdKeyHandler KeyHandler;
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
KeyHandler += ProcessKey;
if (Parent != null)
{
var parent = GetParentControl<UcBase>(Parent);
if (parent != null)
{
parent.KeyHandler += ProcessKey;
}
}
}
protected virtual bool ProcessKey(Keys keyData)
{
return false;
}
protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
{
const int WM_KEYDOWN = 0x100;
const int WM_SYSKEYDOWN = 0x104;
if (KeyHandler != null
&& (msg.Msg == WM_KEYDOWN) || (msg.Msg == WM_SYSKEYDOWN))
{
if (KeyHandler(keyData) == true)
{
return true;
}
}
return base.ProcessCmdKey(ref msg, keyData);
}
private T GetParentControl<T>(Control control)
where T : Control
{
T parentControl = default(T);
var queue = new Queue<Control>();
var targetControlType = typeof(T);
queue.Enqueue(control.Parent);
while (queue.Count > 0)
{
var parent = queue.Dequeue();
if (parent != null)
{
if (parent.GetType().BaseType == targetControlType)
{
parentControl = (T)parent;
break;
}
else
{
queue.Enqueue(parent.Parent);
}
}
else
{
break;
}
}
return parentControl;
}
}
public class UcSub1 : UcBase
{
protected override bool ProcessKey(Keys keyData)
{
// if you process do something, and return true then UcBase.ProcessCmdKey pass by.
return false;
}
}
public class UcSub2 : UcBase
{
protected override bool ProcessKey(Keys keyData)
{
// if you process do something, and return true then UcBase.ProcessCmdKey pass by.
return false;
}
}
public class UcSuperClass : UcBase
{
private UcSub1 _ucSub1;
private UcSub2 _ucSub2;
public UcSuperClass()
{
_ucSub1 = new UcSub1();
_ucSub2 = new UcSub2();
}
protected override bool ProcessKey(Keys keyData)
{
// if you process do something, and return true then UcBase.ProcessCmdKey pass by.
return false;
}
}
公共类UcBase:UserControl
{
公共委托bool processcmdkeydhandler(Keys keyData);
public-ProcessCmdKeyHandler-KeyHandler;
受保护的覆盖无效加载(事件参数e)
{
基础荷载(e);
KeyHandler+=ProcessKey;
如果(父项!=null)
{
var parent=GetParentControl(父级);
如果(父项!=null)
{
parent.KeyHandler+=ProcessKey;
}
}
}
受保护的虚拟bool进程密钥(密钥keyData)
{
返回false;
}
受保护的覆盖bool ProcessCmdKey(参考消息消息消息,Keys keyData)
{
常量int WM_KEYDOWN=0x100;
常量int WM_SYSKEYDOWN=0x104;
if(KeyHandler!=null
&&(msg.msg==WM_KEYDOWN)| |(msg.msg==WM_SYSKEYDOWN))
{
if(KeyHandler(keyData)==true)
{
返回true;
}
}
返回base.ProcessCmdKey(ref msg,keyData);
}
私有T GetParentControl(控件)
其中T:控制
{
T parentControl=默认值(T);
var queue=新队列();
var targetControlType=类型(T);
queue.Enqueue(control.Parent);
而(queue.Count>0)
{
var parent=queue.Dequeue();
如果(父项!=null)
{
if(parent.GetType().BaseType==targetControlType)
{
parentControl=(T)parent;
打破
}
其他的
{
queue.Enqueue(parent.parent);
}
}
其他的
{
打破
}
}
返回控制;
}
}
公共类UcSub1:UcBase
{
受保护的覆盖布尔进程键(键keyData)
{
//如果进程执行某些操作,并返回true,则UcBase.ProcessCmdKey将被忽略。
返回false;
}
}
公共类UcSub2:UcBase
{
受保护的覆盖布尔进程键(键keyData)
{
//如果进程执行某些操作,并返回true,则UcBase.ProcessCmdKey将被忽略。
返回false;
}
}
公共类UC超类:UcBase
{
私人UcSub1 UcSub1;
私有UcSub2 UcSub2;
公共超类()
{
_ucSub1=新的ucSub1();
_ucSub2=新的ucSub2();
}
受保护的覆盖布尔进程键(键keyData)
{
//如果您处理dose,并返回true,那么UcBase.Proces
protected override void OnPreviewKeyDown(KeyEventArgs e)
{
base.OnPreviewKeyDown(e);
if(e.Key == Key.Escape || e.SystemKey == Key.F10)
{
...
}
}