fix unexpected window move when right click or double click on desktop window

This commit is contained in:
Kang Yu 2023-10-29 16:11:43 -07:00
parent 759845d0d8
commit cc7b7fa925
2 changed files with 100 additions and 27 deletions

View file

@ -162,6 +162,10 @@ namespace PersistentWindows.Common
public System.Drawing.Icon icon = null;
private int mouseEvent = -1;
private IntPtr mouseHook = IntPtr.Zero;
private User32.MouseHookHandler winHookHandler;
// running thread
private HashSet<Thread> runningThreads = new HashSet<Thread>();
@ -318,6 +322,11 @@ namespace PersistentWindows.Common
if (realForeGroundWindow == vacantDeskWindow)
{
if (mouseEvent != 2)
return;
mouseEvent = 0; //triger only once
//only left mouse button click goes through
if (!ctrl_key_pressed && !alt_key_pressed)
{
//restore window to previous background position
@ -478,6 +487,13 @@ namespace PersistentWindows.Common
});
ProcessModule module = Process.GetCurrentProcess().MainModule;
IntPtr moduleHandle = Kernel32.GetModuleHandle(module.ModuleName);
//IntPtr moduleHandle = Kernel32.GetModuleHandle(null);
winHookHandler = MouseHookFunc;
mouseHook = User32.SetWindowsHookEx(User32.WH_MOUSE_LL, winHookHandler, moduleHandle, 0);
int err = Marshal.GetLastWin32Error();
Log.Error($"setwindowhook {err}");
winEventsCaptureDelegate = WinEventProc;
@ -1184,6 +1200,18 @@ namespace PersistentWindows.Common
|| (style & (long)WindowStyleFlags.SYSMENU) != 0L;
}
private IntPtr MouseHookFunc(int nCode, uint wParam, IntPtr lParam)
{
// parse system messages
if (nCode >= 0)
{
int action = (int)wParam - 0x0200;
if (action > 0) //not a mouse move event
mouseEvent = action;
}
return User32.CallNextHookEx(mouseHook, nCode, wParam, lParam);
}
private void WinEventProc(IntPtr hWinEventHook, User32Events eventType, IntPtr hwnd, int idObject, int idChild, uint dwEventThread, uint dwmsEventTime)
{
{
@ -1417,7 +1445,8 @@ namespace PersistentWindows.Common
realForeGroundWindow = hwnd;
if (hwnd != vacantDeskWindow)
foreGroundWindow = hwnd;
foregroundTimer.Change(100, Timeout.Infinite);
foregroundTimer.Change(200, Timeout.Infinite);
// Occasionaly OS might bring a window to foreground upon sleep
// If the window move is initiated by OS (before sleep),
@ -3779,6 +3808,8 @@ namespace PersistentWindows.Common
{
User32.UnhookWinEvent(handle);
}
User32.UnhookWindowsHookEx(mouseHook);
}
}

View file

@ -179,11 +179,33 @@ namespace PersistentWindows.Common.WinApiBridge
public class User32
{
#region EnumDisplayMonitors
#region delegates
public delegate IntPtr MouseHookHandler(int nCode, uint wParam, IntPtr lParam);
public delegate bool MonitorEnumDelegate(IntPtr hMonitor, IntPtr hdcMonitor, ref RECT lprcMonitor, IntPtr dwData);
public delegate void WinEventDelegate(IntPtr hWinEventHook,
User32Events eventType,
IntPtr hwnd,
int idObject,
int idChild,
uint dwEventThread,
uint dwmsEventTime);
#endregion
[DllImport("user32.dll")]
public static extern IntPtr SetWinEventHook(
User32Events eventMin,
User32Events eventMax,
IntPtr hmodWinEventProc,
WinEventDelegate lpfnWinEventProc,
uint idProcess,
uint idThread,
uint dwFlags);
[DllImport("user32.dll")]
public static extern bool UnhookWinEvent(IntPtr hWinEventHook);
[DllImport("user32.dll")]
public static extern bool EnumDisplayMonitors(IntPtr hdc, IntPtr lprcClip, MonitorEnumDelegate lpfnEnum, IntPtr dwData);
#endregion
[DllImport("user32.dll", CharSet = CharSet.Auto)]
public static extern bool GetMonitorInfo(IntPtr hMonitor, ref MonitorInfo lpmi);
@ -464,39 +486,59 @@ namespace PersistentWindows.Common.WinApiBridge
return SetThreadDpiAwarenessContext(dpi_awareness_cxt);
}
#region Hooks
[DllImport("user32.dll")]
public static extern IntPtr CallNextHookEx(IntPtr hhk, int nCode, IntPtr wParam, IntPtr lParam);
#endregion
public const int WH_MOUSE = 7;
public const int WH_MOUSE_LL = 14;
#region WinEvent Hooks
public enum MouseMessages
{
WM_LBUTTONDOWN = 0x0201,
WM_LBUTTONUP = 0x0202,
WM_MOUSEMOVE = 0x0200,
WM_MOUSEWHEEL = 0x020A,
WM_RBUTTONDOWN = 0x0204,
WM_RBUTTONUP = 0x0205,
WM_LBUTTONDBLCLK = 0x0203,
WM_MBUTTONDOWN = 0x0207,
WM_MBUTTONUP = 0x0208
}
public delegate void WinEventDelegate(IntPtr hWinEventHook,
User32Events eventType,
IntPtr hwnd,
int idObject,
int idChild,
uint dwEventThread,
uint dwmsEventTime);
[StructLayout(LayoutKind.Sequential)]
public struct MOUSEHOOKSTRUCT
{
public POINT pt;
public IntPtr hwnd;
public uint wHitTestCode;
public IntPtr dwExtraInfo;
}
[DllImport("user32.dll")]
public static extern IntPtr SetWinEventHook(
User32Events eventMin,
User32Events eventMax,
IntPtr hmodWinEventProc,
WinEventDelegate lpfnWinEventProc,
uint idProcess,
uint idThread,
uint dwFlags);
[StructLayout(LayoutKind.Sequential)]
public struct MSLLHOOKSTRUCT
{
public POINT pt;
public uint mouseData;
public uint flags;
public uint time;
public IntPtr dwExtraInfo;
}
[DllImport("user32.dll")]
public static extern bool UnhookWinEvent(IntPtr hWinEventHook);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern IntPtr SetWindowsHookEx(int idHook,
MouseHookHandler lpfn, IntPtr hMod, uint dwThreadId);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool UnhookWindowsHookEx(IntPtr hhk);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern IntPtr CallNextHookEx(IntPtr hhk, int nCode, uint wParam, IntPtr lParam);
#endregion
}
public class Kernel32
{
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern IntPtr GetModuleHandle(string lpModuleName);
[DllImport("kernel32.dll", SetLastError = true)]
public static extern bool QueryFullProcessImageName([In]IntPtr hProcess, [In]int dwFlags, [Out]StringBuilder lpExeName, ref int lpdwSize);