详解C#鼠标事件的处理机制

C#鼠标事件包括鼠标的很多操作,比如为用户提供鼠标的右键单击功能、右键拖拽等等。处理C#鼠标事件比较简单,只要设置好属性,点击右键就会出现菜单,进一步右键拖拽就涉及到时间处理。

过去用C++/MFC开发程序时,常常为用户提供鼠标的右键单击功能,如今在.NET框架中使用C#,也想在程序中提供鼠标右键单击功能,比如,在文本框、窗格、标签以及主窗口背景上使用鼠标右键。毕竟C#不是C++/MFC,那么如何处理C#鼠标事件呢?本文下面将专门探讨这个问题。

在.NET框架下编程是非常容易的一件事情,有时候容易得连C++程序员想都想不到。这主要是因为用C++编写代码常常需要“硬工夫”。所谓“硬工夫”,也就是很多细节都要自己考虑和处理。但使用C#则不然。如果你想显示上下文菜单,完全没有必要去和事件参合。只要设置控制的ContextMenu属性即可,就象下面这样:

ContextMenu myContextMenu = ...  


myControl.ContextMenu = myContextMenu;   

就这么简单。只要按照上述方法设置好属性,当用户单击右键时,菜单便会自动显示出来。此外,如果你想进一步实现右键拖拽,这才涉及到事件处理。在MFC中,你会自然而然想到用OnRButtonDown和OnRButtonUp实现,但是那不是Windows窗体(Forms)的工作方式。虽然许多窗口类确实提供了可以改写的虚拟函数来处理常用消息(如:Form.OnActivated和Form.OnClosed),但是在.NET框架中编程,你必须要学会用事件来思考,而且要了解一个类提供了哪些事件。下面这个表列出了被Control类提供的比较常用的事件:

(表一)

ClickHelpRequestedMouseLeave
ContextMenuChangedInvalidatedMouseMove
DoubleClickKeyDownMouseUp
DragDropKeyPressMouseWheel
DragEnterKeyUpMove
DragLeaveLayoutPaint
DragOverLeaveParentChanged
EnabledChangedLostFocusResize
EnterMouseDownSizeChanged
FontChangedMouseEnterStyleChanged
GotFocusMouseHoverTextChanged

注意表中用黑体标出的事件,这些事件顾名便可思意:MouseDown、 MouseEnter、 MouseHover、 MouseLeave、 MouseMove  和 MouseUp,如果你想要处理右键按下事件,可以安装MouseDown 事件处理例程,用MouseEventArgs.Button == MouseButtons.Right 检查 MouseEventArgs,下面的代码段示范了如何来做:
public class MyControl : Control  


{  



   // 构造函数  




   public MyControl() {  




      // 安装右键按下事件处理器   




      this.myctl1.MouseDown +=   




         new MouseEventHandler(this.OnMouseDown);  



   }  


 



   // 处理例程  




   private void OnMouseDown(object sender, MouseEventArgs e) {  




      if (e==MouseButtons.Right)  




         // do something  



   }  


}  

表一里有三个有用的鼠标事件是在MFC中不能直接处理的:MouseEnter、 MouseHover 和MouseLeave。在Win32 里,要处理这些事件必须通过专门的TrackMouseEvent 函数。.NET框架中,每当鼠标进入或离开特定控制时便会触发MouseEnter 和MouseLeave,当你想在鼠标移动到控制上时使控制呈高亮状态,这些事件相当有用,例如在浏览器中高亮显示链接。当鼠标移动到控制上后,在预先确定好的时间里(这个时间由 SystemParametersInfo(SPI_GETMOUSEHOVERTIME)) 指定),.NET 框架会激活 MouseHover。它在 Tooltips 和其它类似的定时弹出式功能应用中广泛使用。

这些鼠标事件和大家所熟悉的Click 事件有何关系呢?我想可以这么认为,Click属于层次较高的逻辑事件,而鼠标事件的级别相对较低,例如,不管用户按下的是左键还是右键,Forms都触发Click 事件,而文本框只能触发左键的Click事件。表二中列出了不同种类的控制其Click事件的含意。
(表二)由 Click 激发的事件

控制或控件鼠标左键单击鼠标左键双击鼠标右键单击鼠标右键双击鼠标中键单击鼠标中键双击
MonthCalendar, DateTimePicker, RichTextBox, HScrollBar, VScrollBarNoneNoneNoneNoneNoneNone
Button, CheckBox, RadioButtonClickClick, ClickNoneNoneNoneNone
ListBox, CheckedListBox, ComboBoxClickClick, DoubleClickNoneNoneNoneNone
TextBox, DomainUpDown, NumericUpDownClickClick, DoubleClickNoneNoneNoneNone
*TreeView, *ListView ClickClick, DoubleClickClickClick, DoubleClickNoneNone
ProgressBar TrackBar ClickClick, ClickClickClick, ClickClickClick, Click
Form, DataGrid, Label, LinkLabel, Panel,GroupBox, PictureBox, Splitter, DoubleClick, StatusBar,ToolBar, TabPage, **TabControlClickClick, DoubleClickClickClick, DoubleClickClickClick, DoubleClick
* 鼠标指针必须在子对象上方 (TreeNode 或 ListViewItem)
**  TabControl 必须在其 TabPages  页集合中至少有一个 TabPage。


最后,不管怎样,只要你愿意,总是可以改写Control.WndProc 来处理任何WM_XXX 消息,比如:你可以定制WM_NCLBUTTONDOWN 消息处理代码:

protected override void WndProc(ref Message m)  


{  



   // 值来自 winuser.h  




   const int WM_NCLBUTTONDOWN = 0x00A1;  




   if (m.Msg == WM_NCLBUTTONDOWN) {  




      //do something  



   }  



   base.WndProc(ref m); // 这一步不能忘!  



}  

相关推荐