// This code is distributed under MIT license.
// Copyright (c) 2015 George Mamaladze
// See license.txt or https://mit-license.org/
using System;
using System.Runtime.InteropServices;
using System.Windows.Forms;
using Gma.System.MouseKeyHook.WinApi;
namespace Gma.System.MouseKeyHook
{
///
/// Provides extended data for the MouseClickExt and MouseMoveExt events.
///
public class MouseEventExtArgs : MouseEventArgs
{
///
/// Initializes a new instance of the class.
///
/// One of the MouseButtons values indicating which mouse button was pressed.
/// The number of times a mouse button was pressed.
/// The x and y coordinate of a mouse click, in pixels.
/// A signed count of the number of detents the wheel has rotated.
/// The system tick count when the event occurred.
/// True if event signals mouse button down.
/// True if event signals mouse button up.
/// True if event signals horizontal wheel action.
internal MouseEventExtArgs(MouseButtons buttons, int clicks, Point point, int delta, int timestamp,
bool isMouseButtonDown, bool isMouseButtonUp, bool isHorizontalWheel)
: base(buttons, clicks, point.X, point.Y, delta)
{
IsMouseButtonDown = isMouseButtonDown;
IsMouseButtonUp = isMouseButtonUp;
IsHorizontalWheel = isHorizontalWheel;
Timestamp = timestamp;
}
///
/// Set this property to true inside your event handler to prevent further processing of the event in other
/// applications.
///
public bool Handled { get; set; }
///
/// True if event contains information about wheel scroll.
///
public bool WheelScrolled
{
get { return Delta != 0; }
}
///
/// True if event signals a click. False if it was only a move or wheel scroll.
///
public bool Clicked
{
get { return Clicks > 0; }
}
///
/// True if event signals mouse button down.
///
public bool IsMouseButtonDown { get; }
///
/// True if event signals mouse button up.
///
public bool IsMouseButtonUp { get; }
///
/// True if event signals horizontal wheel action.
///
public bool IsHorizontalWheel { get; }
///
/// The system tick count of when the event occurred.
///
public int Timestamp { get; }
///
///
internal Point Point
{
get { return new Point(X, Y); }
}
internal static MouseEventExtArgs FromRawDataApp(CallbackData data)
{
var wParam = data.WParam;
var lParam = data.LParam;
var mSwapButton = data.MSwapButton;
var marshalledMouseStruct =
(AppMouseStruct) Marshal.PtrToStructure(lParam, typeof(AppMouseStruct));
return FromRawDataUniversal(wParam, marshalledMouseStruct.ToMouseStruct(), mSwapButton);
}
internal static MouseEventExtArgs FromRawDataGlobal(CallbackData data)
{
var wParam = data.WParam;
var lParam = data.LParam;
var mSwapButton = data.MSwapButton;
var marshalledMouseStruct = (MouseStruct) Marshal.PtrToStructure(lParam, typeof(MouseStruct));
return FromRawDataUniversal(wParam, marshalledMouseStruct, mSwapButton);
}
///
/// Creates from relevant mouse data.
///
/// First Windows Message parameter.
/// A MouseStruct containing information from which to construct MouseEventExtArgs.
/// A new MouseEventExtArgs object.
private static MouseEventExtArgs FromRawDataUniversal(IntPtr wParam, MouseStruct mouseInfo, int mSwapButton)
{
var button = MouseButtons.None;
short mouseDelta = 0;
var clickCount = 0;
var isMouseButtonDown = false;
var isMouseButtonUp = false;
var isHorizontalWheel = false;
switch ((long) wParam)
{
case Messages.WM_LBUTTONDOWN:
isMouseButtonDown = true;
button = MouseButtons.Left;
clickCount = 1;
break;
case Messages.WM_LBUTTONUP:
isMouseButtonUp = true;
button = MouseButtons.Left;
clickCount = 1;
break;
case Messages.WM_LBUTTONDBLCLK:
isMouseButtonDown = true;
button = MouseButtons.Left;
clickCount = 2;
break;
case Messages.WM_RBUTTONDOWN:
isMouseButtonDown = true;
button = MouseButtons.Right;
clickCount = 1;
break;
case Messages.WM_RBUTTONUP:
isMouseButtonUp = true;
button = MouseButtons.Right;
clickCount = 1;
break;
case Messages.WM_RBUTTONDBLCLK:
isMouseButtonDown = true;
button = MouseButtons.Right;
clickCount = 2;
break;
case Messages.WM_MBUTTONDOWN:
isMouseButtonDown = true;
button = MouseButtons.Middle;
clickCount = 1;
break;
case Messages.WM_MBUTTONUP:
isMouseButtonUp = true;
button = MouseButtons.Middle;
clickCount = 1;
break;
case Messages.WM_MBUTTONDBLCLK:
isMouseButtonDown = true;
button = MouseButtons.Middle;
clickCount = 2;
break;
case Messages.WM_MOUSEWHEEL:
isHorizontalWheel = false;
mouseDelta = mouseInfo.MouseData;
break;
case Messages.WM_MOUSEHWHEEL:
isHorizontalWheel = true;
mouseDelta = mouseInfo.MouseData;
break;
case Messages.WM_XBUTTONDOWN:
button = mouseInfo.MouseData == 1
? MouseButtons.XButton1
: MouseButtons.XButton2;
isMouseButtonDown = true;
clickCount = 1;
break;
case Messages.WM_XBUTTONUP:
button = mouseInfo.MouseData == 1
? MouseButtons.XButton1
: MouseButtons.XButton2;
isMouseButtonUp = true;
clickCount = 1;
break;
case Messages.WM_XBUTTONDBLCLK:
isMouseButtonDown = true;
button = mouseInfo.MouseData == 1
? MouseButtons.XButton1
: MouseButtons.XButton2;
clickCount = 2;
break;
}
if (mSwapButton > 0)
{
button = button == MouseButtons.Left ? MouseButtons.Right : button == MouseButtons.Right ? MouseButtons.Left : button;
}
var e = new MouseEventExtArgs(
button,
clickCount,
mouseInfo.Point,
mouseDelta,
mouseInfo.Timestamp,
isMouseButtonDown,
isMouseButtonUp,
isHorizontalWheel);
return e;
}
internal MouseEventExtArgs ToDoubleClickEventArgs()
{
return new MouseEventExtArgs(Button, 2, Point, Delta, Timestamp, IsMouseButtonDown, IsMouseButtonUp, IsHorizontalWheel);
}
}
}