Windows: restore main window after Pick location (fixes #3)#4
Conversation
BeginPick minimizes the owner so the user can pick coordinates beneath the app. Window_StateChanged turns that minimize into Hide(), which leaves the window with Visibility.Hidden. The pick callbacks only set WindowState = Normal, which doesn't unhide the window — Activate() on a hidden window is a no-op too. Result: coordinates were captured but the app appeared to vanish. Fix: call Show() in OnLocationPicked and OnPickCancelled, matching what RestoreFromTray already does. Fixes #3 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The pick overlay was showing but clicks were never captured. Symptom:
overlay's "Click to select location | ESC to cancel" hint stays on
screen, X/Y boxes are never populated, and the previous OnLocationPicked
restore code never runs (which is why the earlier Show() fix alone did
not help — the callback was never reaching it).
Root cause (likely): SetHook passed
GetModuleHandle(MainModule.ModuleName) — i.e. GetModuleHandle("QuadClicker.exe").
On .NET 10 apphost / single-file deployments the loaded EXE module can
register under a name that does not match Process.MainModule.ModuleName,
so the lookup silently returns 0. SetWindowsHookEx then refuses to
install with hMod=0, returns IntPtr.Zero, and the hook never fires.
Fix: pass NULL for hMod (the Win32-documented form: Windows substitutes
the EXE's HMODULE). Required widening NativeMethods.GetModuleHandle to
accept string?.
Also adds file-based diagnostics at %APPDATA%\QuadClicker\picker.log
covering the BeginPick → ShowOverlay → SetHook → HookCallback → dispatch
chain, plus a visible red error in the overlay when SetHook fails — so
if the picker still misbehaves we have evidence instead of guessing.
Refs #3
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
Pushed What the previous fix actually addressed: restoring the main window after Real root cause (likely): Fix: pass Also added file-based diagnostics at Test plan extension:
|
…TANCE (#3) Diagnostic log captured the actual root cause: EntryPointNotFoundException: Unable to find an entry point named 'GetModuleHandle' in DLL 'kernel32.dll'. kernel32.dll only exports GetModuleHandleA / GetModuleHandleW. The [DllImport(CharSet=Auto)] convention auto-appended the W suffix, but the [LibraryImport] source generator does not — even with StringMarshalling.Utf16 you must set EntryPoint explicitly. Calling NativeMethods.GetModuleHandle(...) therefore threw at runtime, SetHook blew up before installing the WH_MOUSE_LL hook (after the overlay had already been shown), and clicks went nowhere. Fix: drop the GetModuleHandle P/Invoke entirely and use Marshal.GetHINSTANCE(typeof(LocationPicker).Module) for hMod. WH_MOUSE_LL hooks run in the calling thread regardless of hMod, so any valid module handle works — and this avoids the marshaler edge case entirely. The diagnostics added in c10a9e8 stay; they are what surfaced this within one user-test cycle. Refs #3 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
Pushed kernel32 only exports Fix: drop the Diagnostics stay — they paid for themselves immediately and will catch the next regression in this area without another guess-and-build cycle. |
Summary
BeginPickminimizes the owner so the target is visible;Window_StateChangedturns that intoHide(). The pick callbacks only restoredWindowState, which does not undoHide()in WPF.Show()toOnLocationPickedandOnPickCancelled, matching the existingRestoreFromTraypattern.Test plan
dotnet build windows/QuadClicker.csproj -c Release— clean🤖 Generated with Claude Code