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)
|
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)
|
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) :
|
IPublisher publisher) :
|
||||||
INavigation
|
INavigation
|
||||||
{
|
{
|
||||||
public async void Navigate(string route,
|
public void Navigate(string route,
|
||||||
object? sender = null,
|
object? sender = null,
|
||||||
object? region = null,
|
object? region = null,
|
||||||
EventHandler? navigated = null,
|
EventHandler? navigated = null,
|
||||||
|
|||||||
@@ -533,8 +533,8 @@ public class ContentCropper : ContentControl
|
|||||||
double centreX,
|
double centreX,
|
||||||
double centreY)
|
double centreY)
|
||||||
{
|
{
|
||||||
int width = (int)border.Width;
|
int width = (int?)border?.Width ?? 0;
|
||||||
int height = (int)border.Height;
|
int height = (int?)border?.Height ?? 0;
|
||||||
|
|
||||||
double x = Math.Max(centreX - width / 2, 0);
|
double x = Math.Max(centreX - width / 2, 0);
|
||||||
double y = Math.Max(centreY - height / 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 Toolkit.Foundation;
|
||||||
using Windows.Win32;
|
using Windows.Win32;
|
||||||
using Windows.Win32.Foundation;
|
using Windows.Win32.Foundation;
|
||||||
using Windows.Win32.Graphics.Gdi;
|
|
||||||
using Windows.Win32.UI.WindowsAndMessaging;
|
using Windows.Win32.UI.WindowsAndMessaging;
|
||||||
|
|
||||||
namespace Toolkit.Windows;
|
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) :
|
public class PointerMonitor(IPublisher publisher) :
|
||||||
IPointerMonitor
|
IPointerMonitor
|
||||||
{
|
{
|
||||||
@@ -75,6 +15,7 @@ public class PointerMonitor(IPublisher publisher) :
|
|||||||
private bool isPointerPressed;
|
private bool isPointerPressed;
|
||||||
private HOOKPROC? mouseEventDelegate;
|
private HOOKPROC? mouseEventDelegate;
|
||||||
private UnhookWindowsHookExSafeHandle? mouseHandle;
|
private UnhookWindowsHookExSafeHandle? mouseHandle;
|
||||||
|
|
||||||
~PointerMonitor()
|
~PointerMonitor()
|
||||||
{
|
{
|
||||||
Dispose(false);
|
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">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>net9.0-windows</TargetFramework>
|
<TargetFramework>net9.0-windows10.0.19041.0</TargetFramework>
|
||||||
<ImplicitUsings>enable</ImplicitUsings>
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
<Nullable>enable</Nullable>
|
<Nullable>enable</Nullable>
|
||||||
<AllowUnsafeBlocks>True</AllowUnsafeBlocks>
|
<AllowUnsafeBlocks>True</AllowUnsafeBlocks>
|
||||||
<ResolveComReferenceSilent>True</ResolveComReferenceSilent>
|
<ResolveComReferenceSilent>True</ResolveComReferenceSilent>
|
||||||
<Platforms>x64;x86</Platforms>
|
<Platforms>AnyCPU;x64;x86</Platforms>
|
||||||
|
<WindowsSdkPackageVersion>10.0.19041.41</WindowsSdkPackageVersion>
|
||||||
|
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
@@ -14,7 +16,6 @@
|
|||||||
<PrivateAssets>all</PrivateAssets>
|
<PrivateAssets>all</PrivateAssets>
|
||||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||||
</PackageReference>
|
</PackageReference>
|
||||||
<PackageReference Include="System.Runtime.WindowsRuntime" Version="5.0.0-preview.5.20278.1" />
|
|
||||||
<PackageReference Include="WindowsShortcutFactory" Version="1.0.1" />
|
<PackageReference Include="WindowsShortcutFactory" Version="1.0.1" />
|
||||||
</ItemGroup>
|
</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