More WIndows specific parts moved to this project
This commit is contained in:
@@ -19,7 +19,7 @@ public partial class ConfigurationValueViewModel<TConfiguration, TValue>(IServic
|
||||
{
|
||||
if (args.Sender is TConfiguration configuration)
|
||||
{
|
||||
// await Task.Run(() => Value = read(configuration));
|
||||
await Task.Run(() => Value = read(configuration));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -96,7 +96,7 @@ public partial class ConfigurationValueViewModel<TConfiguration, TValue, TItem>
|
||||
{
|
||||
if (args.Sender is TConfiguration configuration)
|
||||
{
|
||||
// await Task.Run(() => Value = read(configuration));
|
||||
await Task.Run(() => Value = read(configuration));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ public class Navigation(IServiceProvider provider,
|
||||
IPublisher publisher) :
|
||||
INavigation
|
||||
{
|
||||
public async void Navigate(string route,
|
||||
public void Navigate(string route,
|
||||
object? sender = null,
|
||||
object? region = null,
|
||||
EventHandler? navigated = null,
|
||||
|
||||
@@ -533,8 +533,8 @@ public class ContentCropper : ContentControl
|
||||
double centreX,
|
||||
double centreY)
|
||||
{
|
||||
int width = (int)border.Width;
|
||||
int height = (int)border.Height;
|
||||
int width = (int?)border?.Width ?? 0;
|
||||
int height = (int?)border?.Height ?? 0;
|
||||
|
||||
double x = Math.Max(centreX - width / 2, 0);
|
||||
double y = Math.Max(centreY - height / 2, 0);
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
using Toolkit.Foundation;
|
||||
|
||||
namespace Toolkit.Windows;
|
||||
|
||||
public interface ITaskbar :
|
||||
IInitialization,
|
||||
IDisposable
|
||||
{
|
||||
TaskbarState GetCurrentState();
|
||||
|
||||
IntPtr GetHandle();
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
namespace Toolkit.Windows;
|
||||
|
||||
public interface ITaskbarButton :
|
||||
IDisposable
|
||||
{
|
||||
Rect Rect { get; }
|
||||
|
||||
string Name { get; }
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
namespace Toolkit.Windows;
|
||||
|
||||
public static class PointerLocationExtensions
|
||||
{
|
||||
public static bool IsWithinBounds(this PointerLocation args, Rect bounds) => args.X >= bounds.X
|
||||
&& args.X <= bounds.X + bounds.Width
|
||||
&& args.Y >= bounds.Y
|
||||
&& args.Y <= bounds.Y + bounds.Height;
|
||||
}
|
||||
@@ -3,70 +3,10 @@ using System.Drawing;
|
||||
using Toolkit.Foundation;
|
||||
using Windows.Win32;
|
||||
using Windows.Win32.Foundation;
|
||||
using Windows.Win32.Graphics.Gdi;
|
||||
using Windows.Win32.UI.WindowsAndMessaging;
|
||||
|
||||
namespace Toolkit.Windows;
|
||||
|
||||
public class WndProcMonitor(IPublisher publisher) :
|
||||
IWndProcMonitor
|
||||
{
|
||||
private WNDPROC? handler;
|
||||
private readonly IPublisher publisher = publisher;
|
||||
|
||||
public IntPtr Handle { get; private set; }
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
PInvoke.DestroyWindow((HWND)Handle);
|
||||
}
|
||||
|
||||
private unsafe void InitializeWndProc()
|
||||
{
|
||||
var windowName = Guid.NewGuid().ToString();
|
||||
handler = Wndproc;
|
||||
|
||||
WNDCLASSW wndProcWindow;
|
||||
|
||||
wndProcWindow.style = 0;
|
||||
wndProcWindow.lpfnWndProc = handler;
|
||||
wndProcWindow.cbClsExtra = 0;
|
||||
wndProcWindow.cbWndExtra = 0;
|
||||
wndProcWindow.hInstance = new HINSTANCE();
|
||||
wndProcWindow.hIcon = new HICON();
|
||||
wndProcWindow.hCursor = new HCURSOR();
|
||||
wndProcWindow.hbrBackground = new HBRUSH();
|
||||
|
||||
fixed (char* menuName = "")
|
||||
{
|
||||
wndProcWindow.lpszMenuName = new PCWSTR(menuName);
|
||||
}
|
||||
|
||||
fixed (char* className = windowName)
|
||||
{
|
||||
wndProcWindow.lpszClassName = new PCWSTR(className);
|
||||
}
|
||||
|
||||
PInvoke.RegisterClass(wndProcWindow);
|
||||
Handle = PInvoke.CreateWindowEx(0, wndProcWindow.lpszClassName,
|
||||
new PCWSTR(), 0, 0, 0, 0, 0, new HWND(),
|
||||
new HMENU(),
|
||||
new HINSTANCE());
|
||||
}
|
||||
|
||||
private LRESULT Wndproc(HWND param0, uint param1, WPARAM param2, LPARAM param3)
|
||||
{
|
||||
publisher.Publish(new WndProcEventArgs(param1, (uint)param2.Value, (uint)param3.Value));
|
||||
return PInvoke.DefWindowProc(param0, param1, param2, param3);
|
||||
}
|
||||
|
||||
public void Initialize()
|
||||
{
|
||||
InitializeWndProc();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public class PointerMonitor(IPublisher publisher) :
|
||||
IPointerMonitor
|
||||
{
|
||||
@@ -75,6 +15,7 @@ public class PointerMonitor(IPublisher publisher) :
|
||||
private bool isPointerPressed;
|
||||
private HOOKPROC? mouseEventDelegate;
|
||||
private UnhookWindowsHookExSafeHandle? mouseHandle;
|
||||
|
||||
~PointerMonitor()
|
||||
{
|
||||
Dispose(false);
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
using Windows.Win32.Foundation;
|
||||
|
||||
namespace Toolkit.Windows;
|
||||
|
||||
internal static class RectExtensions
|
||||
{
|
||||
internal static Rect ToRect(this RECT rect) =>
|
||||
rect.right - rect.left < 0 || rect.bottom - rect.top < 0
|
||||
? new Rect(rect.left, rect.top, 0, 0)
|
||||
: new Rect(rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top);
|
||||
}
|
||||
@@ -0,0 +1,113 @@
|
||||
using System.Runtime.InteropServices;
|
||||
using Windows.Win32;
|
||||
using Windows.Win32.Foundation;
|
||||
using Windows.Win32.UI.WindowsAndMessaging;
|
||||
using Windows.Win32.Graphics.Gdi;
|
||||
|
||||
namespace Toolkit.Windows;
|
||||
|
||||
public class Screen
|
||||
{
|
||||
private const int CCHDEVICENAME = 32;
|
||||
private const int PRIMARY_MONITOR = unchecked((int)0xBAADF00D);
|
||||
private static readonly bool _multiMonitorSupport;
|
||||
|
||||
private readonly IntPtr _monitorHandle;
|
||||
|
||||
static Screen()
|
||||
{
|
||||
_multiMonitorSupport = PInvoke.GetSystemMetrics(SYSTEM_METRICS_INDEX.SM_CMONITORS) != 0;
|
||||
}
|
||||
|
||||
internal Screen(IntPtr monitorHandle)
|
||||
{
|
||||
if (!_multiMonitorSupport || monitorHandle == (IntPtr)PRIMARY_MONITOR)
|
||||
{
|
||||
Bounds = SystemInformationHelper.VirtualScreen;
|
||||
Primary = true;
|
||||
DeviceName = "DISPLAY";
|
||||
}
|
||||
else
|
||||
{
|
||||
var monitorData = GetMonitorData(monitorHandle);
|
||||
|
||||
Bounds = new Rect(monitorData.MonitorRect.left, monitorData.MonitorRect.top,
|
||||
monitorData.MonitorRect.right - monitorData.MonitorRect.left,
|
||||
monitorData.MonitorRect.bottom - monitorData.MonitorRect.top);
|
||||
|
||||
Primary = (monitorData.Flags & (int)MonitorFlag.MONITOR_DEFAULTTOPRIMARY) != 0;
|
||||
DeviceName = monitorData.DeviceName;
|
||||
}
|
||||
|
||||
_monitorHandle = monitorHandle;
|
||||
}
|
||||
|
||||
private enum MonitorFlag : uint
|
||||
{
|
||||
MONITOR_DEFAULTTONULL = 0,
|
||||
MONITOR_DEFAULTTOPRIMARY = 1,
|
||||
MONITOR_DEFAULTTONEAREST = 2
|
||||
}
|
||||
|
||||
public Rect Bounds { get; }
|
||||
|
||||
public string DeviceName { get; }
|
||||
|
||||
public bool Primary { get; }
|
||||
|
||||
public Rect WorkingArea => GetWorkingArea();
|
||||
|
||||
public static Screen FromHandle(IntPtr handle) => _multiMonitorSupport ?
|
||||
new Screen(PInvoke.MonitorFromWindow((HWND)handle,
|
||||
MONITOR_FROM_FLAGS.MONITOR_DEFAULTTONEAREST)) :
|
||||
new Screen(PRIMARY_MONITOR);
|
||||
|
||||
public override bool Equals(object? obj)
|
||||
{
|
||||
if (obj is not Screen monitor) return false;
|
||||
return _monitorHandle == monitor._monitorHandle;
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
checked
|
||||
{
|
||||
return (int)_monitorHandle;
|
||||
}
|
||||
}
|
||||
|
||||
[DllImport("user32.dll", EntryPoint = "GetMonitorInfo", CharSet = CharSet.Auto, SetLastError = true)]
|
||||
private static extern bool GetMonitorInfoEx(IntPtr hMonitor, ref MonitorData lpmi);
|
||||
|
||||
private MonitorData GetMonitorData(IntPtr monitorHandle)
|
||||
{
|
||||
MonitorData monitorData = new();
|
||||
monitorData.Size = Marshal.SizeOf(monitorData);
|
||||
GetMonitorInfoEx(monitorHandle, ref monitorData);
|
||||
|
||||
return monitorData;
|
||||
}
|
||||
|
||||
private Rect GetWorkingArea()
|
||||
{
|
||||
if (!_multiMonitorSupport || _monitorHandle == PRIMARY_MONITOR)
|
||||
{
|
||||
return SystemInformationHelper.WorkingArea;
|
||||
}
|
||||
|
||||
var monitorData = GetMonitorData(_monitorHandle);
|
||||
return new Rect(monitorData.WorkAreaRect.left, monitorData.WorkAreaRect.top, monitorData.WorkAreaRect.right - monitorData.WorkAreaRect.left, monitorData.WorkAreaRect.bottom - monitorData.WorkAreaRect.top);
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
|
||||
private struct MonitorData
|
||||
{
|
||||
public int Size;
|
||||
public RECT MonitorRect;
|
||||
public RECT WorkAreaRect;
|
||||
public uint Flags;
|
||||
|
||||
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = CCHDEVICENAME)]
|
||||
public string DeviceName;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
using System.Runtime.InteropServices;
|
||||
using Windows.Foundation;
|
||||
using Windows.Win32;
|
||||
using Windows.Win32.Foundation;
|
||||
using Windows.Win32.UI.WindowsAndMessaging;
|
||||
|
||||
namespace Toolkit.Windows;
|
||||
|
||||
internal static class SystemInformationHelper
|
||||
{
|
||||
private const int SPI_GETWORKAREA = 48;
|
||||
|
||||
public static Rect VirtualScreen => GetVirtualScreen();
|
||||
public static Rect WorkingArea => GetWorkingArea();
|
||||
|
||||
private static Rect GetVirtualScreen()
|
||||
{
|
||||
Size size = new(PInvoke.GetSystemMetrics(SYSTEM_METRICS_INDEX.SM_CXSCREEN),
|
||||
PInvoke.GetSystemMetrics(SYSTEM_METRICS_INDEX.SM_CYSCREEN));
|
||||
return new Rect(0, 0, (int)size.Width, (int)size.Height);
|
||||
}
|
||||
|
||||
private static Rect GetWorkingArea()
|
||||
{
|
||||
var rect = new RECT();
|
||||
|
||||
SystemParametersInfo(SPI_GETWORKAREA, 0, ref rect, 0);
|
||||
return new Rect(rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top);
|
||||
}
|
||||
|
||||
[DllImport("user32.dll", CharSet = CharSet.Auto)]
|
||||
private static extern bool SystemParametersInfo(int nAction, int nParam, ref RECT rc, int nUpdate);
|
||||
}
|
||||
@@ -0,0 +1,114 @@
|
||||
using Toolkit.Foundation;
|
||||
using Windows.Win32;
|
||||
|
||||
namespace Toolkit.Windows;
|
||||
|
||||
public class Taskbar(ISubscriber subscriber,
|
||||
IPublisher publisher,
|
||||
IDisposer disposer) :
|
||||
ITaskbar,
|
||||
INotificationHandler<WndProcEventArgs>,
|
||||
INotificationHandler<PointerReleasedEventArgs>,
|
||||
INotificationHandler<PointerMovedEventArgs>,
|
||||
INotificationHandler<PointerDragEventArgs>
|
||||
{
|
||||
private bool isDrag;
|
||||
private bool isWithinBounds;
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
disposer.Dispose(this);
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
public TaskbarState GetCurrentState()
|
||||
{
|
||||
var handle = GetHandle();
|
||||
var state = new TaskbarState
|
||||
{
|
||||
Screen = Screen.FromHandle(handle)
|
||||
};
|
||||
|
||||
var appBarData = PInvoke.GetAppBarData(handle);
|
||||
PInvoke.GetAppBarPosition(ref appBarData);
|
||||
|
||||
state.Rect = appBarData.rect.ToRect();
|
||||
state.Placement = (TaskbarPlacement)appBarData.uEdge;
|
||||
|
||||
return state;
|
||||
}
|
||||
|
||||
public IntPtr GetHandle() => WindowHelper.Find("Shell_TrayWnd");
|
||||
|
||||
public Task Handle(WndProcEventArgs args)
|
||||
{
|
||||
if (args.Message == PInvoke.WM_TASKBARCREATED ||
|
||||
args.Message == (int)WndProcMessages.WM_SETTINGCHANGE &&
|
||||
(int)args.WParam == PInvoke.SPI_SETWORKAREA)
|
||||
{
|
||||
publisher.Publish<TaskbarChangedEventArgs>();
|
||||
}
|
||||
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
public Task Handle(PointerReleasedEventArgs args)
|
||||
{
|
||||
if (isDrag)
|
||||
{
|
||||
isDrag = false;
|
||||
}
|
||||
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
public Task Handle(PointerMovedEventArgs args)
|
||||
{
|
||||
nint taskbarHandle = GetHandle();
|
||||
if (WindowHelper.TryGetBounds(taskbarHandle, out var rect))
|
||||
{
|
||||
if (args.Location.IsWithinBounds(rect))
|
||||
{
|
||||
if (isWithinBounds)
|
||||
{
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
isWithinBounds = true;
|
||||
publisher.Publish<TaskbarEnteredEventArgs>();
|
||||
}
|
||||
else
|
||||
{
|
||||
isDrag = false;
|
||||
isWithinBounds = false;
|
||||
}
|
||||
}
|
||||
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
public Task Handle(PointerDragEventArgs args)
|
||||
{
|
||||
if (isWithinBounds)
|
||||
{
|
||||
if (isDrag)
|
||||
{
|
||||
publisher.Publish<TaskbarDragOverEventArgs>();
|
||||
}
|
||||
else
|
||||
{
|
||||
publisher.Publish<TaskbarDragEnterEventArgs>();
|
||||
}
|
||||
|
||||
isDrag = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
isDrag = false;
|
||||
}
|
||||
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
public void Initialize() => subscriber.Subscribe(this);
|
||||
}
|
||||
@@ -0,0 +1,99 @@
|
||||
using Toolkit.Foundation;
|
||||
|
||||
namespace Toolkit.Windows;
|
||||
|
||||
public class TaskbarButton :
|
||||
ITaskbarButton,
|
||||
INotificationHandler<PointerReleasedEventArgs>,
|
||||
INotificationHandler<PointerMovedEventArgs>,
|
||||
INotificationHandler<PointerDragEventArgs>
|
||||
{
|
||||
private readonly IPublisher publisher;
|
||||
private readonly IDisposer disposer;
|
||||
private bool isWithinBounds;
|
||||
private bool isDrag;
|
||||
|
||||
public TaskbarButton(string name,
|
||||
Rect rect,
|
||||
IPublisher publisher,
|
||||
ISubscriber subscriber,
|
||||
IDisposer disposer)
|
||||
{
|
||||
this.publisher = publisher;
|
||||
this.disposer = disposer;
|
||||
|
||||
Name = name;
|
||||
Rect = rect;
|
||||
|
||||
subscriber.Subscribe(this);
|
||||
}
|
||||
|
||||
public Rect Rect { get; internal set; }
|
||||
|
||||
public string Name { get; internal set; }
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
disposer.Dispose(this);
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
public Task Handle(PointerReleasedEventArgs args)
|
||||
{
|
||||
if (!isDrag && isWithinBounds)
|
||||
{
|
||||
publisher.Publish(new TaskbarButtonInvokedEventArgs(this));
|
||||
}
|
||||
|
||||
if (isDrag)
|
||||
{
|
||||
isDrag = false;
|
||||
}
|
||||
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
public Task Handle(PointerDragEventArgs args)
|
||||
{
|
||||
if (isWithinBounds)
|
||||
{
|
||||
if (isDrag)
|
||||
{
|
||||
publisher.Publish(new TaskbarButtonDragOverEventArgs(this));
|
||||
}
|
||||
else
|
||||
{
|
||||
publisher.Publish(new TaskbarButtonDragEnterEventArgs(this));
|
||||
}
|
||||
|
||||
isDrag = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
isDrag = false;
|
||||
}
|
||||
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
public Task Handle(PointerMovedEventArgs args)
|
||||
{
|
||||
if (args.Location.IsWithinBounds(Rect))
|
||||
{
|
||||
if (isWithinBounds)
|
||||
{
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
isWithinBounds = true;
|
||||
publisher.Publish(new TaskbarButtonEnteredEventArgs(this));
|
||||
}
|
||||
else
|
||||
{
|
||||
isDrag = false;
|
||||
isWithinBounds = false;
|
||||
}
|
||||
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
namespace Toolkit.Windows;
|
||||
|
||||
public record TaskbarButtonDragEnterEventArgs(TaskbarButton Button);
|
||||
@@ -0,0 +1,3 @@
|
||||
namespace Toolkit.Windows;
|
||||
|
||||
public record TaskbarButtonDragOverEventArgs(TaskbarButton Button);
|
||||
@@ -0,0 +1,3 @@
|
||||
namespace Toolkit.Windows;
|
||||
|
||||
public record TaskbarButtonEnteredEventArgs(TaskbarButton Button);
|
||||
@@ -0,0 +1,3 @@
|
||||
namespace Toolkit.Windows;
|
||||
|
||||
public record TaskbarButtonInvokedEventArgs(TaskbarButton Button);
|
||||
@@ -0,0 +1,3 @@
|
||||
namespace Toolkit.Windows;
|
||||
|
||||
public record TaskbarChangedEventArgs;
|
||||
@@ -0,0 +1,3 @@
|
||||
namespace Toolkit.Windows;
|
||||
|
||||
public record TaskbarDragEnterEventArgs;
|
||||
@@ -0,0 +1,3 @@
|
||||
namespace Toolkit.Windows;
|
||||
|
||||
public record TaskbarDragOverEventArgs;
|
||||
@@ -0,0 +1,3 @@
|
||||
namespace Toolkit.Windows;
|
||||
|
||||
public record TaskbarEnteredEventArgs;
|
||||
@@ -0,0 +1,12 @@
|
||||
namespace Toolkit.Windows;
|
||||
|
||||
public class TaskbarList(ITaskbar taskbar) :
|
||||
ITaskbarList
|
||||
{
|
||||
public IntPtr GetHandle()
|
||||
{
|
||||
nint rebarHandle = WindowHelper.Find("ReBarWindow32", taskbar.GetHandle());
|
||||
nint taskHandle = WindowHelper.Find("MSTaskSwWClass", rebarHandle);
|
||||
return WindowHelper.Find("MSTaskListWClass", taskHandle);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
namespace Toolkit.Windows;
|
||||
|
||||
public enum TaskbarPlacement
|
||||
{
|
||||
Left = 0,
|
||||
Top = 1,
|
||||
Right = 2,
|
||||
Bottom = 3
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
namespace Toolkit.Windows;
|
||||
|
||||
public struct TaskbarState
|
||||
{
|
||||
public TaskbarPlacement Placement;
|
||||
public Rect Rect;
|
||||
public Screen Screen;
|
||||
}
|
||||
@@ -1,12 +1,14 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net9.0-windows</TargetFramework>
|
||||
<TargetFramework>net9.0-windows10.0.19041.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<AllowUnsafeBlocks>True</AllowUnsafeBlocks>
|
||||
<ResolveComReferenceSilent>True</ResolveComReferenceSilent>
|
||||
<Platforms>x64;x86</Platforms>
|
||||
<Platforms>AnyCPU;x64;x86</Platforms>
|
||||
<WindowsSdkPackageVersion>10.0.19041.41</WindowsSdkPackageVersion>
|
||||
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
@@ -14,7 +16,6 @@
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="System.Runtime.WindowsRuntime" Version="5.0.0-preview.5.20278.1" />
|
||||
<PackageReference Include="WindowsShortcutFactory" Version="1.0.1" />
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
@@ -0,0 +1,65 @@
|
||||
using Toolkit.Foundation;
|
||||
using Windows.Win32;
|
||||
using Windows.Win32.Foundation;
|
||||
using Windows.Win32.Graphics.Gdi;
|
||||
using Windows.Win32.UI.WindowsAndMessaging;
|
||||
|
||||
namespace Toolkit.Windows;
|
||||
|
||||
public class WndProcMonitor(IPublisher publisher) :
|
||||
IWndProcMonitor
|
||||
{
|
||||
private WNDPROC? handler;
|
||||
private readonly IPublisher publisher = publisher;
|
||||
|
||||
public IntPtr Handle { get; private set; }
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
PInvoke.DestroyWindow((HWND)Handle);
|
||||
}
|
||||
|
||||
private unsafe void InitializeWndProc()
|
||||
{
|
||||
var windowName = Guid.NewGuid().ToString();
|
||||
handler = Wndproc;
|
||||
|
||||
WNDCLASSW wndProcWindow;
|
||||
|
||||
wndProcWindow.style = 0;
|
||||
wndProcWindow.lpfnWndProc = handler;
|
||||
wndProcWindow.cbClsExtra = 0;
|
||||
wndProcWindow.cbWndExtra = 0;
|
||||
wndProcWindow.hInstance = new HINSTANCE();
|
||||
wndProcWindow.hIcon = new HICON();
|
||||
wndProcWindow.hCursor = new HCURSOR();
|
||||
wndProcWindow.hbrBackground = new HBRUSH();
|
||||
|
||||
fixed (char* menuName = "")
|
||||
{
|
||||
wndProcWindow.lpszMenuName = new PCWSTR(menuName);
|
||||
}
|
||||
|
||||
fixed (char* className = windowName)
|
||||
{
|
||||
wndProcWindow.lpszClassName = new PCWSTR(className);
|
||||
}
|
||||
|
||||
PInvoke.RegisterClass(wndProcWindow);
|
||||
Handle = PInvoke.CreateWindowEx(0, wndProcWindow.lpszClassName,
|
||||
new PCWSTR(), 0, 0, 0, 0, 0, new HWND(),
|
||||
new HMENU(),
|
||||
new HINSTANCE());
|
||||
}
|
||||
|
||||
private LRESULT Wndproc(HWND param0, uint param1, WPARAM param2, LPARAM param3)
|
||||
{
|
||||
publisher.Publish(new WndProcEventArgs(param1, (uint)param2.Value, (uint)param3.Value));
|
||||
return PInvoke.DefWindowProc(param0, param1, param2, param3);
|
||||
}
|
||||
|
||||
public void Initialize()
|
||||
{
|
||||
InitializeWndProc();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user