(c) 2005 Marc Clifton All Rights Reserved.

Introduction
I was recently implementing some right-click functionality for a TreeView, and I got to thinking, how many times have I handled the MouseUp event and tested for Buttons.Right because there isn't a RightClick event in Control class? So I've written a mouse event helper class that lets you connect directly to these specific events:
public event EventHandler LeftClick;
public event EventHandler LeftDoubleClick;
public event EventHandler MiddleDoubleClick;
public event EventHandler RightDoubleClick;
public event EventHandler MiddleClick;
public event EventHandler RightClick;
public event MouseEventHandler LeftMouseDown;
public event MouseEventHandler LeftMouseUp;
public event MouseEventHandler MiddleMouseDown;
public event MouseEventHandler MiddleMouseUp;
public event MouseEventHandler RightMouseDown;
public event MouseEventHandler RightMouseUp;
public event MouseEventHandler WheelForward;
public event MouseEventHandler WheelBackward;
Implementation
The implementation is trivial. The MouseHelper class hooks the following control events:
protected virtual void Initialize()
{
control.Click+=new EventHandler(OnClick);
control.DoubleClick+=new EventHandler(OnDoubleClick);
control.MouseDown+=new MouseEventHandler(OnMouseDown);
control.MouseUp+=new MouseEventHandler(OnMouseUp);
control.MouseWheel+=new MouseEventHandler(OnMouseWheel);
}
A typical handler looks like this:
private void OnClick(object sender, EventArgs e)
{
switch(lastButton)
{
case MouseButtons.Left:
if (LeftClick != null)
{
LeftClick(sender, e);
}
break;
case MouseButtons.Middle:
if (MiddleClick != null)
{
MiddleClick(sender, e);
}
break;
case MouseButtons.Right:
if (RightClick != null)
{
RightClick(sender, e);
}
break;
}
}
You will note that this isn't intended to handle situations where more than one mouse button is being held down at a time.
Wheel Movement
One thing that's odd is that, for wheel movement, the documentation says that:
A positive value indicates that the wheel was rotated forward, away from the user; a negative value indicates that the wheel was rotated backward, toward the user.
However, if I push the wheel away from me, what I think would mean forward, the program actually says I'm moving the wheel backwards.
Usage
To use the MouseHelper class:
- Instantiate the class and pass into the constructor the control for which you wish to trap mouse events
- Assign the control to the MouseHelper's Control property
- Use the MouseHelper's AddControl method
You can add more than one control to the same mouse helper, which lets you combine mouse events from different controls into a single handler.
You should note that in the typical usage, you would use a unique MouseHelper instance for every Control class that you need to capture mouse events. This is a drawback, but I wanted to keep the class simple. An alternative would be to have a static factory method that returns a MouseHandler instance for the specific control you want to extend. And possibly, an even more interesting implementation would be to have MouseHandler implement IExtenderProvider. Those may be future additions.
Conclusion
That's it! It's really simple, and now I have a helper class that takes care of the drudgery of writing over and over again the same "is the right button clicked" code. And my other motivation for writing this is because there was no way to handle right clicks declaratively. For example, I'd like to do something like this:
<TreeView RightClick="PopupMenu"/>
without writing a custom handler. Now I can!