彩票走势图

如何让ToolBox控件响应键盘操作

转帖|其它|编辑:郝浩|2010-12-01 16:05:21.000|阅读 650 次

概述:本问主要介绍如何让ToolBox控件响应键盘操作,希望对大家有帮助。

# 慧都年终大促·界面/图表报表/文档/IDE等千款热门软控件火热促销中 >>

  最近,一朋友问我如何让ToolBox控件也能响应键盘操作,也就是用Up,down按键来选择工具箱控件里的Item,他添加了键盘事件,但是不起作用。一开始做这个控件的时候也只是演示一下控件的制作过程,只用了很短的时间做了一个,只考虑了用鼠标选取,没有考虑键盘操作,我想要添加键盘操作无非重载KeyDown事件,针对Up,Down做一些响应就可以了。可是添加了重载了OnKeyDown事件后,结果和那位朋友所说的一样,没有任何作用,我设了断点,调试了一下,发现KeyDown根本捕获不到Up,Down按键的点击,是什么原因呢,是不是忘记设控件的风格以便让它能够获得焦点?于是,我使用了语句:

  SetStyle(ControlStyles.Selectable, true);

  依然没有效果,当我们在控件上按下Down键的时候,另一个控件获得了焦点。这时Up,Down按钮只是起到了导航的作用就像Tab键一样。

  接下来,我在测试工程的窗体上放置了一个ListBox控件做一个对比,其实ToolBox和ListBox在界面表现上有相似之处,就是都有子Item,并且在ListBox上点击Down是起作用的,ListBox并没有失去焦点,这说明这时Up,Down按键没有成为导航键。我想Windows一定是对默认的导航键Up,Down,Left,Right有默认的处理,除非你希望你的控件希望自己处理这些键。用反汇编工具看了一下ListBoxControl控件的源代码,发现一个有趣的函数:

  protected override bool IsInputKey(Keys keyData)
{
if ((keyData & Keys.Alt) == Keys.Alt)
{
return false;
}
switch ((keyData & Keys.KeyCode))
{
case Keys.Prior:
case Keys.Next:
case Keys.End:
case Keys.Home:
return true;
}
return base.IsInputKey(keyData);
}

  在这里面,ListBoxControl允许Prior,Next,End,Home成为有效的输入键,接着一路跟下去,看看winform控件的基类Control的这个函数是如何处理的:

  [UIPermission(SecurityAction.InheritanceDemand, Window=UIPermissionWindow.AllWindows)]
protected virtual bool IsInputKey(Keys keyData)
{
if ((keyData & Keys.Alt) != Keys.Alt)
{
int num = 4;
switch ((keyData & Keys.KeyCode))
{
case Keys.Left:
case Keys.Up:
case Keys.Right:
case Keys.Down:
num = 5;
break;

   case Keys.Tab:
num = 6;
break;
}
if (this.IsHandleCreated)
{
return ((((int) this.SendMessage(0x87, 0, 0)) & num) != 0);
}
}
return false;
}

  注意这一行return ((((int) this.SendMessage(0x87, 0, 0)) & num) != 0);0x87是什么windows消息呢,打开WinUser.h文件,发现是WM_GETDLGCODE,在MSDN中的描述是这样的:

  The WM_GETDLGCODE message is sent to the window procedure associated with a control. By default, the system handles all keyboard input to the control; the system interprets certain types of keyboard input as dialog box navigation keys. To override this default behavior, the control can respond to the WM_GETDLGCODE message to indicate the types of input it wants to process itself.

  也就是说windows用这个消息来判断哪些类型的输入交给控件本身来处理。然后,我注意到,对于方向导航键,函数都给于一个值5与this.SendMessage(0x87, 0, 0))的返回值进行与操作,那么this.SendMessage(0x87, 0, 0))的返回值都可能是什么值呢,WinUser.h中是这样声明的:

  /*
* Dialog Codes
*/
#define DLGC_WANTARROWS 0x0001 /* Control wants arrow keys */
#define DLGC_WANTTAB 0x0002 /* Control wants tab keys */
#define DLGC_WANTALLKEYS 0x0004 /* Control wants all keys */
#define DLGC_WANTMESSAGE 0x0004 /* Pass message to control */
#define DLGC_HASSETSEL 0x0008 /* Understands EM_SETSEL message */
#define DLGC_DEFPUSHBUTTON 0x0010 /* Default pushbutton */
#define DLGC_UNDEFPUSHBUTTON 0x0020 /* Non-default pushbutton */
#define DLGC_RADIOBUTTON 0x0040 /* Radio button */
#define DLGC_WANTCHARS 0x0080 /* Want WM_CHAR messages */
#define DLGC_STATIC 0x0100 /* Static item: don't include */
#define DLGC_BUTTON 0x2000 /* Button item: can be checked */

   5最贴切的表达就是DLGC_WANTMESSAGE | DLGC_WANTARROWS,也就是将方向键发送给控件处理,对于6呢,也就是DLGC_WANTMESSAGE| DLGC_WANTTAB,将Tab键发送给控件处理。

  从这段代码里和控件实际的行为我们可以得出一个结论,那就是,控件本身是不处理方向键和Tab键的,因为他们有默认的行为,也就是支持焦点在窗体的控件之间转换。如果你想要处理这些导航键,那么结论很简单,就是重载IsInputKey方法,它是一个保护类型的虚方法。

   在ToolBox控件的代码里重载IsinputKey方法:

   protected override bool IsInputKey(Keys keyData)
{
if ((keyData & Keys.Alt) == Keys.Alt)
{
return false;
}
switch ((keyData & Keys.KeyCode))
{
case Keys.Up:
case Keys.Down:
return true;
}
return base.IsInputKey(keyData);

   }

当用户点击的键是Up,Down的时候,返回true,这时我们的OnKeyDown方法里就可以捕获到Up,Down的点击事件了。
 


标签:

本站文章除注明转载外,均为本站原创或翻译。欢迎任何形式的转载,但请务必注明出处、不得修改原文相关链接,如果存在内容上的异议请邮件反馈至chenjj@pclwef.cn

文章转载自:博客转载

为你推荐

  • 推荐视频
  • 推荐活动
  • 推荐产品
  • 推荐文章
  • 慧都慧问
扫码咨询


添加微信 立即咨询

电话咨询

客服热线
023-68661681

TOP