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:
@@ -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.
|
||||
|
||||
@@ -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);
|
||||
SendMessage(LBtn, WM_SETFONT, WPARAM(GetStockObject(DEFAULT_GUI_FONT)), 1);
|
||||
GLazyOldBtnProc := Pointer(SetWindowLongPtr(LBtn, GWLP_WNDPROC,
|
||||
LONG_PTR(@LazyButtonProc)));
|
||||
end;
|
||||
|
||||
var
|
||||
|
||||
Reference in New Issue
Block a user