From 366a935b3617142b1ab850839492cd75d7510ac7 Mon Sep 17 00:00:00 2001 From: Jumar Macato <16554748+jmacato@users.noreply.github.com> Date: Sat, 13 Jan 2024 10:16:19 +0800 Subject: [PATCH] Port DragMove logic from WPF (#14186) * Port DragMove logic from WPF to fix missing PointerReleased event on drag out. * remove WindowState.Normal check --- .../Avalonia.Win32/Interop/UnmanagedMethods.cs | 7 ++++++- src/Windows/Avalonia.Win32/WindowImpl.cs | 18 ++++++++++++++++-- 2 files changed, 22 insertions(+), 3 deletions(-) diff --git a/src/Windows/Avalonia.Win32/Interop/UnmanagedMethods.cs b/src/Windows/Avalonia.Win32/Interop/UnmanagedMethods.cs index 445bec979e..6c64603377 100644 --- a/src/Windows/Avalonia.Win32/Interop/UnmanagedMethods.cs +++ b/src/Windows/Avalonia.Win32/Interop/UnmanagedMethods.cs @@ -1180,7 +1180,12 @@ namespace Avalonia.Win32.Interop [DllImport("user32.dll", EntryPoint = "DefWindowProcW")] public static extern IntPtr DefWindowProc(IntPtr hWnd, uint msg, IntPtr wParam, IntPtr lParam); - + + public const int SC_MOUSEMOVE = 0xf012; + + [DllImport("user32.dll", CharSet = CharSet.Unicode, EntryPoint = "SendMessageW")] + public static extern IntPtr SendMessage(IntPtr hWnd, int Msg, IntPtr wParam, IntPtr lParam); + [DllImport("user32.dll", EntryPoint = "DispatchMessageW")] public static extern IntPtr DispatchMessage(ref MSG lpmsg); diff --git a/src/Windows/Avalonia.Win32/WindowImpl.cs b/src/Windows/Avalonia.Win32/WindowImpl.cs index 0a75732182..50ed39193c 100644 --- a/src/Windows/Avalonia.Win32/WindowImpl.cs +++ b/src/Windows/Avalonia.Win32/WindowImpl.cs @@ -695,8 +695,22 @@ namespace Avalonia.Win32 public void BeginMoveDrag(PointerPressedEventArgs e) { e.Pointer.Capture(null); - DefWindowProc(_hwnd, (int)WindowsMessage.WM_NCLBUTTONDOWN, - new IntPtr((int)HitTestValues.HTCAPTION), IntPtr.Zero); + + // Mouse.LeftButton actually reflects the primary button user is using. + // So we don't need to check whether the button has been swapped here. + if (e.Pointer.IsPrimary) + { + // SendMessage's return value is dependent on the message send. WM_SYSCOMMAND + // and WM_LBUTTONUP return value just signify whether the WndProc handled the + // message or not, so they are not interesting + + SendMessage(_hwnd, (int)WindowsMessage.WM_SYSCOMMAND, (IntPtr)SC_MOUSEMOVE, IntPtr.Zero); + SendMessage(_hwnd, (int)WindowsMessage.WM_LBUTTONUP, IntPtr.Zero, IntPtr.Zero); + } + else + { + throw new InvalidOperationException("BeginMoveDrag Failed"); + } } public void BeginResizeDrag(WindowEdge edge, PointerPressedEventArgs e)