Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/21.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
.net 在UserControl中捕获KeyDown事件_.net_Winforms_C# 2.0 - Fatal编程技术网

.net 在UserControl中捕获KeyDown事件

.net 在UserControl中捕获KeyDown事件,.net,winforms,c#-2.0,.net,Winforms,C# 2.0,我有一个用户控件和几个子控件。我需要用户界面对按键做出反应,所以我决定将处理代码放入MainControl\u KeyDown事件中。但是,当我按下应用程序中的某个键时,此事件不会触发 我已经通过一个依赖于使用Windows API的搜索引擎找到了一个解决方案,我希望避免这种情况,因为对于一个应该由.NET framework正确支持的函数来说,这似乎有些过分。也许您应该在本地处理所有事件,然后触发虚拟事件以与主控件通信 或者这可能是一个焦点问题;如果有许多子控件,并且其中只有一个是焦点,那么其

我有一个用户控件和几个子控件。我需要用户界面对按键做出反应,所以我决定将处理代码放入MainControl\u KeyDown事件中。但是,当我按下应用程序中的某个键时,此事件不会触发


我已经通过一个依赖于使用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 mad
UcSub1
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)
    {
        ...
    }
}