···11+# Auto-Hide Caption (frame visible only when active) — Design
22+33+**Date:** 2026-07-15
44+**Status:** Approved (brainstorming)
55+66+## Goal
77+88+Show the calculator window's title bar and close button **only while the window is
99+active**. When focus moves to another window the calculator stays on top as a clean,
1010+chromeless display (no caption, no X); clicking it back (or showing it from the tray)
1111+brings the frame back.
1212+1313+## Behavior
1414+1515+- Handle `WM_ACTIVATE` in `CCalculatorWindow`:
1616+ - **Activated** (`WA_ACTIVE` / `WA_CLICKACTIVE`): add `WS_CAPTION | WS_SYSMENU`.
1717+ - **Deactivated** (`WA_INACTIVE`): remove `WS_CAPTION | WS_SYSMENU`.
1818+- The toggle uses `SetWindowLongPtr(GWL_STYLE)` followed by
1919+ `SetWindowPos(SWP_FRAMECHANGED | SWP_NOACTIVATE | SWP_NOZORDER)`.
2020+- `CreateStandalone` is unchanged (window is created with the caption styles; it is
2121+ hidden at that point, so the first activation just confirms the state).
2222+- A private helper `ApplyFrameStyle(bool visible)` centralizes the style/geometry change;
2323+ a `bool m_captionVisible` member tracks the current state and makes the call idempotent
2424+ (no-op when the requested state already applies).
2525+2626+## Geometry — display stays put
2727+2828+When the frame toggles, the **client rectangle keeps its exact screen position**: the
2929+caption grows upward when it appears and retracts when it disappears; the displayed
3030+number never moves.
3131+3232+- On toggle: take the current client rect in screen coordinates
3333+ (`GetClientRect` + `ClientToScreen`), compute the new window rect for the new style
3434+ with `AdjustWindowRectEx`, and pass position + size to the same `SetWindowPos` call
3535+ that applies `SWP_FRAMECHANGED`.
3636+- Safety clamp: if growing upward would push the window top above the work area top,
3737+ clamp to the work area (in practice the window sits near the taskbar, so this is a
3838+ guard, not an expected path).
3939+4040+## Position persistence — canonical form
4141+4242+`OnExitSizeMove` currently saves the window's top-left corner, which now depends on
4343+whether the caption is present (± caption height). To keep the restored position stable
4444+across restarts regardless of the frame state at save time:
4545+4646+- **Save** the position in canonical form: the top-left of the **chromeless** window
4747+ (equal to the client origin, since a plain `WS_POPUP` window has no frame offset).
4848+- **Restore** (`PlaceInitial`) converts the canonical point back to the window origin for
4949+ the style in effect at that moment (via `AdjustWindowRectEx`): since the window is
5050+ created with the caption styles, its top-left is placed one caption height above the
5151+ saved client origin, so the client lands exactly where it was saved.
5252+- Registry value name and type are unchanged (`REG_DWORD` pair via `Settings`); existing
5353+ saved positions are reinterpreted with at most a caption-height offset once, then
5454+ stay stable.
5555+5656+## Accepted side effects
5757+5858+- Opening the tray menu or the About dialog deactivates the calculator, so the caption
5959+ disappears while they are open. Consistent with the rule ("active = framed"); no
6060+ functional impact.
6161+- The frame appears/disappears instantly (no animation); with DWM on Windows 11 the
6262+ repaint is near-imperceptible.
6363+6464+## Components touched
6565+6666+`CalculatorWindow.h` / `CalculatorWindow.cpp` only:
6767+6868+- `MESSAGE_HANDLER(WM_ACTIVATE, OnActivate)` + `OnActivate` implementation.
6969+- Private `void ApplyFrameStyle(bool visible)` + `bool m_captionVisible`.
7070+- Canonical-position adjustment in `OnExitSizeMove` and `PlaceInitial`.
7171+7272+Engine (`calc`), `Settings` storage format, `App.cpp`, tray icon, and packaging are all
7373+untouched.
7474+7575+## Testing
7676+7777+- **Engine regression:** `tests\build-and-run.cmd` still passes 16/16 (feature is UI-only).
7878+- **Manual verification checklist:**
7979+ 1. Show from tray → window appears with caption + X.
8080+ 2. Click another app → caption disappears; the number display does not move.
8181+ 3. Click the calculator → caption reappears; display does not move.
8282+ 4. X → hides to tray (existing `WM_CLOSE` behavior).
8383+ 5. Drag by caption and by body both work; position persists.
8484+ 6. Restart the app → window reappears at the same visual position (no drift).
8585+8686+## Out of scope (YAGNI)
8787+8888+- Animated caption transitions.
8989+- Custom-drawn caption (approach B — fallback if the native toggle disappoints).
9090+- Any change to sizing, fonts, or engine behavior.