天天看点

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 类提供的比较常用的事件:

(表一)

Click HelpRequested MouseLeave
ContextMenuChanged Invalidated MouseMove
DoubleClick KeyDown MouseUp
DragDrop KeyPress MouseWheel
DragEnter KeyUp Move
DragLeave Layout Paint
DragOver Leave ParentChanged
EnabledChanged LostFocus Resize
Enter MouseDown SizeChanged
FontChanged MouseEnter StyleChanged
GotFocus MouseHover TextChanged

注意表中用黑体标出的事件,这些事件顾名便可思意: 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, VScrollBar None None None None None None
Button, CheckBox, RadioButton Click Click, Click None None None None
ListBox, CheckedListBox, ComboBox Click Click, DoubleClick None None None None
TextBox, DomainUpDown, NumericUpDown Click Click, DoubleClick None None None None
*TreeView, *ListView Click Click, DoubleClick Click Click, DoubleClick None None
ProgressBar TrackBar Click Click, Click Click Click, Click Click Click, Click
Form, DataGrid, Label, LinkLabel, Panel,GroupBox, PictureBox, Splitter, DoubleClick, StatusBar,ToolBar, TabPage, **TabControl Click Click, DoubleClick Click Click, DoubleClick Click Click, 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); // 这一步不能忘!       }  我写了一个例子程序 MouseTrap ,如图一所示,

图一 MouseEventTrap

该程序示范了如何进行鼠标事件的处理。如果你借 WndProc 处理消息,由于必须用 IntPtrs 获取消息参数,所以你或多或少要用 C 编程,但因为你已经谙熟 C++ ,所以此时你不会感觉吃力,而是轻车熟路。

继续阅读