关于不包含keypreview属性的usercontrol的问题 [英] A question about usercontrol that not contains keypreview attribute

查看:316
本文介绍了关于不包含keypreview属性的usercontrol的问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

UserControl不像Form组件包含keypreview属性,所以我如何使用keydown或keypress事件如form组件,我的困惑是焦点必须在其中一个组件中,因为usercontrol没有keypreview属性。

所以我怎么能解决这个问题,谢谢你的回答。



我试过的:



a部分我尝试过的代码如下:

private void tabControlAutomaticManual_ParentChanged(object sender,EventArgs e)

{

if(TopLevelControl是Form)

{

(TopLevelControl as Form).KeyPreview = true;

TopLevelControl。 KeyDown + = new KeyEventHandler(TopLevelControl_KeyDown);

TopLevelControl.KeyUp + = new KeyEventHandler(TopLevelControl_KeyUp);

}

}



void TopLevelControl_Ke yUp(对象发件人,KeyEventArgs e)

{



}



void TopLevelControl_KeyDown(object sender,KeyEventArgs e)

{



}

解决方案

< blockquote>注意:CodeProject中描述了使用Win API函数的方法:[ ^ ]。我不想使用这种依赖API的方法,除非有没有替代方法。



首先,UserControl按照设计是光重量其他控件的容器;使它变轻的一部分原因是它的消息泵没有获得关键事件......即使它确实在设计时暴露了属性浏览器中的关键事件(错误,imho)。 />


UserControl期望在其上放置控件...如果不包含控件,为什么还要使用它?其中一个包含的控件将(很可能)具有焦点,并将获得关键事件。默认情况下获取关键事件的UserControl中的Control可能是具有最低'TabOrder值的那个。



所以,让我们把重点改为获取关键事件对于UserControl中包含的所有控件。示例:

  //  在UserControl的主体中 
public Func< string,Keys,bool> KBNotification { set ; get ; }

private void UserControl1_Load( object sender,EventArgs e)
{
foreach (控制控件 in ControlUtilities.GetAllControls( this ))
{
control.KeyDown + = ControlKeyDown;
}
}

