如何处理Arrow KeyPressEvent [英] How to handle Arrow KeyPressEvent

查看:104
本文介绍了如何处理Arrow KeyPressEvent的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

大家好。

我的应用程序是VS 2005上的C#。我创建了一个小程序,仅用两个按钮进行测试。我需要在键盘上的箭头键上处理KeyPress事件(左,右,上,下),但是当我按下这个按钮时,应用程序只会改变按钮的焦点。

我想处理这个事件,当按住这些按钮来改变它时组件上的位置(例如)不要改变它们的焦点。如何解决问题?



提前谢谢。

解决方案

编辑... 10月14日...



我编写此回复后,我在C#论坛上发布了代码,处理箭头键,将Control保持在特定ContainerControl的边框内:[ ^ ]



...结束编辑...



它是如果单击一个按钮(或者,按下按钮时是什么意思?),我不清楚你想要移动以响应箭头键事件,但你的代码处理箭头键事件必须知道哪个控制表格移动。



如果你为Button定义一个KeyDown EventHandler,它只会在按下一个修饰键(如< Control>)时处理箭头键。 KeyPress EventHandler不会处理箭头键事件。



要在没有修改键的情况下获取WinForms中的箭头键事件,你需要使用一个ProcessCmdKey方法的-ride,它将作为一个整体应用于Form。或者,您可以使用PInvoke和Windows API将这些关键事件放在较低级别。



使用Button作为接收器的想法对于关键事件非常不寻常,我认为这不是一个好的设计决定。



这是一个解决方案的想法,它可以移动任何具有Focus的Form上的Control,但是它需要一个修饰键,如< Control>坚持工作。



1.将设计时属性网格中Form的'KeyPreview属性设置为'true。



2.写一个KeyDown事件处理程序:

  private   void  FormTemplate_KeyDown( object  sender,KeyEventArgs e)
{
// 如果我们不过滤掉< control>的重复次数密钥
// 当密钥被按下时会有大量的密钥
if (e.KeyCode == Keys.Control) return ;

控制controlToMove = ActiveControl;

// 用于测试:需要一个TextBox,'frm上的textBox1
// textBox1.Text + =
// ActiveControl:+ controlToMove.Name
// +KeyCode:+ e.KeyCode.ToString()
// < span class =code-comment> +KeyData:+ e.KeyData.ToString()
// +KeyValue:+ e.KeyValue.ToString()
// + Environment.NewLine;

switch (e.KeyCode)
{
< span class =code-keyword> case Keys.Left:
controlT oMove.Left - = 1 ;
break ;
case Keys.Right:
controlToMove.Left + = 1 ;
break ;
case Keys.Up:
controlToMove.Top - = 1 ;
break ;
case Keys.Down:
controlToMove.Top + = 1 ;
break ;
}
} < / control >

现在,如果您使用此功能,您可能会感到惊讶:可能最需要移动的表单上的某些控件是容器控件,如Panels。 Panel永远不会成为Form上的ActiveControl。



所以,如果你想让这个解决方案更强大,并处理像Panel这样的东西,你就是将不得不想办法让Form scoped KeyDown EventHandler知道它需要移动哪个Panel或其他Container Control。



你可能会认为你可以简单地使用表格的'GetChildAtPoint方法:

 Control controlToMove; 

