如何在Blazor Hybrid应用中检测窗口移动事件?
在Windows平台的Blazor Hybrid应用中检测窗口移动事件
你可以通过两种方式实现Windows平台下的窗口移动检测,一种是利用MAUI官方修复后的API,另一种是直接使用Win32底层窗口消息监听:
方法1:基于MAUI AppWindow的消息监听
由于你提到的相关GitHub问题已修复,现在可以通过Microsoft.UI.Windowing.AppWindow的消息事件捕获窗口移动信号。核心思路是监听Win32的WM_MOVE消息,该消息会在窗口位置改变时触发。
#if WINDOWS using Microsoft.UI.Windowing; using Microsoft.UI.Xaml; #endif // 获取当前MAUI窗口实例 var currentMauiWindow = Application.Current.Windows.First(); #if WINDOWS // 转换为WinUI窗口,获取对应的AppWindow var winuiWindow = currentMauiWindow.Handler.PlatformView as Window; var appWindow = AppWindow.GetFromWindowId(winuiWindow.WindowId); // 监听窗口消息 appWindow.WindowMessageReceived += (sender, args) => { const uint WM_MOVE = 0x0003; if (args.Message.MessageId == WM_MOVE) { // 获取最新窗口位置 var windowPosition = appWindow.Position; // 这里添加你的移动后处理逻辑 Console.WriteLine($"窗口已移动至:X={windowPosition.X}, Y={windowPosition.Y}"); } }; #endif
方法2:Win32底层窗口过程钩子
如果需要更灵活的控制,可直接通过Win32API替换窗口过程,监听WM_MOVE或WM_WINDOWPOSCHANGED消息(后者会在窗口大小、位置改变时触发)。
#if WINDOWS using Windows.Win32; using Windows.Win32.Foundation; using Windows.Win32.UI.WindowsAndMessaging; using System.Runtime.InteropServices; #endif private nint _originalWndProc; // 初始化钩子 public void SetupWindowMoveListener() { #if WINDOWS var currentMauiWindow = Application.Current.Windows.First(); // 获取窗口句柄 var hwnd = new HWND((nint)currentMauiWindow.Handler.PlatformView.GetType() .GetProperty("WindowHandle") .GetValue(currentMauiWindow.Handler.PlatformView)); // 替换窗口过程 _originalWndProc = PInvoke.SetWindowLongPtr(hwnd, WINDOW_LONG_PTR_INDEX.GWL_WNDPROC, (nint)Marshal.GetFunctionPointerForDelegate(new WNDPROC(CustomWndProc))); #endif } // 自定义窗口过程 private nint CustomWndProc(HWND hwnd, uint msg, WPARAM wParam, LPARAM lParam) { const uint WM_MOVE = 0x0003; const uint WM_WINDOWPOSCHANGED = 0x0047; if (msg == WM_MOVE || msg == WM_WINDOWPOSCHANGED) { RECT windowRect = new(); PInvoke.GetWindowRect(hwnd, ref windowRect); Console.WriteLine($"窗口位置更新:X={windowRect.left}, Y={windowRect.top}"); } // 调用原始窗口过程,保证窗口正常运作 return PInvoke.CallWindowProc(_originalWndProc, hwnd, msg, wParam, lParam); } // 窗口关闭时恢复原始窗口过程,避免内存泄漏 public void CleanupWindowListener() { #if WINDOWS var currentMauiWindow = Application.Current.Windows.First(); var hwnd = new HWND((nint)currentMauiWindow.Handler.PlatformView.GetType() .GetProperty("WindowHandle") .GetValue(currentMauiWindow.Handler.PlatformView)); PInvoke.SetWindowLongPtr(hwnd, WINDOW_LONG_PTR_INDEX.GWL_WNDPROC, _originalWndProc); #endif }
关于WebView2的关联说明
Tauri的onMoved事件本质也是通过监听Win32窗口消息实现的,和上述两种方案的核心逻辑一致,都是捕获窗口移动相关的系统消息来触发事件回调。
内容的提问来源于stack exchange,提问作者VassilisM
相关产品推荐
相关产品推荐

