最近一个朋友要做一个操作非常方便的Windows应用程序,就是希望通过按回车键或者上下键,在输入项之间自动跳转,国人都不习惯
使用Tab/Shift Tab在输入项之间的跳转。我之前也使用了一些别的方法,如:首先将需要跳转的输入项放置到一个集合对象ArrayList里;
然后设置Form的PreKeyView为True;最后 给Form添加一个KeyDown事件处理程序。虽然是一个办法。但总觉得不够专业。
前不久在WWW.CodeProject.COM看了一个老外写的一篇文章http://www.codeproject.com/cs/menu/menuimage.asp,是关于如何做一个带
图标的菜单的,大部分人写这样的程序都是重写MenuItem,重载MenuItme的OnDrawItem和OnMeasureItme方法,可是这位老大独树一帜,
去做了一个叫MenuImage的类,它实现了System.ComponentModel.IExtenderProvider 接口,在设计期给MenuItem扩展了一个属性
MenuImage。如下图:
这篇文章给了我极大的启发,决定做一个给所有的Control“扩展” 两个属性NextControl和PreviousControl,这样按回车或者上下键就可以跳转了。
首先创建一个类ControlFocus
[ProvideProperty( "NextControl", typeof(Component)) ]
[ProvideProperty( "PreviousControl", typeof(Component)) ]
public class ControlFocus:Component, IExtenderProvider
第一行和第二行是什么意思呢,就是这个ExtenderProvider会给别的Control扩展两个属性NextControl和PreviousControl
同时要求在ControlFocus类里面包含下面四个方法:
GetNextControl/SetNextControl/GetPreviousControl/SetPreviousControl
另外ControlFocus这个ExtenderProvider必须实现IExtenderProvider的CanExtend方法。
下面就是ControlFocus类的全部源代码:
1using System ;
2using System.ComponentModel ;
3using System.Collections ;
4using System.Diagnostics ;
5using System.Windows.Forms ;
6using System.Drawing ;
7using System.Drawing.Drawing2D ;
8
9namespace Shark
10{
11
12 [ProvideProperty( "NextControl", typeof(Component)) ]
13 [ProvideProperty( "PreviousControl", typeof(Component)) ]
14 public class ControlFocus:Component, IExtenderProvider
15 {
16 public ControlFocus()
17 {
18 //
19 // TODO: Add constructor logic here
20 //
21 }
22 Hashtable _hashTable = new Hashtable();
23 Hashtable _previousHashTable = new Hashtable();
24
25 public Keys NextK;
26 public Keys PreviousK;
27
28 public void SetNextControl(Component component,Control c)
29 {
30 if ( _hashTable.Contains( component ) != true)
31 {
32 //MessageBox.Show(component.ToString());
33 _hashTable.Add(component,c);
34 Control currentC = (Control)component;
35 currentC.KeyDown +=new KeyEventHandler(currentC_KeyDown);
36 }
37 else
38 {
39 _hashTable[component] = c;
40 }
41 }
42 public Control GetNextControl(Component component)
43 {
44 if( _hashTable.Contains( component ))
45 {
46 return (Control)_hashTable[ component ];
47 }
48 return null;
49 }
50
51
52 public void SetPreviousControl(Component component,Control c)
53 {
54 if ( _previousHashTable.Contains( component ) != true)
55 {
56 //MessageBox.Show(component.ToString());
57 _previousHashTable.Add(component,c);
58 Control currentC = (Control)component;
59 currentC.KeyDown +=new KeyEventHandler(currentC_KeyDown);
60 }
61 else
62 {
63 _previousHashTable[component] = c;
64 }
65 }
66
67 public Control GetPreviousControl(Component component)
68 {
69 if( _previousHashTable.Contains( component ))
70 {
71 return (Control)_previousHashTable[ component ];
72 }
73 return null;
74 }
75
76 /**//// <summary>
77 /// Used to retrieve the MenuImage extender property value
78 /// for a given <c>MenuItem</c> component instance.
79 /// </summary>
80 /// <param name="component">the menu item instance associated with the value</param>
81 /// <returns>Returns the MenuImage index property value for the specified <c>MenuItem</c> component instance.</returns>
82 public string GetControlFocus( Component component )
83 {
84 if( _hashTable.Contains( component ))
85 return (string) _hashTable[ component ] ;
86
87 return null;
88 }
89
90 public ControlFocus(System.ComponentModel.IContainer container)
91 {
92 container.Add(this);
93 }
94 public bool CanExtend( object component )
95 {
96 // only support MenuItem objects that are not
97 // top-level menus (default rendering for top-level
98 // menus is fine - does not need extension
99 if ( component is Control && !(component is Form))
100 {
101 return true;
102 }
103
104 return false ;
105 }
106
107
108 private void currentC_KeyDown(object sender, KeyEventArgs e)
109 {
110 if(e.KeyCode == this.NextK)
111 {
112 Control nextControl = this.GetNextControl( (Component)sender);
113 if(nextControl != null && nextControl.CanFocus)
114 nextControl.Focus();
115 }
116 else if(e.KeyCode == this.PreviousK)
117 {
118 Control previousControl = this.GetPreviousControl( (Component)sender);
119 if(previousControl != null && previousControl.CanFocus)
120 previousControl.Focus();
121 }
122 }
123
124
125 }
126}
127
其次创建一个示例窗口.如下:
程序的全部源代码,请下载: