Project verify skill: drive the GUI via PostMessage + PrintWindow
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,50 @@
|
|||||||
|
---
|
||||||
|
name: verify
|
||||||
|
description: Build, launch, and drive the vRIO WinForms app to verify changes at the GUI surface — screenshots via PrintWindow, input via PostMessage, no focus stealing.
|
||||||
|
---
|
||||||
|
|
||||||
|
# Verifying vRIO changes
|
||||||
|
|
||||||
|
Build + tests (tests are CI's job; run the app for verification):
|
||||||
|
|
||||||
|
```powershell
|
||||||
|
dotnet build vrio.sln -v q -nologo # Debug
|
||||||
|
# exe: src\VRio.App\bin\Debug\net48\VRio.App.exe
|
||||||
|
```
|
||||||
|
|
||||||
|
## Driving the GUI without touching the user's desktop
|
||||||
|
|
||||||
|
This is the user's live desktop — **never** use SetForegroundWindow +
|
||||||
|
SendKeys/mouse_event: focus-stealing prevention leaves the app behind
|
||||||
|
VS Code and your clicks land in the user's windows. Instead:
|
||||||
|
|
||||||
|
- **Screenshots**: `PrintWindow(hwnd, dc, 2)` (PW_RENDERFULLCONTENT) —
|
||||||
|
captures the window even when occluded. CopyFromScreen captures
|
||||||
|
whatever is on top; don't use it.
|
||||||
|
- **Canvas input** (stick drags, cell clicks): PostMessage
|
||||||
|
`WM_LBUTTONDOWN/WM_MOUSEMOVE/WM_LBUTTONUP` straight to the canvas
|
||||||
|
child HWND. Find it by descending `RealChildWindowFromPoint` from the
|
||||||
|
form. Canvas geometry is compile-time constant (PanelCanvas.cs):
|
||||||
|
CellW=66, BoxXY = x 416..496, y 6..74 (X/Y stick box).
|
||||||
|
The **first** posted drag after launch can half-land (only the
|
||||||
|
button-down registers); do a throwaway drag first, then the measured
|
||||||
|
one, screenshot **while held** (spring-back recenters on up).
|
||||||
|
- **Checkboxes/buttons**: WinForms controls expose no UIA TogglePattern
|
||||||
|
(they surface as bare Panes) and don't answer BM_GETCHECK — but
|
||||||
|
`SendMessage(hwnd, BM_CLICK, 0, 0)` works. Get the HWND from the UIA
|
||||||
|
element's NativeWindowHandle (find by Name).
|
||||||
|
- Pattern that works: Add-Type user32 P/Invokes, Start-Process the exe,
|
||||||
|
drive via messages, PrintWindow screenshot to the scratchpad, kill
|
||||||
|
the process in `finally`.
|
||||||
|
|
||||||
|
## Environment gotchas
|
||||||
|
|
||||||
|
- Bindings load from `%APPDATA%\vRIO\bindings.txt` (the user's file),
|
||||||
|
not the built-in defaults — arrow keys are bound to Hat *buttons*,
|
||||||
|
not the joystick axis. Drive axes via the X/Y box.
|
||||||
|
- A real XInput gamepad is connected on this machine ("Controller #1
|
||||||
|
connected"); the router only writes an axis when its composed value
|
||||||
|
changes, so a centered pad won't fight a canvas drag.
|
||||||
|
- The wire readout (top center, green) shows `GetWireAxis` values —
|
||||||
|
joystick Y is natively negated on the wire (stick up = −80) unless
|
||||||
|
"Invert Y" is checked.
|
||||||
Reference in New Issue
Block a user