fix(autofill): la barrette reste au-dessus, et se traine depuis ses boutons

TOPMOST n'est pas un rang, c'est une bande. La barre des taches y est
aussi, et cliquer son fond vide la remonte en tete de cette bande : une
barrette posee dessus passe DERRIERE et semble avoir disparu. Le meme
battement de 200 ms la repose.

Traine depuis un bouton : les boutons sont subclasses, et DragDetect
tranche entre clic et glissement en respectant le seuil regle par
l'utilisateur. Sur un clic, on envoie BN_CLICKED a la place du bouton -
DragDetect a avale le WM_LBUTTONUP, lui rendre la main le laisserait
enfonce pour toujours.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
r-zakarya
2026-08-26 17:27:38 +01:00
parent 9ce07ae5d0
commit 6b908e73a5
2 changed files with 63 additions and 2 deletions
+12
View File
@@ -206,6 +206,18 @@ Détails :
détruirait le `NOACTIVATE` qui la fait fonctionner. Deux portes vers ce menu —
`WM_NCRBUTTONUP` (le fond est non-client à cause de `HTCAPTION`) et
`WM_CONTEXTMENU` (remonté par les boutons).
- **`TOPMOST` n'est pas un rang, c'est une bande** : la barre des tâches y est
aussi, et cliquer son fond vide la remonte en tête de cette bande — une
barrette posée dessus passe **derrière** et semble avoir disparu. Le même
battement de 200 ms la repose (`SetWindowPos … SWP_NOMOVE or SWP_NOSIZE`) ;
sans mouvement ni taille à changer, l'appel ne repeint rien.
- **Traîner depuis un bouton** : les boutons sont subclassés (`GWLP_WNDPROC`,
une seule proc d'origine — même classe). Sur `WM_LBUTTONDOWN`, **`DragDetect`**
tranche entre clic et glissement en respectant le seuil réglé par
l'utilisateur. Glissement → `ReleaseCapture` + `WM_SYSCOMMAND, SC_MOVE or
HTCAPTION`. Clic → on **envoie `BN_CLICKED` à la place du bouton** : DragDetect
a avalé le `WM_LBUTTONUP`, lui rendre la main le laisserait enfoncé pour
toujours. Le clic droit n'est pas intercepté, donc le menu d'opacité tient.
- Le survol est **sondé** par un `SetTimer` de 200 ms, pas par `TrackMouseEvent` :
avec quatre fenêtres enfants, passer de la barrette à un bouton envoie déjà un
`WM_MOUSELEAVE` au parent. Comparer le curseur au rectangle ignore ce piège.
+50 -1
View File
@@ -1066,6 +1066,45 @@ begin
FOnAutofillRequest(AKind, LTarget, LTitle);
end;
// Les quatre boutons sont de la meme classe, donc une seule procedure d'origine
// a retenir.
var
GLazyOldBtnProc: Pointer = nil;
/// Un appui sur un bouton de la barrette : clic, ou debut de glissement ?
///
/// C'EST DragDetect QUI TRANCHE, ET PERSONNE D'AUTRE. Il bloque jusqu'a ce que
/// la souris depasse le seuil de glissement du systeme - celui que
/// l'utilisateur a regle, et qui n'est pas le meme sur un ecran tactile - ou
/// jusqu'au relachement. Un seuil ecrit a la main serait un troisieme reglage
/// que personne n'a demande.
function LazyButtonProc(AWnd: HWND; AMsg: UINT; AWp: WPARAM;
ALp: LPARAM): LRESULT; stdcall;
var
LPt: TPoint;
begin
if AMsg = WM_LBUTTONDOWN then
begin
GetCursorPos(LPt);
if DragDetect(AWnd, LPt) then
begin
ReleaseCapture; // DragDetect a pris la souris, la boucle de deplacement la veut
// Exactement le geste "trainer par la barre de titre" : la barrette EST
// sa propre barre de titre (WM_NCHITTEST -> HTCAPTION).
SendMessage(GetParent(AWnd), WM_SYSCOMMAND, SC_MOVE or HTCAPTION, 0);
end
else
// Relache sans bouger. DragDetect a AVALE le WM_LBUTTONUP, que le bouton
// ne verra donc jamais : lui rendre la main le laisserait enfonce pour
// toujours. On annonce le clic a sa place - c'est le message qu'il aurait
// envoye lui-meme.
SendMessage(GetParent(AWnd), WM_COMMAND,
MAKEWPARAM(GetDlgCtrlID(AWnd), BN_CLICKED), LPARAM(AWnd));
Exit(0);
end;
Result := CallWindowProc(GLazyOldBtnProc, AWnd, AMsg, AWp, ALp);
end;
procedure TPMBridge.DrawLazyButton(ADraw: PDrawItemStruct);
var
LRect: TRect;
@@ -1174,6 +1213,14 @@ begin
FLazyHover := LIn;
ApplyLazyAlpha(LIn);
end;
// TOPMOST N'EST PAS UN RANG, C'EST UNE BANDE. La barre des taches y est
// elle aussi, et cliquer son fond vide la remonte en tete de cette
// bande : une barrette posee dessus passe DERRIERE et semble avoir
// disparu, alors qu'elle est seulement recouverte. La reposer a chaque
// battement est ce que font tous les outils flottants ; sans mouvement
// ni taille a changer, l'appel ne repeint rien.
SetWindowPos(FLazyWnd, HWND_TOPMOST, 0, 0, 0, 0,
SWP_NOMOVE or SWP_NOSIZE or SWP_NOACTIVATE);
Exit;
end;
// Fin du glissement (la boucle modale ouverte par HTCAPTION), donc une
@@ -1252,9 +1299,11 @@ procedure TPMBridge.SetLazyBar(AOn: Boolean);
LBtn := CreateWindow('BUTTON', PChar(ACaption),
WS_CHILD or WS_VISIBLE or BS_OWNERDRAW, AX, 5, AWidth, 28,
FLazyWnd, HMENU(AId), HInstance, nil);
if LBtn = 0 then Exit;
// Without this the button wears the 1995 system font.
if LBtn <> 0 then
SendMessage(LBtn, WM_SETFONT, WPARAM(GetStockObject(DEFAULT_GUI_FONT)), 1);
GLazyOldBtnProc := Pointer(SetWindowLongPtr(LBtn, GWLP_WNDPROC,
LONG_PTR(@LazyButtonProc)));
end;
var