project
This commit is contained in:
@@ -0,0 +1,155 @@
|
||||
using Windows.Win32;
|
||||
using Windows.Win32.UI.WindowsAndMessaging;
|
||||
using Windows.Win32.Foundation;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
|
||||
namespace TheXamlGuy.TaskbarGroup.Core
|
||||
{
|
||||
public class PointerMonitor : IPointerMonitor
|
||||
{
|
||||
private readonly IMessenger messenger;
|
||||
private bool isDisposed;
|
||||
private bool isPointerPressed;
|
||||
private HOOKPROC? mouseEventDelegate;
|
||||
private UnhookWindowsHookExSafeHandle? mouseHandle;
|
||||
private bool isPointerDrag;
|
||||
|
||||
public PointerMonitor(IMessenger messenger)
|
||||
{
|
||||
this.messenger = messenger;
|
||||
}
|
||||
|
||||
~PointerMonitor()
|
||||
{
|
||||
Dispose(false);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Dispose(true);
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
public unsafe void Initialize()
|
||||
{
|
||||
InitializeHook();
|
||||
}
|
||||
|
||||
protected virtual void Dispose(bool disposing)
|
||||
{
|
||||
if (!isDisposed)
|
||||
{
|
||||
RemoveHook();
|
||||
isDisposed = true;
|
||||
}
|
||||
}
|
||||
|
||||
private unsafe void InitializeHook()
|
||||
{
|
||||
mouseEventDelegate = new HOOKPROC(MouseProc);
|
||||
mouseHandle = PInvoke.SetWindowsHookEx(WINDOWS_HOOK_ID.WH_MOUSE_LL, mouseEventDelegate, PInvoke.GetModuleHandle("user32.dll"), 0);
|
||||
}
|
||||
|
||||
private unsafe bool TryGetPointer(out POINT point)
|
||||
{
|
||||
fixed (POINT* lpPointLocal = &point)
|
||||
{
|
||||
return PInvoke.GetPhysicalCursorPos(lpPointLocal);
|
||||
}
|
||||
}
|
||||
|
||||
private bool TryGetPointerLocation([MaybeNullWhen(false)]out PointerLocation location)
|
||||
{
|
||||
if (TryGetPointer(out POINT point))
|
||||
{
|
||||
location = new PointerLocation(point.x, point.y);
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
location = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
private LRESULT MouseProc(int nCode, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
if (nCode >= 0)
|
||||
{
|
||||
|
||||
if (TryGetPointerLocation(out var location))
|
||||
{
|
||||
switch ((uint)wParam.Value)
|
||||
{
|
||||
case (uint)WndProcMessages.WM_MOUSEMOVE:
|
||||
SendPointerMoved(location);
|
||||
break;
|
||||
case (uint)WndProcMessages.WM_LBUTTONUP:
|
||||
SendPointerReleased(location, PointerButton.Left);
|
||||
break;
|
||||
case (uint)WndProcMessages.WM_MBUTTONUP:
|
||||
SendPointerReleased(location, PointerButton.Middle);
|
||||
break;
|
||||
case (uint)WndProcMessages.WM_RBUTTONUP:
|
||||
SendPointerReleased(location, PointerButton.Right);
|
||||
break;
|
||||
case (uint)WndProcMessages.WM_LBUTTONDOWN:
|
||||
SendPointerPressed(location, PointerButton.Left);
|
||||
break;
|
||||
case (uint)WndProcMessages.WM_MBUTTONDOWN:
|
||||
SendPointerPressed(location, PointerButton.Middle);
|
||||
break;
|
||||
case (uint)WndProcMessages.WM_RBUTTONDOWN:
|
||||
SendPointerPressed(location, PointerButton.Right);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return PInvoke.CallNextHookEx(mouseHandle, nCode, wParam, lParam);
|
||||
}
|
||||
|
||||
private unsafe void RemoveHook()
|
||||
{
|
||||
if (mouseHandle is not null && mouseHandle.DangerousGetHandle() != IntPtr.Zero)
|
||||
{
|
||||
PInvoke.UnhookWindowsHookEx((HHOOK)mouseHandle.DangerousGetHandle());
|
||||
}
|
||||
}
|
||||
|
||||
private void SendPointerMoved(PointerLocation location)
|
||||
{
|
||||
if (isPointerPressed)
|
||||
{
|
||||
if (!isPointerDrag)
|
||||
{
|
||||
isPointerDrag = true;
|
||||
}
|
||||
|
||||
messenger.Send(new PointerDrag(location));
|
||||
}
|
||||
|
||||
messenger.Send(new PointerMoved(location));
|
||||
}
|
||||
|
||||
private void SendPointerPressed(PointerLocation location, PointerButton button)
|
||||
{
|
||||
isPointerPressed = true;
|
||||
messenger.Send(new PointerPressed(location, button));
|
||||
}
|
||||
|
||||
private void SendPointerReleased(PointerLocation location, PointerButton button)
|
||||
{
|
||||
if (isPointerPressed)
|
||||
{
|
||||
if (isPointerDrag)
|
||||
{
|
||||
isPointerDrag = false;
|
||||
messenger.Send(new PointerDragReleased(location, button));
|
||||
}
|
||||
|
||||
isPointerPressed = false;
|
||||
messenger.Send(new PointerReleased(location, button));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user