私有 void ControlKeyDown( object sender,KeyEventArgs e)
{
if (KBNotification!= null
{
e.SuppressKeyPress = KBNotification((sender as Control).Name ,e.KeyCode);
}
}

// 一个单独的类
// 控制实用程序功能
public static class ControlUtilities
{
public static IEnumerable< Control> GetAllControls(控制aControl)
{
Stack< Control> stack = new Stack< Control>();

stack.Push(aControl);

while (stack.Any())
{
var nextControl = stack.Pop();

foreach (控制childControl nextControl.Controls)
{
stack.Push(childControl);
}

yield return nextControl;
}
}
}

这里发生了什么:



1.我们创建一个代表(使用Func语法将采用两个参数,一个Control名称和一个Keys Enumeration值,并返回一个布尔值。



2.我们连接一个KeyDown UserControl中所有控件的EventHandler,用于测试是否定义了Delegate,如果已定义,则使用所需参数调用它。



3.如果代理人被调用,并返回'true,将阻止KeyDown事件到达获得KeyDown的Control;如果Delegate返回false,则将KeyDown传递给Control,并以通常的方式处理。



使用示例:在托管实例的表单中UserControl:

  private   void  Form1_Load( object  sender,EventArgs e)
{
userControl11.KBNotification = UCKbNotification;
}

private bool UCKbNotification( string s,Keys键)
{
if (s == textBox1 return ;
}

这里,如果在UserControl中名为'textBox1的TextBox获得KeyDown,'将返回false,并且KeyDown被抑制。



但是,虽然我们可以使用它来修改某些ContainerControl中每个Control的行为,但请考虑这个:



1.在实际的基础上,大多数在这种情况下,您不需要在ContainerControl中的每个Control上进行关键事件拦截,但仅限于某些控件。



所以,为什么不简化这个,只需定义。 ..在ContainerControl ...你做的控件想要安装密钥拦截:

  public  List< Control> ; ControlsToGetKeyDown; 

public Func< string,Keys,bool> KBNotification { set ; get ; }

private void UserControl1_Load( object sender,EventArgs e)
{
ControlsToGetKeyDown = new List< Control>
{
textBox1,panel1.Controls [ richTextBox1]
};

foreach (控制控件 ControlsToGetKeyDown)
{
control.KeyDown + = ControlKeyDown;
}
}


而不是这个属性,有一个虚方法 System.Windows.Forms。 Controls.ProcessKeyPreview

Control.ProcessKeyPreview方法(消息)(System.Windows.Forms) [ ^ ]。



处理调用此方法的事件的操作不依赖于父窗体的 KeyPreview 标志;事件总是分派给这个函数。您可以在控件类型中覆盖它(不仅仅是 UserControl )并将处理放入其中。如果返回true,它将停止进一步处理子控件层次结构中的事件。



-SA


The UserControl is not like Form component contains keypreview attribute,so how can i use keydown or keypress event like form component,my confuse is that the focus must be in one of it's component ,because usercontrol doesn't has keypreview attribute.
so how can i solve this question,thanks for answer.

What I have tried:

a part of my tried code as below:
private void tabControlAutomaticManual_ParentChanged(object sender, EventArgs e)
{
if (TopLevelControl is Form)
{
(TopLevelControl as Form).KeyPreview = true;
TopLevelControl.KeyDown += new KeyEventHandler(TopLevelControl_KeyDown);
TopLevelControl.KeyUp += new KeyEventHandler(TopLevelControl_KeyUp);
}
}

void TopLevelControl_KeyUp(object sender, KeyEventArgs e)
{

}

void TopLevelControl_KeyDown(object sender, KeyEventArgs e)
{

}

解决方案

Note: an approach to use using the Win API functions has been described here on CodeProject: [^]. I prefer not to use such API dependent methods unless there is no alternative.

First, a UserControl is, by design, a "light-weight" container for other Controls; part of what makes it "lighter" is that its "message pump" does not get Key Events ... even though it does expose the Key- related Events in the Property Browser at design-time (a mistake, imho).

The UserControl "expects" to have Controls placed on it ... why else use it if not to contain Controls ? One of its contained Controls will (most likely) have focus, and will get Key Events. The Control in the UserControl that gets Key Events by default will probably be the one with the lowest 'TabOrder value.

So, let's change the focus here to getting Key Events for all Controls contained in the UserControl. Example:

// in the body of the UserControl
public Func<string, Keys, bool> KBNotification { set; get; }

private void UserControl1_Load(object sender, EventArgs e)
{
    foreach (Control control in ControlUtilities.GetAllControls(this))
    {
        control.KeyDown += ControlKeyDown;
    }
}

private void ControlKeyDown(object sender, KeyEventArgs e)
{
    if (KBNotification != null)
    {
        e.SuppressKeyPress = KBNotification((sender as Control).Name, e.KeyCode);
    }
}

// a separate Class
// Control Utility Functions
public static class ControlUtilities
{
    public static IEnumerable<Control> GetAllControls(Control aControl)
    {
        Stack<Control> stack = new Stack<Control>();
    
        stack.Push(aControl);
    
        while (stack.Any())
        {
            var nextControl = stack.Pop();
    
            foreach (Control childControl in nextControl.Controls)
            {
                stack.Push(childControl);
            }
    
            yield return nextControl;
        }
    }
}

What's happening here:

1. we create a Delegate (using the 'Func syntax) that will take two parameters, a Control name, and a Keys Enumeration value, and return a boolean.

2. we wire-up a KeyDown EventHandler for all Controls in the UserControl that tests if the Delegate is defined, and, if it is defined, invokes it with the required arguments.

3. if the Delegate is invoked, and returns 'true, the KeyDown Event will be prevented from reaching the Control that got the KeyDown; if the Delegate returns false, the KeyDown is passed to the Control, and handled in the usual way.

Example of use: in a Form that hosts an instance of the UserControl:

private void Form1_Load(object sender, EventArgs e)
{
    userControl11.KBNotification = UCKbNotification;
}

private bool UCKbNotification(string s, Keys keys)
{
    if(s == "textBox1") return true;
}

Here, if the TextBox named 'textBox1 in the UserControl gets a KeyDown, 'false will be returned, and the KeyDown suppressed.

But, while we can use this to modify the behavior of every Control in some ContainerControl, consider this:

1. on a practical basis, in most cases, you will not need key event interception on every Control in your ContainerControl, but, only on certain Controls.

So, why not simplify this, and simply define ... in the ContainerControl ... the Controls you do want key intercept installed:

public List<Control> ControlsToGetKeyDown;

public Func<string, Keys, bool> KBNotification { set; get; }

private void UserControl1_Load(object sender, EventArgs e)
{
    ControlsToGetKeyDown = new List<Control>
    {
       textBox1, panel1.Controls["richTextBox1"]
    };

    foreach (Control control in ControlsToGetKeyDown)
    {
        control.KeyDown += ControlKeyDown;
    }
}


Instead of this property, there is a virtual method System.Windows.Forms.Controls.ProcessKeyPreview:
Control.ProcessKeyPreview Method (Message) (System.Windows.Forms)[^].

The action of handling events which calls this method does not depend on the KeyPreview flag of the parent form; the events are always dispatched to this function. You can override it in your control type (not only UserControl) and put your processing in it. It if returns true, it will stop further handling of the event in the hierarchy of child controls.

—SA


这篇关于关于不包含keypreview属性的usercontrol的问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