using CommunityToolkit.Mvvm.Input; using Microsoft.UI.Dispatching; using System.Runtime.InteropServices; using HaloPixelToolBox.Client.Interface.Services; using HaloPixelToolBox.Client.Utilities.Helpers; using HaloPixelToolBox.Client.Utilities.Helpers.Win32; using HaloPixelToolBox.Client.Views; using XFEExtension.NetCore.WinUIHelper.Implements; using XFEExtension.NetCore.WinUIHelper.Utilities; namespace HaloPixelToolBox.Client.ViewModels; public partial class TrayMenuPageViewModel : ServiceBaseViewModelBase { IntPtr _mouseHook = new(); LowLevelMouseProc? _proc; public Window MenuWindow { get; set; } public DispatcherQueue DispatcherQueue => MenuWindow.DispatcherQueue; public TrayMenuPageViewModel(Window window) { MenuWindow = window; AutoNavigationParameterService.ParameterChange += AutoNavigationParameterService_ParameterChange; } private void AutoNavigationParameterService_ParameterChange(object? sender, string? e) { AutoNavigationParameterService.CurrentPage?.Unloaded += CurrentPage_Unloaded; InstallMouseHook(); } private void CurrentPage_Unloaded(object sender, RoutedEventArgs e) { UnInstallMouseHook(); } void UnInstallMouseHook() { if (_mouseHook != IntPtr.Zero) { Win32Helper.UnhookWindowsHookEx(_mouseHook); _mouseHook = IntPtr.Zero; } } void InstallMouseHook() { _proc = HookCallback; _mouseHook = Win32Helper.SetWindowsHookEx(Win32Helper.WH_MOUSE_LL, _proc, IntPtr.Zero, 0); } IntPtr HookCallback(int nCode, IntPtr wParam, IntPtr lParam) { try { if (nCode >= 0 && wParam == Win32Helper.WM_LBUTTONDOWN) { var hook = Marshal.PtrToStructure(lParam); var pt = hook.pt; var hwnd = WinRT.Interop.WindowNative.GetWindowHandle(MenuWindow); Win32Helper.GetWindowRect(hwnd, out var rect); var inside = pt.x >= rect.Left && pt.x <= rect.Right && pt.y >= rect.Top && pt.y <= rect.Bottom; if (!inside) { DispatcherQueue.TryEnqueue(() => { MenuWindow.Close(); }); } } } catch { } return Win32Helper.CallNextHookEx(_mouseHook, nCode, wParam, lParam); } [RelayCommand] void Show() { ServiceManager.GetGlobalService()?.ShowWindow(); NavigationViewService?.NavigateTo(); MenuWindow.Close(); } [RelayCommand] void OpenSettings() { ServiceManager.GetGlobalService()?.ShowWindow(); NavigationViewService?.NavigateTo(); MenuWindow.Close(); } [RelayCommand] static void Exit() => ServiceManager.GetGlobalService()?.ExitApp(); }