Skip to content

Add a pin button to list rows, wrap long clip text, and mark the delete-all-clips entry in red - #1172

Open
happymy wants to merge 3 commits into
sabrogden:masterfrom
happymy:dev
Open

happymy wants to merge 3 commits into
sabrogden:masterfrom
happymy:dev

Conversation

@happymy

@happymy happymy commented Oct 17, 2026

Copy link
Copy Markdown

Three small usability changes to the quick paste window, in three commits on top of a80fd35.

Summary

Commit What it does
f2da01e A pin button on the hovered list row pins / unpins that clip
7457d43 Long clip text wraps inside its row instead of being cut off at the right
7ac0162 The "Delete All Non Used Clips" entry is drawn in red as a warning

No new dependencies, no new settings, no resource or language file changes. All of it is Win32 / MFC code in src.

1. Pin button (f2da01e)

Clicking the pin button of the hovered row pins the clip (never auto deleted), clicking it again unpins it. Nothing else about the row changes.

  • It reuses the slot the "never auto delete" star is already drawn in, so a pinned clip shows one star, not two. The slot is kept free for every row, so the text does not shift when the button appears on hover.
  • A pinned row shows the star solid, a hovered row shows it faded (alpha 60/255) - a hovered clip is clearly not a pinned one. The fade is a new opacity argument on CGdiImageDrawer::Draw (GDI+ color matrix).
  • The click is taken in CQPasteWnd::PreTranslateMessage before the list sees it, and the matching WM_LBUTTONUP is swallowed, so the action configured for "click on a clip" does not run. The hit test uses the button rectangle recorded while that row was painted.
  • lDontAutoDelete is written through SetClipPinned, so the state survives a restart. Pinning is the existing mechanism - no new column, no schema change.
  • The symbol string a row is drawn with is now built by one function, GetRowSymbols, used by both the list painting and GetDispInfo, which had the same logic copied in two places.

2. Clip text wraps inside the row (7457d43)

A list view has one height for every row, so text longer than one line used to be cut off at the right. The text now wraps (DT_WORDBREAK) to fill the lines the row height already covers, and is clipped at the bottom when it needs more. A clip that needs fewer lines than the row has is measured with DT_CALCRECT and stays vertically centered, exactly as before.

The visible width of the text is also limited to the part of the row that really belongs to the list - the strip the list keeps for its scroll bar is inside the client rectangle but is not part of the list, so text no longer runs under it (CQListCtrl::GetVisibleRight).

How many lines are shown is decided by the existing "Text lines per clip" setting, which is what sizes the rows.

3. Red warning on the delete-all-clips entry (7ac0162)

The entry that permanently deletes every clip that is not pinned looked exactly like the harmless entries next to it. Windows draws its menus itself and cannot color a single entry, so this one entry is switched to owner draw and painted by the application:

  • Background COLOR_MENU, selection COLOR_HIGHLIGHT, selected text COLOR_HIGHLIGHTTEXT, disabled text COLOR_GRAYTEXT, unselected text RGB(200, 0, 0) - the system colors Windows uses for the entries around it, and the menu font from SPI_GETNONCLIENTMETRICS.
  • The item width is measured from its actual text with that font, so a translation longer than the English string is not clipped.
  • The text is still the localized one: it is read from the menu after UpdateRightClickMenu, so the language files stay untouched.
  • WM_DRAWITEM / WM_MEASUREITEM are forwarded to the base class for anything that is not ODT_MENU, which keeps the existing MFC list reflection (row height messages) working.

Reviewer note - the one visible side effect: a menu that contains an owner drawn entry is drawn by Windows in the classic style, so this menu (the "Menu" button in the lower right of the quick paste window) no longer follows the modern style: its rows, indents and background change. That affects only this menu - the right click menu and the tray menu are untouched. It is a Windows behavior and cannot be avoided while that single entry is colored. If that is not acceptable, the entry has to stay in the regular color.

The other thing that used to exist in the popup - "delete clips that are not pinned" - already has an entry there (DeleteNonUsedClips), so this PR only marks it as dangerous and adds no code for it.

Testing

  • Built with msbuild CP_Main_10.sln /p:Configuration=Release /p:Platform=x64 (what CI runs); each of the three commits builds on its own.
  • Manually verified on Windows 11 at 192 DPI (200% scaling) with the real installed build:
    • pin: hover shows the faded star, click pins / unpins, the action for clicking a clip does not fire, the state survives a restart, and the text of the row does not move;
    • wrap: rows with several lines of text fill the row and short clips stay centered, no text under the scroll bar;
    • red entry: measured from the screen - menu 524 x 683 (was 646 x 683 before the width was measured from the text), red text 262 x 23, at the same left indent as the regular entries, background 240/240/240 = COLOR_MENU.

Known limitations

  • The owner drawn entry uses a fixed row height of 17 logical pixels, which is 1 px short of what Windows uses for the entries next to it at this DPI. If the user changes the system text size, that entry does not grow with the others.
  • The pin button is mouse only: no menu entry, no shortcut, and no accessibility name (the star it replaces had none either).
  • Multi line display depends on the "Text lines per clip" setting; the row height is the limit and a longer clip is cut off at the bottom of the row.
  • The measured item width was verified with the Chinese string only. Every translation goes through the same measurement, but that was not run in all 29 language files.

A clip can be pinned (never auto deleted) again by clicking the pin button that shows up on the hovered row. It uses the slot the never-auto-delete star has always been drawn in, so a pinned clip shows one solid star and the text does not move; the pin is drawn faded while it is only offered by the hover. Clicking it writes lDontAutoDelete through SetClipPinned, the symbol text of a row comes from the shared GetRowSymbols.
A row has one height for every clip, so text longer than a single line was cut off at the right. The text now wraps to fill the lines the row height covers and is clipped at the bottom; a clip that needs fewer lines stays vertically centered like before. The text is also kept inside the part of the row that is really visible, the strip the list holds for its scroll bar is not part of it.
The entry that deletes every clip that is not pinned looked like the harmless entries next to it. Windows draws its menus itself and cannot color a single entry, so this one is switched to owner draw and painted by the app with the menu font and the system colors windows uses for the entries around it. The text still comes from the language file. A menu that holds an owner drawn entry is drawn by Windows the classic way, so this menu no longer follows the modern style.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant