Add some WinUI work
This commit is contained in:
@@ -1,6 +1,5 @@
|
|||||||
using Avalonia.Controls;
|
using Avalonia.Controls;
|
||||||
using Avalonia.Controls.Templates;
|
using Avalonia.Controls.Templates;
|
||||||
using Avalonia.Data;
|
|
||||||
using Avalonia.Interactivity;
|
using Avalonia.Interactivity;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
using Toolkit.Foundation;
|
using Toolkit.Foundation;
|
||||||
|
|||||||
@@ -7,14 +7,14 @@ public class AsyncHandlerInitialization<TMessage, TResponse, THandler>(IServiceP
|
|||||||
IInitialization where THandler : class, IAsyncHandler<TMessage, TResponse>
|
IInitialization where THandler : class, IAsyncHandler<TMessage, TResponse>
|
||||||
where TMessage : class
|
where TMessage : class
|
||||||
{
|
{
|
||||||
public void Initialize() => WeakReferenceMessenger.Default.Register<IServiceProvider, AsyncResponseEventArgs<TMessage, TResponse>>(provider,
|
public void Initialize() => StrongReferenceMessenger.Default.Register<IServiceProvider, AsyncResponseEventArgs<TMessage, TResponse>>(provider,
|
||||||
async (provider, args) => args.Reply(await provider.GetRequiredService<THandler>().Handle(args.Message, args.CancellationToken)));
|
(provider, args) => args.Reply(provider.GetRequiredService<THandler>().Handle(args.Message, args.CancellationToken)));
|
||||||
}
|
}
|
||||||
|
|
||||||
public class AsyncHandlerInitialization<TMessage, THandler>(IServiceProvider provider) :
|
public class AsyncHandlerInitialization<TMessage, THandler>(IServiceProvider provider) :
|
||||||
IInitialization where THandler : class, IAsyncHandler<TMessage>
|
IInitialization where THandler : class, IAsyncHandler<TMessage>
|
||||||
where TMessage : class
|
where TMessage : class
|
||||||
{
|
{
|
||||||
public void Initialize() => WeakReferenceMessenger.Default.Register<IServiceProvider, AsyncResponseEventArgs<TMessage, Unit>>(provider,
|
public void Initialize() => StrongReferenceMessenger.Default.Register<IServiceProvider, AsyncResponseEventArgs<TMessage, Unit>>(provider,
|
||||||
async (provider, args) => await provider.GetRequiredService<THandler>().Handle(args.Message, args.CancellationToken));
|
(provider, args) => provider.GetRequiredService<THandler>().Handle(args.Message, args.CancellationToken));
|
||||||
}
|
}
|
||||||
@@ -5,7 +5,7 @@ namespace Toolkit.Foundation;
|
|||||||
public class AsyncResponseEventArgs<TMessage, TResponse> :
|
public class AsyncResponseEventArgs<TMessage, TResponse> :
|
||||||
AsyncRequestMessage<TResponse>
|
AsyncRequestMessage<TResponse>
|
||||||
{
|
{
|
||||||
public TMessage? Message { get; set; }
|
public required TMessage Message { get; set; }
|
||||||
|
|
||||||
public CancellationToken CancellationToken { get; set; }
|
public CancellationToken CancellationToken { get; set; }
|
||||||
}
|
}
|
||||||
@@ -20,14 +20,8 @@ public class DefaultHostBuilder :
|
|||||||
ComponentHostCollection>();
|
ComponentHostCollection>();
|
||||||
|
|
||||||
services.AddSingleton<IDisposer, Disposer>();
|
services.AddSingleton<IDisposer, Disposer>();
|
||||||
services.AddSingleton<IMessenger, WeakReferenceMessenger>(_ => WeakReferenceMessenger.Default);
|
services.AddSingleton<IMessenger, StrongReferenceMessenger>(_ => StrongReferenceMessenger.Default);
|
||||||
|
|
||||||
//services.AddScoped<SubscriptionCollection>();
|
|
||||||
|
|
||||||
//services.AddTransient<IHandlerProvider, HandlerProvider>();
|
|
||||||
//services.AddScoped<ISubscriber, Subscriber>();
|
|
||||||
//services.AddTransient<IPublisher, Publisher>();
|
|
||||||
//services.AddTransient<IMediator, Mediator>();
|
|
||||||
|
|
||||||
services.AddTransient<IValidation, Validation>();
|
services.AddTransient<IValidation, Validation>();
|
||||||
services.AddTransient<IValidatorCollection, ValidatorCollection>();
|
services.AddTransient<IValidatorCollection, ValidatorCollection>();
|
||||||
@@ -57,10 +51,10 @@ public class DefaultHostBuilder :
|
|||||||
services.AddTransient<IComponentFactory, ComponentFactory>();
|
services.AddTransient<IComponentFactory, ComponentFactory>();
|
||||||
services.AddTransient<IComponentScopeProvider, ComponentScopeProvider>();
|
services.AddTransient<IComponentScopeProvider, ComponentScopeProvider>();
|
||||||
|
|
||||||
//services.AddHandler<NavigateHandler>();
|
services.AddHandler<NavigateEventArgs, NavigateHandler>();
|
||||||
//services.AddHandler<NavigateBackHandler>();
|
services.AddHandler<NavigateBackEventArgs, NavigateBackHandler>();
|
||||||
|
|
||||||
//services.AddInitialization<ComponentInitializer>();
|
services.AddInitialization<ComponentInitializer>();
|
||||||
services.AddHostedService<AppService>();
|
services.AddHostedService<AppService>();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ public class HandlerInitialization<TMessage, TResponse, THandler>(IServiceProvid
|
|||||||
IInitialization where THandler : class, IHandler<TMessage, TResponse>
|
IInitialization where THandler : class, IHandler<TMessage, TResponse>
|
||||||
where TMessage : class
|
where TMessage : class
|
||||||
{
|
{
|
||||||
public void Initialize() => WeakReferenceMessenger.Default.Register<IServiceProvider, ResponseEventArgs<TMessage, TResponse>>(provider,
|
public void Initialize() => StrongReferenceMessenger.Default.Register<IServiceProvider, ResponseEventArgs<TMessage, TResponse>>(provider,
|
||||||
(provider, args) => args.Reply(provider.GetRequiredService<THandler>().Handle(args.Message)));
|
(provider, args) => args.Reply(provider.GetRequiredService<THandler>().Handle(args.Message)));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -15,7 +15,7 @@ public class HandlerInitialization<TMessage, THandler>(IServiceProvider provider
|
|||||||
IInitialization where THandler : class, IHandler<TMessage>
|
IInitialization where THandler : class, IHandler<TMessage>
|
||||||
where TMessage : class
|
where TMessage : class
|
||||||
{
|
{
|
||||||
public void Initialize() => WeakReferenceMessenger.Default.Register<IServiceProvider, TMessage>(provider,
|
public void Initialize() => StrongReferenceMessenger.Default.Register<IServiceProvider, TMessage>(provider,
|
||||||
(provider, args) => provider.GetRequiredService<THandler>().Handle(args));
|
(provider, args) => provider.GetRequiredService<THandler>().Handle(args));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -23,6 +23,6 @@ public class HandlerKeyedInitialization<TMessage, THandler>(string key, IService
|
|||||||
IInitialization where THandler : class, IHandler<TMessage>
|
IInitialization where THandler : class, IHandler<TMessage>
|
||||||
where TMessage : class
|
where TMessage : class
|
||||||
{
|
{
|
||||||
public void Initialize() => WeakReferenceMessenger.Default.Register<IServiceProvider, TMessage, string>(provider, key,
|
public void Initialize() => StrongReferenceMessenger.Default.Register<IServiceProvider, TMessage, string>(provider, key,
|
||||||
(provider, args) => provider.GetRequiredKeyedService<THandler>(key).Handle(args));
|
(provider, args) => provider.GetRequiredKeyedService<THandler>(key).Handle(args));
|
||||||
}
|
}
|
||||||
@@ -11,9 +11,27 @@ public static class IMessengerExtensions
|
|||||||
return args.Response;
|
return args.Response;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void Send<TMessage>(this IMessenger messenger, string key)
|
public static TResponse Send<TMessage, TResponse>(this IMessenger messenger,
|
||||||
where TMessage : class, new() => messenger.Send(new TMessage(), key);
|
TMessage message)
|
||||||
|
where TMessage : class
|
||||||
|
{
|
||||||
|
ResponseEventArgs<TMessage, TResponse> args = messenger.Send(new ResponseEventArgs<TMessage, TResponse> { Message = message });
|
||||||
|
return args.Response;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void Send<TMessage>(this IMessenger messenger,
|
||||||
|
TMessage message, string key) where TMessage : class =>
|
||||||
|
messenger.Send(message, key);
|
||||||
|
|
||||||
|
public static void Send<TMessage>(this IMessenger messenger,
|
||||||
|
string key) where TMessage : class, new() =>
|
||||||
|
messenger.Send(new TMessage(), key);
|
||||||
|
|
||||||
public static async Task<TResponse> SendAsync<TMessage, TResponse>(this IMessenger messenger)
|
public static async Task<TResponse> SendAsync<TMessage, TResponse>(this IMessenger messenger)
|
||||||
where TMessage : class, new() => await messenger.Send(new AsyncResponseEventArgs<TMessage, TResponse> { Message = new TMessage() });
|
where TMessage : class, new() =>
|
||||||
|
await messenger.Send(new AsyncResponseEventArgs<TMessage, TResponse> { Message = new TMessage() });
|
||||||
|
|
||||||
|
public static async Task<TResponse> SendAsync<TMessage, TResponse>(this IMessenger messenger,
|
||||||
|
TMessage message) where TMessage : class =>
|
||||||
|
await messenger.Send(new AsyncResponseEventArgs<TMessage, TResponse> { Message = message });
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,21 @@
|
|||||||
|
using System.Drawing;
|
||||||
|
using System.IO;
|
||||||
|
using Toolkit.Windows;
|
||||||
|
using Toolkit.WinUI;
|
||||||
|
|
||||||
|
namespace Toolkit.UI.WinUI;
|
||||||
|
|
||||||
|
public static class NotifyIconExtensions
|
||||||
|
{
|
||||||
|
public static void SetIcon(this INotifyIcon notifyIcon,
|
||||||
|
Stream? stream)
|
||||||
|
{
|
||||||
|
nint shellTrayHandle = WindowHelper.GetWindowHandle("Shell_TrayWnd");
|
||||||
|
uint dpi = WindowHelper.GetDpi(shellTrayHandle);
|
||||||
|
|
||||||
|
if (stream?.ConvertToIcon(dpi) is Icon icon)
|
||||||
|
{
|
||||||
|
notifyIcon.SetIcon(icon.Handle);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -23,5 +23,6 @@
|
|||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\Toolkit.Windows\Toolkit.Windows.csproj" />
|
<ProjectReference Include="..\Toolkit.Windows\Toolkit.Windows.csproj" />
|
||||||
|
<ProjectReference Include="..\Toolkit.WinUI\Toolkit.WinUI.csproj" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
||||||
|
|||||||
@@ -7,6 +7,9 @@ using Windows.Win32.Graphics.Gdi;
|
|||||||
using System.Drawing;
|
using System.Drawing;
|
||||||
using Windows.Win32.UI.Shell;
|
using Windows.Win32.UI.Shell;
|
||||||
using Windows.Win32.UI.WindowsAndMessaging;
|
using Windows.Win32.UI.WindowsAndMessaging;
|
||||||
|
using Toolkit.Windows;
|
||||||
|
using Rect = Windows.Foundation.Rect;
|
||||||
|
using WinUIEx;
|
||||||
|
|
||||||
namespace Toolkit.UI.WinUI;
|
namespace Toolkit.UI.WinUI;
|
||||||
|
|
||||||
@@ -14,20 +17,78 @@ public static partial class WindowExtensions
|
|||||||
{
|
{
|
||||||
private static SUBCLASSPROC? SubClassDelegate;
|
private static SUBCLASSPROC? SubClassDelegate;
|
||||||
|
|
||||||
public static void SetBorderless(this Window window,
|
public static void Hide(this Window window)
|
||||||
|
{
|
||||||
|
nint handle = WindowNative.GetWindowHandle(window);
|
||||||
|
if (handle == 0) return;
|
||||||
|
|
||||||
|
WindowHelper.HideWindow(new HWND(handle));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void IsShownInSwitchers(this Window window,
|
||||||
bool value)
|
bool value)
|
||||||
{
|
{
|
||||||
if (window.AppWindow is AppWindow appWindow &&
|
if (window.AppWindow is AppWindow appWindow)
|
||||||
appWindow.Presenter is OverlappedPresenter presenter)
|
|
||||||
{
|
{
|
||||||
presenter.IsMaximizable = !value;
|
appWindow.IsShownInSwitchers = value;
|
||||||
presenter.IsMinimizable = !value;
|
|
||||||
presenter.IsResizable = !value;
|
|
||||||
presenter.SetBorderAndTitleBar(!value, !value);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void SetTransparency(this Window window,
|
public static void MoveAndResize(this Window window,
|
||||||
|
Rect rect)
|
||||||
|
{
|
||||||
|
nint handle = WindowNative.GetWindowHandle(window);
|
||||||
|
if (handle == 0) return;
|
||||||
|
|
||||||
|
WindowHelper.MoveAndResizeWindow(new HWND(handle),
|
||||||
|
(int)rect.Left,
|
||||||
|
(int)rect.Top,
|
||||||
|
(int)rect.Width,
|
||||||
|
(int)rect.Height);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void SetBorderless(this Window window,
|
||||||
|
bool value)
|
||||||
|
{
|
||||||
|
WindowStyle windowStyle = window.GetWindowStyle();
|
||||||
|
|
||||||
|
if (value)
|
||||||
|
{
|
||||||
|
windowStyle &= ~(WindowStyle.Caption |
|
||||||
|
WindowStyle.ThickFrame |
|
||||||
|
WindowStyle.Border |
|
||||||
|
WindowStyle.SysMenu);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
windowStyle |= WindowStyle.Caption |
|
||||||
|
WindowStyle.ThickFrame |
|
||||||
|
WindowStyle.Border |
|
||||||
|
WindowStyle.SysMenu;
|
||||||
|
}
|
||||||
|
|
||||||
|
window.SetWindowStyle(windowStyle);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void SetForeground(this Window window)
|
||||||
|
{
|
||||||
|
nint handle = WindowNative.GetWindowHandle(window);
|
||||||
|
if (handle == 0) return;
|
||||||
|
|
||||||
|
WindowHelper.SetForegroundWindow(new HWND(handle));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void SetTopMost(this Window window,
|
||||||
|
bool value)
|
||||||
|
{
|
||||||
|
if (window.AppWindow is AppWindow appWindow &&
|
||||||
|
appWindow.Presenter is OverlappedPresenter presenter)
|
||||||
|
{
|
||||||
|
presenter.IsAlwaysOnTop = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void SetTransparency(this Window window,
|
||||||
bool value)
|
bool value)
|
||||||
{
|
{
|
||||||
nint handle = WindowNative.GetWindowHandle(window);
|
nint handle = WindowNative.GetWindowHandle(window);
|
||||||
@@ -44,18 +105,12 @@ public static partial class WindowExtensions
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static unsafe void EnableTransparency(HWND hWnd)
|
public static void Show(this Window window)
|
||||||
{
|
{
|
||||||
SubClassDelegate = new SUBCLASSPROC(WindowSubClass);
|
nint handle = WindowNative.GetWindowHandle(window);
|
||||||
_ = PInvoke.SetWindowSubclass(hWnd, SubClassDelegate, 0, 0);
|
if (handle == 0) return;
|
||||||
|
|
||||||
WINDOW_EX_STYLE exStyle = (WINDOW_EX_STYLE)PInvoke.GetWindowLong(hWnd, WINDOW_LONG_PTR_INDEX.GWL_EXSTYLE);
|
WindowHelper.ShowWindow(new HWND(handle));
|
||||||
_ = PInvoke.SetWindowLong(hWnd, WINDOW_LONG_PTR_INDEX.GWL_EXSTYLE,
|
|
||||||
(int)(exStyle | WINDOW_EX_STYLE.WS_EX_LAYERED));
|
|
||||||
|
|
||||||
COLORREF blackColor = new COLORREF((uint)ToWin32(Color.Black));
|
|
||||||
_ = PInvoke.SetLayeredWindowAttributes(hWnd, blackColor, 0, LAYERED_WINDOW_ATTRIBUTES_FLAGS.LWA_COLORKEY |
|
|
||||||
LAYERED_WINDOW_ATTRIBUTES_FLAGS.LWA_ALPHA);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static unsafe void DisableTransparency(HWND hWnd)
|
private static unsafe void DisableTransparency(HWND hWnd)
|
||||||
@@ -70,6 +125,20 @@ public static partial class WindowExtensions
|
|||||||
_ = PInvoke.SetWindowLong(hWnd, WINDOW_LONG_PTR_INDEX.GWL_EXSTYLE, (int)(exStyle & ~WINDOW_EX_STYLE.WS_EX_LAYERED));
|
_ = PInvoke.SetWindowLong(hWnd, WINDOW_LONG_PTR_INDEX.GWL_EXSTYLE, (int)(exStyle & ~WINDOW_EX_STYLE.WS_EX_LAYERED));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static unsafe void EnableTransparency(HWND hWnd)
|
||||||
|
{
|
||||||
|
SubClassDelegate = new SUBCLASSPROC(WindowSubClass);
|
||||||
|
_ = PInvoke.SetWindowSubclass(hWnd, SubClassDelegate, 0, 0);
|
||||||
|
|
||||||
|
WINDOW_EX_STYLE exStyle = (WINDOW_EX_STYLE)PInvoke.GetWindowLong(hWnd, WINDOW_LONG_PTR_INDEX.GWL_EXSTYLE);
|
||||||
|
_ = PInvoke.SetWindowLong(hWnd, WINDOW_LONG_PTR_INDEX.GWL_EXSTYLE,
|
||||||
|
(int)(exStyle | WINDOW_EX_STYLE.WS_EX_LAYERED));
|
||||||
|
|
||||||
|
COLORREF blackColor = new COLORREF((uint)ToWin32(Color.Black));
|
||||||
|
_ = PInvoke.SetLayeredWindowAttributes(hWnd, blackColor, 0, LAYERED_WINDOW_ATTRIBUTES_FLAGS.LWA_COLORKEY |
|
||||||
|
LAYERED_WINDOW_ATTRIBUTES_FLAGS.LWA_ALPHA);
|
||||||
|
}
|
||||||
|
|
||||||
private static int ToWin32(Color c) => c.B << 16 | c.G << 8 | c.R;
|
private static int ToWin32(Color c) => c.B << 16 | c.G << 8 | c.R;
|
||||||
|
|
||||||
private static unsafe LRESULT WindowSubClass(HWND hWnd,
|
private static unsafe LRESULT WindowSubClass(HWND hWnd,
|
||||||
|
|||||||
@@ -0,0 +1,45 @@
|
|||||||
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
using Microsoft.UI.Xaml;
|
||||||
|
using Microsoft.UI.Xaml.Controls;
|
||||||
|
using Microsoft.UI.Xaml.Markup;
|
||||||
|
using Toolkit.Foundation;
|
||||||
|
|
||||||
|
namespace Toolkit.WinUI;
|
||||||
|
|
||||||
|
public class ContentTemplate :
|
||||||
|
DataTemplateSelector,
|
||||||
|
IContentTemplate
|
||||||
|
{
|
||||||
|
protected override DataTemplate? SelectTemplateCore(object item)
|
||||||
|
{
|
||||||
|
if (item is IObservableViewModel observableViewModel)
|
||||||
|
{
|
||||||
|
if (observableViewModel.Provider is IServiceProvider provider)
|
||||||
|
{
|
||||||
|
Type itemType = item.GetType();
|
||||||
|
if (provider.GetRequiredKeyedService<IContentTemplateDescriptor>(itemType.Name.Replace("ViewModel", ""))
|
||||||
|
is IContentTemplateDescriptor descriptor)
|
||||||
|
{
|
||||||
|
return CreateDataTemplate(descriptor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return default;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override DataTemplate? SelectTemplateCore(object item,
|
||||||
|
DependencyObject container) => SelectTemplateCore(item);
|
||||||
|
|
||||||
|
private static DataTemplate CreateDataTemplate(IContentTemplateDescriptor descriptor)
|
||||||
|
{
|
||||||
|
string xamlString = @$"
|
||||||
|
<DataTemplate xmlns=""http://schemas.microsoft.com/winfx/2006/xaml/presentation""
|
||||||
|
xmlns:x=""http://schemas.microsoft.com/winfx/2006/xaml""
|
||||||
|
xmlns:local=""using:Toolkit.WinUI"">
|
||||||
|
<local:TemplateControl />
|
||||||
|
</DataTemplate>";
|
||||||
|
|
||||||
|
return (DataTemplate)XamlReader.Load(xamlString);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -11,6 +11,8 @@ public static class IServiceCollectionExtensions
|
|||||||
services.AddTransient<IDispatcherTimerFactory, DispatcherTimerFactory>();
|
services.AddTransient<IDispatcherTimerFactory, DispatcherTimerFactory>();
|
||||||
services.AddSingleton<IWindowRegistry, WindowRegistry>();
|
services.AddSingleton<IWindowRegistry, WindowRegistry>();
|
||||||
|
|
||||||
|
services.AddTransient<IContentTemplate, ContentTemplate>();
|
||||||
|
|
||||||
services.AddTransient((Func<IServiceProvider, IProxyServiceCollection<IComponentBuilder>>)(provider =>
|
services.AddTransient((Func<IServiceProvider, IProxyServiceCollection<IComponentBuilder>>)(provider =>
|
||||||
new ProxyServiceCollection<IComponentBuilder>(services =>
|
new ProxyServiceCollection<IComponentBuilder>(services =>
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -0,0 +1,79 @@
|
|||||||
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
using Microsoft.UI.Xaml;
|
||||||
|
using Microsoft.UI.Xaml.Controls;
|
||||||
|
using Microsoft.UI.Xaml.Data;
|
||||||
|
using Toolkit.Foundation;
|
||||||
|
|
||||||
|
namespace Toolkit.WinUI;
|
||||||
|
|
||||||
|
[Bindable]
|
||||||
|
public class TemplateControl :
|
||||||
|
ContentControl
|
||||||
|
{
|
||||||
|
public TemplateControl()
|
||||||
|
{
|
||||||
|
DefaultStyleKey = typeof(TemplateControl);
|
||||||
|
Loaded += OnLoaded;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnLoaded(object sender,
|
||||||
|
RoutedEventArgs args)
|
||||||
|
{
|
||||||
|
Loaded -= OnLoaded;
|
||||||
|
|
||||||
|
if (DataContext is IObservableViewModel observableViewModel)
|
||||||
|
{
|
||||||
|
if (observableViewModel.Provider is IServiceProvider provider)
|
||||||
|
{
|
||||||
|
if (provider.GetRequiredKeyedService<IContentTemplateDescriptor>(DataContext.GetType().Name.Replace("ViewModel", ""))
|
||||||
|
is IContentTemplateDescriptor descriptor)
|
||||||
|
{
|
||||||
|
if (provider.GetRequiredKeyedService(descriptor.TemplateType, descriptor.Key)
|
||||||
|
is FrameworkElement control)
|
||||||
|
{
|
||||||
|
void HandleLoaded(object? sender, RoutedEventArgs args)
|
||||||
|
{
|
||||||
|
control.Loaded -= HandleLoaded;
|
||||||
|
if (control.DataContext is object content)
|
||||||
|
{
|
||||||
|
if (content is IActivation activation)
|
||||||
|
{
|
||||||
|
activation.IsActive = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void HandleDataContextChanged(FrameworkElement? sender, DataContextChangedEventArgs args)
|
||||||
|
{
|
||||||
|
if (control.DataContext is object content)
|
||||||
|
{
|
||||||
|
if (content is IActivation activation)
|
||||||
|
{
|
||||||
|
activation.IsActive = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void HandleUnloaded(object? sender, RoutedEventArgs args)
|
||||||
|
{
|
||||||
|
control.Unloaded -= HandleUnloaded;
|
||||||
|
if (control.DataContext is object content)
|
||||||
|
{
|
||||||
|
if (content is IActivation activation)
|
||||||
|
{
|
||||||
|
activation.IsActive = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
control.Loaded += HandleLoaded;
|
||||||
|
control.Unloaded += HandleUnloaded;
|
||||||
|
control.DataContextChanged += HandleDataContextChanged;
|
||||||
|
|
||||||
|
Content = control;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -15,14 +15,13 @@
|
|||||||
<UseWinUI>true</UseWinUI>
|
<UseWinUI>true</UseWinUI>
|
||||||
<WindowsSdkPackageVersion>10.0.19041.41</WindowsSdkPackageVersion>
|
<WindowsSdkPackageVersion>10.0.19041.41</WindowsSdkPackageVersion>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Microsoft.Windows.SDK.BuildTools" Version="10.0.26100.1742" />
|
<PackageReference Include="Microsoft.Windows.SDK.BuildTools" Version="10.0.26100.1742" />
|
||||||
<PackageReference Include="Microsoft.WindowsAppSDK" Version="1.6.240923002" />
|
<PackageReference Include="Microsoft.WindowsAppSDK" Version="1.6.240923002" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\Toolkit.Foundation\Toolkit.Foundation.csproj" />
|
|
||||||
<ProjectReference Include="..\Toolkit.Windows\Toolkit.Windows.csproj" />
|
<ProjectReference Include="..\Toolkit.Windows\Toolkit.Windows.csproj" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
|
|||||||
@@ -2,6 +2,6 @@
|
|||||||
|
|
||||||
namespace Toolkit.Windows;
|
namespace Toolkit.Windows;
|
||||||
|
|
||||||
public interface IPointerMonitor :
|
public interface IPointer :
|
||||||
IInitialization,
|
IInitialization,
|
||||||
IDisposable;
|
IDisposable;
|
||||||
@@ -1,41 +1,51 @@
|
|||||||
SetWindowsHookEx
|
CallNextHookEx
|
||||||
GetModuleHandle
|
CreateSolidBrush
|
||||||
CallNextHookEx
|
|
||||||
GetPhysicalCursorPos
|
|
||||||
FindWindowEx
|
|
||||||
FindWindow
|
|
||||||
GetWindowRect
|
|
||||||
DestroyWindow
|
|
||||||
DefWindowProcW
|
|
||||||
CreateWindowExW
|
CreateWindowExW
|
||||||
RegisterClassW
|
DWM_WINDOW_CORNER_PREFERENCE
|
||||||
GetSystemMetrics
|
DefSubclassProc
|
||||||
MonitorFromWindow
|
DefWindowProcW
|
||||||
RegisterWindowMessage
|
DeleteObject
|
||||||
GetDpiForWindow
|
DestroyWindow
|
||||||
SetWindowPos
|
DwmSetWindowAttribute
|
||||||
SHCreateShellItemArrayFromDataObject
|
FillRect
|
||||||
Shell_NotifyIcon
|
FindWindow
|
||||||
GetSystemMetricsForDpi
|
FindWindowEx
|
||||||
GetSystemMetrics
|
GetClientRect
|
||||||
GetCurrentProcess
|
GetCurrentProcess
|
||||||
SetProcessInformation
|
GetDpiForWindow
|
||||||
PROCESS_POWER_THROTTLING_STATE
|
GetPhysicalCursorPos
|
||||||
|
GetSystemMetrics
|
||||||
|
GetSystemMetricsForDpi
|
||||||
|
GetWindowLong
|
||||||
|
GetWindowRect
|
||||||
|
MonitorFromWindow
|
||||||
PROCESS_POWER_THROTTLING_CURRENT_VERSION
|
PROCESS_POWER_THROTTLING_CURRENT_VERSION
|
||||||
PROCESS_POWER_THROTTLING_EXECUTION_SPEED
|
PROCESS_POWER_THROTTLING_EXECUTION_SPEED
|
||||||
SetPriorityClass
|
PROCESS_POWER_THROTTLING_STATE
|
||||||
WINDOW_STYLE
|
RegisterClassW
|
||||||
DefSubclassProc
|
RegisterWindowMessage
|
||||||
SetLayeredWindowAttributes
|
|
||||||
WM_ERASEBKGND
|
|
||||||
SetWindowSubclass
|
|
||||||
GetClientRect
|
|
||||||
CreateSolidBrush
|
|
||||||
DwmSetWindowAttribute
|
|
||||||
DWM_WINDOW_CORNER_PREFERENCE
|
|
||||||
FillRect
|
|
||||||
SetLayeredWindowAttributes
|
|
||||||
DeleteObject
|
|
||||||
RemoveWindowSubclass
|
RemoveWindowSubclass
|
||||||
GetWindowLong
|
SHCreateShellItemArrayFromDataObject
|
||||||
SetWindowLong
|
SetLayeredWindowAttributes
|
||||||
|
SetPriorityClass
|
||||||
|
SetProcessInformation
|
||||||
|
SetWindowLong
|
||||||
|
SetWindowPos
|
||||||
|
SetWindowSubclass
|
||||||
|
SetWindowsHookEx
|
||||||
|
Shell_NotifyIcon
|
||||||
|
WINDOW_STYLE
|
||||||
|
WM_ERASEBKGND
|
||||||
|
SetForegroundWindow
|
||||||
|
ShowWindow
|
||||||
|
GetCursorPos
|
||||||
|
UnregisterClass
|
||||||
|
CreateWindowEx
|
||||||
|
RegisterClass
|
||||||
|
DefWindowProc
|
||||||
|
GetMessage
|
||||||
|
TranslateMessage
|
||||||
|
DispatchMessage
|
||||||
|
PostQuitMessage
|
||||||
|
DestroyWindow
|
||||||
|
GetModuleHandle
|
||||||
@@ -1,11 +1,12 @@
|
|||||||
using CommunityToolkit.Mvvm.Messaging;
|
using CommunityToolkit.Mvvm.Messaging;
|
||||||
|
using System.Drawing;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
using Toolkit.Foundation;
|
using Toolkit.Foundation;
|
||||||
|
using Windows.Win32;
|
||||||
|
|
||||||
namespace Toolkit.Windows;
|
namespace Toolkit.Windows;
|
||||||
|
|
||||||
|
public class NotifyIcon(IWndProc wndProc,
|
||||||
public partial class NotifyIcon(IWndProc wndProc,
|
|
||||||
IMessenger messenger) :
|
IMessenger messenger) :
|
||||||
INotifyIcon,
|
INotifyIcon,
|
||||||
IRecipient<WndProcEventArgs>
|
IRecipient<WndProcEventArgs>
|
||||||
@@ -17,11 +18,6 @@ public partial class NotifyIcon(IWndProc wndProc,
|
|||||||
private bool isDisposed;
|
private bool isDisposed;
|
||||||
private NotifyIconData notifyIconData;
|
private NotifyIconData notifyIconData;
|
||||||
|
|
||||||
~NotifyIcon()
|
|
||||||
{
|
|
||||||
Dispose(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
private enum NotifyIconBalloonType
|
private enum NotifyIconBalloonType
|
||||||
{
|
{
|
||||||
None = 0x00,
|
None = 0x00,
|
||||||
@@ -66,6 +62,14 @@ public partial class NotifyIcon(IWndProc wndProc,
|
|||||||
GC.SuppressFinalize(this);
|
GC.SuppressFinalize(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public unsafe PointerLocation GetPointerPosition()
|
||||||
|
{
|
||||||
|
Point point = new();
|
||||||
|
_ = PInvoke.GetCursorPos(&point);
|
||||||
|
|
||||||
|
return new PointerLocation(point.X, point.Y);
|
||||||
|
}
|
||||||
|
|
||||||
public void Initialize()
|
public void Initialize()
|
||||||
{
|
{
|
||||||
messenger.RegisterAll(this);
|
messenger.RegisterAll(this);
|
||||||
@@ -79,15 +83,18 @@ public partial class NotifyIcon(IWndProc wndProc,
|
|||||||
switch (message.LParam)
|
switch (message.LParam)
|
||||||
{
|
{
|
||||||
case (uint)WndProcMessages.WM_LBUTTONUP:
|
case (uint)WndProcMessages.WM_LBUTTONUP:
|
||||||
messenger.Send(new NotifyIconInvokedEventArgs(PointerButton.Left));
|
messenger.Send(new NotifyIconInvokedEventArgs(PointerButton.Left,
|
||||||
|
GetPointerPosition()));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case (uint)WndProcMessages.WM_MBUTTONUP:
|
case (uint)WndProcMessages.WM_MBUTTONUP:
|
||||||
messenger.Send(new NotifyIconInvokedEventArgs(PointerButton.Middle));
|
messenger.Send(new NotifyIconInvokedEventArgs(PointerButton.Middle,
|
||||||
|
GetPointerPosition()));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case (uint)WndProcMessages.WM_RBUTTONUP:
|
case (uint)WndProcMessages.WM_RBUTTONUP:
|
||||||
messenger.Send(new NotifyIconInvokedEventArgs(PointerButton.Right));
|
messenger.Send(new NotifyIconInvokedEventArgs(PointerButton.Right,
|
||||||
|
GetPointerPosition()));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
namespace Toolkit.Windows;
|
namespace Toolkit.Windows;
|
||||||
|
|
||||||
public record NotifyIconInvokedEventArgs(PointerButton PointerButton);
|
public record NotifyIconInvokedEventArgs(PointerButton Button,
|
||||||
|
PointerLocation Location);
|
||||||
|
|||||||
@@ -59,4 +59,9 @@ public static partial class PInvoke
|
|||||||
|
|
||||||
public static void GetAppBarPosition(ref AppBarData appBarData) =>
|
public static void GetAppBarPosition(ref AppBarData appBarData) =>
|
||||||
SHAppBarMessage(AppBarMessage.GetTaskbarPos, ref appBarData);
|
SHAppBarMessage(AppBarMessage.GetTaskbarPos, ref appBarData);
|
||||||
|
|
||||||
|
internal static bool SetWindowSubclass(HWND value1, Func<HWND, uint, WPARAM, LPARAM, nuint, nuint, LRESULT> value2, int v1, nuint v2)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,8 +7,8 @@ using Windows.Win32.UI.WindowsAndMessaging;
|
|||||||
|
|
||||||
namespace Toolkit.Windows;
|
namespace Toolkit.Windows;
|
||||||
|
|
||||||
public class PointerMonitor(IMessenger messenger) :
|
public class Pointer(IMessenger messenger) :
|
||||||
IPointerMonitor
|
IPointer
|
||||||
{
|
{
|
||||||
private bool isDisposed;
|
private bool isDisposed;
|
||||||
private bool isPointerDrag;
|
private bool isPointerDrag;
|
||||||
@@ -16,7 +16,7 @@ public class PointerMonitor(IMessenger messenger) :
|
|||||||
private HOOKPROC? mouseEventDelegate;
|
private HOOKPROC? mouseEventDelegate;
|
||||||
private UnhookWindowsHookExSafeHandle? mouseHandle;
|
private UnhookWindowsHookExSafeHandle? mouseHandle;
|
||||||
|
|
||||||
~PointerMonitor()
|
~Pointer()
|
||||||
{
|
{
|
||||||
Dispose(false);
|
Dispose(false);
|
||||||
}
|
}
|
||||||
@@ -126,9 +126,9 @@ public class PointerMonitor(IMessenger messenger) :
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private unsafe bool TryGetPointer(out Point point)
|
private unsafe bool TryGetPointer(out System.Drawing.Point point)
|
||||||
{
|
{
|
||||||
fixed (Point* lpPointLocal = &point)
|
fixed (System.Drawing.Point* lpPointLocal = &point)
|
||||||
{
|
{
|
||||||
return PInvoke.GetPhysicalCursorPos(lpPointLocal);
|
return PInvoke.GetPhysicalCursorPos(lpPointLocal);
|
||||||
}
|
}
|
||||||
@@ -136,7 +136,7 @@ public class PointerMonitor(IMessenger messenger) :
|
|||||||
|
|
||||||
private bool TryGetPointerLocation([MaybeNullWhen(false)] out PointerLocation location)
|
private bool TryGetPointerLocation([MaybeNullWhen(false)] out PointerLocation location)
|
||||||
{
|
{
|
||||||
if (TryGetPointer(out Point point))
|
if (TryGetPointer(out System.Drawing.Point point))
|
||||||
{
|
{
|
||||||
location = new PointerLocation(point.X, point.Y);
|
location = new PointerLocation(point.X, point.Y);
|
||||||
return true;
|
return true;
|
||||||
@@ -16,7 +16,10 @@ public record Rect
|
|||||||
}
|
}
|
||||||
|
|
||||||
public int X { get; }
|
public int X { get; }
|
||||||
|
|
||||||
public int Y { get; }
|
public int Y { get; }
|
||||||
|
|
||||||
public int Width { get; }
|
public int Width { get; }
|
||||||
|
|
||||||
public int Height { get; }
|
public int Height { get; }
|
||||||
}
|
}
|
||||||
@@ -40,7 +40,7 @@ public class Taskbar(IMessenger messenger,
|
|||||||
return state;
|
return state;
|
||||||
}
|
}
|
||||||
|
|
||||||
public IntPtr GetHandle() => WindowHelper.Find("Shell_TrayWnd");
|
public IntPtr GetHandle() => WindowHelper.FindWindow("Shell_TrayWnd");
|
||||||
|
|
||||||
public void Receive(WndProcEventArgs args)
|
public void Receive(WndProcEventArgs args)
|
||||||
{
|
{
|
||||||
@@ -63,7 +63,7 @@ public class Taskbar(IMessenger messenger,
|
|||||||
public void Receive(PointerMovedEventArgs args)
|
public void Receive(PointerMovedEventArgs args)
|
||||||
{
|
{
|
||||||
nint taskbarHandle = GetHandle();
|
nint taskbarHandle = GetHandle();
|
||||||
if (WindowHelper.TryGetBounds(taskbarHandle, out Rect? rect))
|
if (WindowHelper.TryGetWindowBounds(taskbarHandle, out Rect? rect))
|
||||||
{
|
{
|
||||||
if (args.Location.IsWithinBounds(rect))
|
if (args.Location.IsWithinBounds(rect))
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -49,7 +49,7 @@ public class TaskbarButtonMonitor :
|
|||||||
taskListHandle = taskbarList.GetHandle();
|
taskListHandle = taskbarList.GetHandle();
|
||||||
taskListElement = clientUIAutomation.ElementFromHandle(taskListHandle);
|
taskListElement = clientUIAutomation.ElementFromHandle(taskListHandle);
|
||||||
|
|
||||||
if (WindowHelper.TryGetBounds(taskListHandle, out Rect? rect))
|
if (WindowHelper.TryGetWindowBounds(taskListHandle, out Rect? rect))
|
||||||
{
|
{
|
||||||
taskbarRectCache = rect;
|
taskbarRectCache = rect;
|
||||||
}
|
}
|
||||||
@@ -60,7 +60,7 @@ public class TaskbarButtonMonitor :
|
|||||||
|
|
||||||
private bool CheckDirtyTaskbarRegion()
|
private bool CheckDirtyTaskbarRegion()
|
||||||
{
|
{
|
||||||
if (WindowHelper.TryGetBounds(taskListHandle, out Rect? rect))
|
if (WindowHelper.TryGetWindowBounds(taskListHandle, out Rect? rect))
|
||||||
{
|
{
|
||||||
if (taskbarRectCache?.Width != rect.Width ||
|
if (taskbarRectCache?.Width != rect.Width ||
|
||||||
taskbarRectCache?.Height != rect.Height)
|
taskbarRectCache?.Height != rect.Height)
|
||||||
|
|||||||
@@ -5,8 +5,8 @@ public class TaskbarList(ITaskbar taskbar) :
|
|||||||
{
|
{
|
||||||
public IntPtr GetHandle()
|
public IntPtr GetHandle()
|
||||||
{
|
{
|
||||||
nint rebarHandle = WindowHelper.Find("ReBarWindow32", taskbar.GetHandle());
|
nint rebarHandle = WindowHelper.FindWindow("ReBarWindow32", taskbar.GetHandle());
|
||||||
nint taskHandle = WindowHelper.Find("MSTaskSwWClass", rebarHandle);
|
nint taskHandle = WindowHelper.FindWindow("MSTaskSwWClass", rebarHandle);
|
||||||
return WindowHelper.Find("MSTaskListWClass", taskHandle);
|
return WindowHelper.FindWindow("MSTaskListWClass", taskHandle);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,35 +7,44 @@ namespace Toolkit.Windows;
|
|||||||
|
|
||||||
public class WindowHelper
|
public class WindowHelper
|
||||||
{
|
{
|
||||||
public static IntPtr GetHandle(string windowName) => PInvoke.FindWindow(windowName, null);
|
public static IntPtr FindWindow(string name) =>
|
||||||
|
PInvoke.FindWindow(name, null);
|
||||||
|
|
||||||
public static uint GetDpi(IntPtr handle) => PInvoke.GetDpiForWindow((HWND)handle);
|
public static IntPtr FindWindow(string name, IntPtr handle) =>
|
||||||
|
PInvoke.FindWindowEx(new HWND(handle), new HWND(), name, null);
|
||||||
|
|
||||||
public static void BringToForeground(HWND handle)
|
public static uint GetDpi(IntPtr handle) =>
|
||||||
{
|
PInvoke.GetDpiForWindow((HWND)handle);
|
||||||
if (TryGetBoundsUnsafe(handle, out RECT bounds))
|
|
||||||
{
|
|
||||||
PInvoke.SetWindowPos(handle, new HWND(), bounds.left, bounds.top, bounds.right -
|
|
||||||
bounds.left, bounds.bottom - bounds.top, SET_WINDOW_POS_FLAGS.SWP_SHOWWINDOW | SET_WINDOW_POS_FLAGS.SWP_NOACTIVATE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static IntPtr Find(string windowName) =>
|
public static IntPtr GetWindowHandle(string name) =>
|
||||||
PInvoke.FindWindow(windowName, null);
|
PInvoke.FindWindow(name, null);
|
||||||
|
|
||||||
public static IntPtr Find(string windowName, IntPtr parentHandle) =>
|
public static bool HideWindow(IntPtr hWnd) =>
|
||||||
PInvoke.FindWindowEx(new HWND(parentHandle), new HWND(), windowName, null);
|
PInvoke.ShowWindow(new HWND(hWnd), SHOW_WINDOW_CMD.SW_HIDE);
|
||||||
|
|
||||||
public static void MoveAndResize(HWND handle, int x, int y, int width, int height) =>
|
public static void MoveAndResizeWindow(HWND handle, int x, int y, int width, int height) =>
|
||||||
PInvoke.SetWindowPos(handle, new HWND(), x, y, width, height, 0);
|
PInvoke.SetWindowPos(handle, new HWND(), x, y, width, height, 0);
|
||||||
|
|
||||||
public static bool TryGetBounds(IntPtr handle,
|
public static bool SetForegroundWindow(HWND handle)
|
||||||
|
{
|
||||||
|
if (TryGetWindowBoundsUnsafe(handle, out RECT bounds))
|
||||||
|
{
|
||||||
|
return PInvoke.SetWindowPos(handle, new HWND(), bounds.left, bounds.top, bounds.right -
|
||||||
|
bounds.left, bounds.bottom - bounds.top, SET_WINDOW_POS_FLAGS.SWP_SHOWWINDOW | SET_WINDOW_POS_FLAGS.SWP_NOACTIVATE) == 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool ShowWindow(IntPtr hWnd) =>
|
||||||
|
PInvoke.ShowWindow(new HWND(hWnd), SHOW_WINDOW_CMD.SW_SHOW);
|
||||||
|
|
||||||
|
public static bool TryGetWindowBounds(IntPtr handle,
|
||||||
[MaybeNullWhen(false)] out Rect rect)
|
[MaybeNullWhen(false)] out Rect rect)
|
||||||
{
|
{
|
||||||
if (TryGetBoundsUnsafe(handle, out RECT unsafeRect))
|
if (TryGetWindowBoundsUnsafe(handle, out RECT unsafeRect))
|
||||||
{
|
{
|
||||||
rect = new Rect(unsafeRect.left, unsafeRect.top, unsafeRect.right - unsafeRect.left, unsafeRect.bottom - unsafeRect.top);
|
rect = new Rect(unsafeRect.left, unsafeRect.top, unsafeRect.right - unsafeRect.left, unsafeRect.bottom - unsafeRect.top);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -43,7 +52,7 @@ public class WindowHelper
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static unsafe bool TryGetBoundsUnsafe(IntPtr handle, out RECT rect)
|
private static unsafe bool TryGetWindowBoundsUnsafe(IntPtr handle, out RECT rect)
|
||||||
{
|
{
|
||||||
fixed (RECT* lpRectLocal = &rect)
|
fixed (RECT* lpRectLocal = &rect)
|
||||||
{
|
{
|
||||||
|
|||||||
+42
-37
@@ -1,7 +1,7 @@
|
|||||||
using CommunityToolkit.Mvvm.Messaging;
|
using CommunityToolkit.Mvvm.Messaging;
|
||||||
|
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;
|
||||||
@@ -10,56 +10,61 @@ public class WndProc(IMessenger messenger) :
|
|||||||
IWndProc
|
IWndProc
|
||||||
{
|
{
|
||||||
private WNDPROC? handler;
|
private WNDPROC? handler;
|
||||||
|
private bool isDisposed;
|
||||||
|
|
||||||
|
~WndProc()
|
||||||
|
{
|
||||||
|
Dispose(false);
|
||||||
|
}
|
||||||
|
|
||||||
public IntPtr Handle { get; private set; }
|
public IntPtr Handle { get; private set; }
|
||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
|
Dispose(true);
|
||||||
GC.SuppressFinalize(this);
|
GC.SuppressFinalize(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Initialize() => InitializeWndProc();
|
||||||
|
|
||||||
|
protected virtual void Dispose(bool disposing)
|
||||||
|
{
|
||||||
|
if (isDisposed)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
isDisposed = true;
|
||||||
|
|
||||||
PInvoke.DestroyWindow((HWND)Handle);
|
PInvoke.DestroyWindow((HWND)Handle);
|
||||||
}
|
}
|
||||||
|
private LRESULT HandleWndProc(HWND hWnd, uint msg,
|
||||||
|
WPARAM wParam, LPARAM lParam)
|
||||||
|
{
|
||||||
|
messenger.Send(new WndProcEventArgs(msg,
|
||||||
|
(uint)wParam.Value,
|
||||||
|
(uint)lParam.Value));
|
||||||
|
|
||||||
|
return PInvoke.DefWindowProc(hWnd, msg, wParam, lParam);
|
||||||
|
}
|
||||||
|
|
||||||
private unsafe void InitializeWndProc()
|
private unsafe void InitializeWndProc()
|
||||||
{
|
{
|
||||||
string windowName = Guid.NewGuid().ToString();
|
string windowId = $"WndProc_Handler_{Guid.NewGuid()}";
|
||||||
handler = Wndproc;
|
handler = HandleWndProc;
|
||||||
|
|
||||||
WNDCLASSW wndProcWindow;
|
fixed (char* className = windowId)
|
||||||
|
|
||||||
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);
|
WNDCLASSW wndCLass = new()
|
||||||
|
{
|
||||||
|
lpfnWndProc = handler,
|
||||||
|
lpszClassName = className,
|
||||||
|
};
|
||||||
|
|
||||||
|
_ = PInvoke.RegisterClass(wndCLass);
|
||||||
}
|
}
|
||||||
|
|
||||||
fixed (char* className = windowName)
|
Handle = PInvoke.CreateWindowEx(0, windowId, windowId, 0, 0, 0, 0, 0,
|
||||||
{
|
new HWND(IntPtr.Zero), null, null, null);
|
||||||
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)
|
|
||||||
{
|
|
||||||
messenger.Send(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