Files
SteamTools/System.Application.SteamTools.Client.Desktop.Windows/MouseHook.cs
T
2021-02-27 01:40:02 +08:00

167 lines
6.0 KiB
C#

using System.ComponentModel;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Windows;
namespace System
{
internal static class MouseHook
{
delegate int HookProc(int nCode, int wParam, IntPtr lParam);
static int _mouseHookHandle;
static HookProc? _mouseDelegate;
static event MouseUpEventHandler? MouseUp;
public static event MouseUpEventHandler OnMouseUp
{
add
{
Subscribe();
MouseUp += value;
}
remove
{
MouseUp -= value;
Unsubscribe();
}
}
static void Unsubscribe()
{
if (_mouseHookHandle != 0)
{
int result = UnhookWindowsHookEx(_mouseHookHandle);
_mouseHookHandle = 0;
_mouseDelegate = null;
if (result == 0)
{
int errorCode = Marshal.GetLastWin32Error();
throw new Win32Exception(errorCode);
}
}
}
static void Subscribe()
{
if (_mouseHookHandle == 0)
{
var currentProcessMainModuleName = Process.GetCurrentProcess().MainModule?.ModuleName;
if (string.IsNullOrWhiteSpace(currentProcessMainModuleName)) throw new ArgumentNullException(nameof(currentProcessMainModuleName));
_mouseDelegate = MouseHookProc;
_mouseHookHandle = SetWindowsHookEx(WH_MOUSE_LL,
_mouseDelegate,
GetModuleHandle(currentProcessMainModuleName),
0);
if (_mouseHookHandle == 0)
{
int errorCode = Marshal.GetLastWin32Error();
throw new Win32Exception(errorCode);
}
}
}
static int MouseHookProc(int nCode, int wParam, IntPtr lParam)
{
if (nCode >= 0)
{
var mouseHookStructObj = Marshal.PtrToStructure(lParam, typeof(MSLLHOOKSTRUCT));
if (mouseHookStructObj == null) throw new ArgumentNullException(nameof(mouseHookStructObj));
var mouseHookStruct = (MSLLHOOKSTRUCT)mouseHookStructObj;
if (wParam == WM_LBUTTONUP)
{
if (MouseUp != null)
{
MouseUp.Invoke(null, new Point(mouseHookStruct.pt.X, mouseHookStruct.pt.Y));
}
}
}
return CallNextHookEx(_mouseHookHandle, nCode, wParam, lParam);
}
const int WH_MOUSE_LL = 14;
const int WM_LBUTTONUP = 0x0202;
[StructLayout(LayoutKind.Sequential)]
struct MSLLHOOKSTRUCT
{
public PointInt32 pt;
public uint mouseData;
public uint flags;
public uint time;
public IntPtr dwExtraInfo;
}
[DllImport("kernel32.dll", CharSet = CharSet.Unicode)]
public static extern IntPtr GetModuleHandle(string name);
[DllImport(User32Window.LibraryName, CharSet = CharSet.Auto,
CallingConvention = CallingConvention.StdCall, SetLastError = true)]
static extern int SetWindowsHookEx(int idHook, HookProc lpfn, IntPtr hMod, int dwThreadId);
[DllImport(User32Window.LibraryName, CharSet = CharSet.Auto,
CallingConvention = CallingConvention.StdCall, SetLastError = true)]
static extern int UnhookWindowsHookEx(int idHook);
[DllImport(User32Window.LibraryName, CharSet = CharSet.Auto,
CallingConvention = CallingConvention.StdCall)]
static extern int CallNextHookEx(int idHook, int nCode, int wParam, IntPtr lParam);
[DllImport(User32Window.LibraryName, CharSet = CharSet.Auto)]
public static extern IntPtr LoadCursor(IntPtr hInstance, uint lpCursorName);
[DllImport(User32Window.LibraryName, CharSet = CharSet.Auto)]
public static extern bool SetSystemCursor(IntPtr hcur, uint id);
public const uint OCR_NORMAL = 32512;
public const uint OCR_IBEAM = 32513;
public const uint OCR_CROSS = 32515;
public const uint OCR_HAND = 32649;
[DllImport(User32Window.LibraryName, CharSet = CharSet.Auto)]
public static extern bool SystemParametersInfo(uint uiAction, uint uiParam,
IntPtr pvParam, uint fWinIni);
public enum SystemParametersDesktopInfo : uint
{
SPIF_SENDWININICHANGE = 2,
SPI_SETDESKWALLPAPER = 20,
SPI_SETDESKPATTERN = 21,
SPI_SETWORKAREA = 47,
SPI_GETWORKAREA = 48,
SPI_GETFONTSMOOTHING = 74,
SPI_SETFONTSMOOTHING = 75,
SPI_SETCURSORS = 87,
SPI_GETDESKWALLPAPER = 115,
SPI_GETFLATMENU = 4130,
SPI_SETFLATMENU = 4131,
SPI_GETDROPSHADOW = 4132,
SPI_SETDROPSHADOW = 4133,
SPI_GETCLEARTYPE = 4168,
SPI_SETCLEARTYPE = 4169,
SPI_GETFONTSMOOTHINGTYPE = 8202,
SPI_SETFONTSMOOTHINGTYPE = 8203,
SPI_GETFONTSMOOTHINGCONTRAST = 8204,
SPI_SETFONTSMOOTHINGCONTRAST = 8205,
SPI_GETFONTSMOOTHINGORIENTATION = 8210,
SPI_SETFONTSMOOTHINGORIENTATION = 8211
}
[Flags]
public enum SystemParamtersInfoFlags : uint
{
None = 0,
SPIF_UPDATEINIFILE = 1,
SPIF_SENDCHANGE = 2,
SPIF_SENDWININICHANGE = 2
}
[DllImport(User32Window.LibraryName, CharSet = CharSet.Auto, EntryPoint = "GetCursorPos")]
public static extern bool GetCursorPos(out PointInt32 pt);
[DllImport(User32Window.LibraryName, CharSet = CharSet.Auto, EntryPoint = "WindowFromPoint")]
public static extern IntPtr WindowFromPoint(PointInt32 pt);
}
internal delegate void MouseUpEventHandler(object? sender, Point p);
}