private void FormTemplate_KeyDown(对象 sender,KeyEventArgs e)
{
if (e.KeyCode == Keys.Control || ActiveControl == null return ;

controlToMove = this .GetChildAtPoint( this .PointToClient(MousePosition));

if (controlToMove == null 返回;

switch (e.KeyCode)
{
case Keys.Left:
controlToMove.Left - = 1 ;
break ;
case Keys.Right:
controlToMove.Left + = 1 ;
break ;
case Keys.Up:
controlToMove.Top - = 1 ;
break ;
case Keys.Down:
controlToMove.Top + = 1 ;
break ;
}
}

好了,现在你可以移动面板了,但是还有另外一个问题:你点击并选择的面板内的控件不会移动,但是它们包含的面板会。这是'GetChildAtPoint工作方式的工件(或者,从我的角度看,不起作用)。



所以,真正让它变得健壮解决方案,您需要找到一种方法来获取任何控件或容器控件内任意数量的容器控件,设置为窗体范围箭头键EventHandler的目标。



解决这个问题的一种便宜方法是:在设计时选择表单上的所有控件,并定义他们共享的Click EventHandler:

  private   void  AllControls_Click( object  sender,EventArgs e)
{
controlToMove = sender as Control;
}

并且,确保点击表单重置箭头键事件处理:

  private   void  SomeForm_Click( object  sender,EventArgs e)
{
controlToMove = null ;
}

。嗯,便宜并不等于优雅,但是,它有效。



现在,在这之后,问题仍然存在于我的脑海中:是真的吗?一个好东西以这种方式运行控件的运行时间。我的直觉说:不,除非是一些非常特殊的情况。 imho,这里展示的是太多的工作:)



毕竟还有其他标准方法可以让控件在运行时移动,通过MouseDown,MouseMove ,MouseUp;您甚至可以在运行时设置PropertyGrid控件并让用户编辑控件的像素位置。



您需要多久移动一次在运行时对表单上的每个控件?


查看此处发布的类似问题。该主题包含几个有用的提示:捕获所有键盘键,包括 [< a href =http://www.codeproject.com/Answers/646326/capture-all-keyboard-key-including#answer3target =_ blanktitle =New Window> ^ ]。

Hello everybody.
My application is a C# on VS 2005.I creat a small program for a test only with two buttons.I need to handle "KeyPress Event" on arrow keys on keyboard(left,right,up,down),but when I press this buttons application only change the focus of the buttons.
I want to handle this event and when press and hold some of this buttons to change the location on the component (for example) not to change the focus of them.How to solve the problem?

Thanks in advance.

解决方案

edit ... October 14 ...

Code I posted on the C# forum after I wrote this response that will allow you to handle arrow-keys, keeping a Control inside the borders of a specific ContainerControl: [^]

... end edit ...

It is not clear to me exactly what you wish to move in response to arrow-key Events if a Button has been clicked (or, did you mean while a Button is pressed ?), but your code to handle arrow-key Events has to know which Control on the Form to move.

If you define a KeyDown EventHandler for a Button, it will only handle arrow-keys if a modifier key, like <Control>, is held down. A KeyPress EventHandler will not handle arrow-key events.

To get arrow-key Events in WinForms without a modifier key held down, you'll need to use an over-ride of the ProcessCmdKey method, and that will apply to the Form as a whole. Or, you can get into using PInvoke and the Windows API to get those key Events at a "lower level."

The idea of using a Button as the "sink" for key Events is very unusual, and I think not a good design decision.

Here's a solution idea which could move any Control on the Form that has Focus, but it does require a modifier key, like <Control> held down to work.

1. set the 'KeyPreview property of the Form in the design-time Property Grid to 'true.

2. write a KeyDown Event Handler:

private void FormTemplate_KeyDown(object sender, KeyEventArgs e)
{
    // if we don't filter out repeats of the <control> Key 
    // there will be a flood of them while the key is held down
    if (e.KeyCode == Keys.Control) return;

    Control controlToMove = ActiveControl;

    // use for testing: requires a TextBox, 'textBox1 on the Frm
    //textBox1.Text +=
        //"ActiveControl: " + controlToMove.Name
        //+ " KeyCode: " + e.KeyCode.ToString()
        //+ " KeyData: " + e.KeyData.ToString()
        //+ " KeyValue: " + e.KeyValue.ToString()
        //+ Environment.NewLine;

    switch (e.KeyCode)
    {
        case Keys.Left:
            controlToMove.Left -= 1;
            break;
        case Keys.Right:
            controlToMove.Left += 1;
            break;
        case Keys.Up:
            controlToMove.Top -= 1;
            break;
        case Keys.Down:
            controlToMove.Top += 1;
            break;
    }
}</control>

Now, if you use this you may be surprised: some of the Controls on a Form that it might be most desirable to move are Container Controls, like Panels. A Panel never becomes the ActiveControl on a Form.

So, if you want to make this solution more "robust," and handle moving something like a Panel, you are going to have to come up with a way for the Form scoped KeyDown EventHandler to "know" which Panel, or other Container Control, it needs to move.

You might think you can simply use the 'GetChildAtPoint method of the Form:

Control controlToMove;

private void FormTemplate_KeyDown(object sender, KeyEventArgs e)
{
    if (e.KeyCode == Keys.Control || ActiveControl == null) return;

    controlToMove = this.GetChildAtPoint(this.PointToClient(MousePosition));

    if (controlToMove == null) return;

    switch (e.KeyCode)
    {
        case Keys.Left:
            controlToMove.Left -= 1;
            break;
        case Keys.Right:
            controlToMove.Left += 1;
            break;
        case Keys.Up:
            controlToMove.Top -= 1;
            break;
        case Keys.Down:
            controlToMove.Top += 1;
            break;
    }
}

Well, now you can move Panels, but you have another problem: Controls inside Panels that you click on and select will not move, but their containing Panel will. This is an artifact of the way that 'GetChildAtPoint works (or, from my point of view, doesn't work).

So, to really make this a robust solution, you need to find a way to get any Control or Container Control inside any arbitrary number of Container Controls set as the "target" of your Form scoped arrow-key EventHandler.

A cheap way to get around this is: at design-time is to select all Controls on the Form, and define a Click EventHandler they all share:

private void AllControls_Click(object sender, EventArgs e)
{
    controlToMove = sender as Control;
}

And, make sure that a click on the Form "resets" arrow-key event handling:

private void SomeForm_Click(object sender, EventArgs e)
{
    controlToMove = null;
}

. Well, "cheap" does not equal "elegant," but, it works.

And now, after all this, the question remains in my mind: is it really a good thing to have run-time moving of Controls in this way. My "gut" says: "no," unless it's some very special circumstance. imho, what's demonstrated here is too much work :)

There are, after all, other standard ways of enabling Controls to move at run-time, via MouseDown, MouseMove, MouseUp; you can even put up a PropertyGrid Control at run-time and let the user edit the pixel locations of Controls.

How often do you really need to move every Control on a Form at run-time ?


Take a look at similar questions posted here. This thread contains several useful tips: capture all keyboard key including[^].


这篇关于如何处理Arrow KeyPressEvent的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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