键盘事件有三个:KeyDown,KeyPress,KeyUp,分别发生于键按下,击键完成,键弹出三种情况,KeyDown和KeyUp属于低级一点的事件,KeyPress属于高级一点的事件,KeyPress产生时击键动作完成,但产生的字符尚未输入。有些特殊键会产生KeyDown和KeyUp事件,但不会产生KeyPress事件,这些键包括:功能键、光标键、Ctrl、Alt、Shift、CapsLock、NumLock、ScrollLock、Delete、Insert、Pause、Break、Home、End、PageDown、PageUp、PrintScreen。KeyPress事件的参数是KeyPressEventArgs对象,包括一个Handled属性,如果将其设置为true的话,将阻断本次按键的后续键事件的发生。

  对于Ctrl、Alt和Shift几个键,如果在KeyDown或KeyUp事件中检测它们的状态,可使用事件参数e(KeyEventArgs对象)的属性:

if ((e.Modifiers & Keys.Shift) == Keys.Shift)

或者:

if (e.Alt)

  如果需要测试CapsLock、NumLock或ScrollLock的状态,可使用Control类在.Net 2.0以后新加入的方法:

if (Control.IsKeyLocked(Keys.CapsLock))

  这个方法只能用于这三个键,如果用于其他键的话,将抛出一个NotSupportedException异常。

  同样,Control的ModifierKeys属性可在键盘事件之外的其他位置检测Ctrl这几个键的状态。

  对于编辑控件来说,有必要知道Insert键的状态,没有直接的属性或方法能获得这个信息,可以使用Windows API:

[DllImport("User32.dll")]
private static extern short GetKeyState(System.Windows.Forms.Keys key);
...
if (GetKeyState(Keys.Insert) == 1)//改写状态

  Form类的KeyPreview属性如果为true的话,可使Form在控件之前截获键盘事件,如果这个时候,将KeyPress事件的KeyPressEventArgs的Handled属性设置为true的话,那么,对应的控件就无法收到键盘消息了。不过这个属性的作用限定在单次按键,下一次按键不受影响。如果要禁止所有后续键盘事件,设置KeyEventArgs的SuppressKeyPress属性为true。

  这些事件、方法和属性都是键盘的虚拟状态,并不对应于当前时刻键盘的物理状态。获得键盘的物理状态使用Windows API:

[DllImport("User32.dll")]
private static extern short GetAsyncKeyState(System.Windows.Forms.Keys key);

  这个函数的可能返回值有三个:0表示自上次调用以来对应键未按下过,1表示对应键当前未按下,但自上次调用后曾按下过,-32767表示当前正按下。

  GetKeyState返回的信息与.Net中的方法、属性类似,也是键盘的虚拟状态。

  鼠标消息的种类相对多一点,需要特别关注的地方也不是很多:

  MouseDown、Click、MouseUp,这是三个常用事件产生的顺序,对于常规控件,左右键都可以产生这几个事件。而按钮可以通过键盘操作产生Click事件,并且右键点击按钮会产生MouseDown和MouseUp,却不会产生Click事件。如果是一个双击,第一次点击会产生Click事件,第二次产生DoubleClick事件。

  MouseEnter和MouseLeave分别产生于鼠标光标进入和离开控件区域。鼠标每在控件表面移动一个像素,或刚产生一个MouseUp事件,都会产生MouseMove事件。由于可能一次鼠标移动就会产生大量MouseMove事件,一般情况下,MouseMove的处理方法中不应进行过于耗时的操作。如果鼠标在控件表面停留了指定的时间,就会产生一个MouseHover事件,只会产生一次。MouseWheel事件产生时,并不需要鼠标光标停留在控件表面,只要它有焦点即可,对于不能获得焦点的控件,就不会有这个事件了。

  MouseDown和MouseUp事件处理方法的参数e(MouseEventArgs类型的对象)的属性Button可获得按下的是哪个按钮:

 

if (e.Button == MouseButtons.Right)

   MouseMove事件中,Button属性表示的是所有被按下的按钮。

  所有从Control派生的类都拥有这些静态属性:MousePosition和MouseButtons,这两个属性反映的是当前的鼠标状态。MousePosition获得的是屏幕坐标(静态方法嘛),可以使用Form.PointToClient和Form.ClientToPoint方法进行坐标的转换。

  鼠标事件中还有一点细节需要注意:当一个控件收到MouseDown事件时,它“捕获”了鼠标,即使鼠标光标移出了控件的区域范围,它仍会持续地收到其他鼠标事件(如MouseMove),这个过程一直持续到鼠标按钮被释放,MouseUp事件产生。

  控件的鼠标光标形状由Cursor属性指定,这个属性作用于控件本身和它的子控件。Cursors类包含有一些预定义的光标:Cursors.WaitCursor、Cursors.Default等,也可以使用Cursor类创建自定义的光标,不过目前仅支持cur文件,如果需要使用ani文件,需要通过Windows API函数:

[DllImport("User32.dll")]
private static extern IntPtr LoadCursorFromFile(String str);

...
IntPtr hCursor = LoadCursorFromFile(filename);

if (!IntPtr.Zero.Equals(hCursor))
{
return new Cursor(hCursor);
}