feat(autofill): un troisieme bouton 2FA, et la barrette suit le theme
SetPreferredAppMode(ForceDark) ne themise que ce que le systeme dessine lui-meme - menus, ascenseurs, infobulles. Un bouton Win32 standard reste donc gris clair sur fond sombre, ce que la capture montrait. BS_OWNERDRAW + WM_DRAWITEM : le systeme garde le suivi de la souris et l'etat enfonce, nous ne reprenons que les couleurs, recopiees des variables de css/style.css. Le cadre passe dans WM_ERASEBKGND plutot que par WS_BORDER, qui se sert dans les couleurs systeme. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -29,7 +29,7 @@ unit PM.Bridge;
|
||||
interface
|
||||
|
||||
uses
|
||||
System.SysUtils, System.Classes, System.Math,
|
||||
System.SysUtils, System.Classes, System.Math, System.Types,
|
||||
FMX.Types, FMX.Forms,
|
||||
Winapi.Windows, Winapi.ShellAPI, Winapi.Messages,
|
||||
PM.SingleInstance;
|
||||
@@ -152,7 +152,15 @@ type
|
||||
// foreground: the browser stays active, its field stays focused, and the
|
||||
// capture below sees exactly what the hotkey path sees.
|
||||
FLazyWnd: HWND;
|
||||
// Dernier theme annonce par la page. La barrette est peinte a la main, donc
|
||||
// elle a besoin de savoir - un bouton Win32 standard reste gris clair meme
|
||||
// sous SetPreferredAppMode(ForceDark), qui ne themise que ce que le systeme
|
||||
// dessine lui-meme (menus, ascenseurs, infobulles).
|
||||
FDarkTheme: Boolean;
|
||||
procedure LazyWindowHandler(var AMsg: TMessage);
|
||||
/// Peint un bouton de la barrette (BS_OWNERDRAW). Le systeme garde le suivi
|
||||
/// du clic et l'etat enfonce ; nous ne reprenons que les couleurs.
|
||||
procedure DrawLazyButton(ADraw: PDrawItemStruct);
|
||||
// Capture the foreground window and hand it to the host. Shared by the
|
||||
// autofill hotkeys and the lazy strip - same target, same title matching,
|
||||
// same picker. Only the gesture differs.
|
||||
@@ -377,9 +385,25 @@ const
|
||||
const
|
||||
LAZY_ID_FULL = 101;
|
||||
LAZY_ID_PWD = 102;
|
||||
LAZY_W = 148;
|
||||
LAZY_ID_TOTP = 103;
|
||||
LAZY_W = 206;
|
||||
LAZY_H = 40;
|
||||
|
||||
// Palette de la barrette, en COLORREF ($00BBGGRR - les octets sont INVERSES
|
||||
// par rapport a l'hexadecimal CSS). Reprise des variables de css/style.css pour
|
||||
// que la barrette et la fenetre principale ne soient pas deux gris differents.
|
||||
const
|
||||
LAZY_DARK_BG = $1C1515; // --bg #15151c
|
||||
LAZY_DARK_FACE = $322929; // --bg-elev-2 #292932
|
||||
LAZY_DARK_DOWN = $3F3434; // --bg-elev-3 #34343f
|
||||
LAZY_DARK_EDGE = $413535; // --border #353541
|
||||
LAZY_DARK_INK = $F5F1F1; // --text #f1f1f5
|
||||
LAZY_LITE_BG = $F5F7F7; // --bg #f7f7f5
|
||||
LAZY_LITE_FACE = $FFFFFF; // --bg-elev #ffffff
|
||||
LAZY_LITE_DOWN = $DDE3E3; // --bg-elev-3 #e3e3dd
|
||||
LAZY_LITE_EDGE = $D7DCDC; // --border #dcdcd7
|
||||
LAZY_LITE_INK = $1F1A1A; // --text #1a1a1f
|
||||
|
||||
// Dynamic WTS function pointers — wtsapi32.dll is not guaranteed on all
|
||||
// Windows SKUs (e.g. minimal Server Core without Session Services), so
|
||||
// we load it at runtime and tolerate absence gracefully.
|
||||
@@ -1011,6 +1035,41 @@ begin
|
||||
FOnAutofillRequest(AKind, LTarget, LTitle);
|
||||
end;
|
||||
|
||||
procedure TPMBridge.DrawLazyButton(ADraw: PDrawItemStruct);
|
||||
var
|
||||
LRect: TRect;
|
||||
LBrush: HBRUSH;
|
||||
LFace, LEdge, LInk: COLORREF;
|
||||
LText: array[0..31] of Char;
|
||||
begin
|
||||
LRect := ADraw.rcItem;
|
||||
if FDarkTheme then
|
||||
begin
|
||||
LFace := LAZY_DARK_FACE; LEdge := LAZY_DARK_EDGE; LInk := LAZY_DARK_INK;
|
||||
if (ADraw.itemState and ODS_SELECTED) <> 0 then LFace := LAZY_DARK_DOWN;
|
||||
end
|
||||
else
|
||||
begin
|
||||
LFace := LAZY_LITE_FACE; LEdge := LAZY_LITE_EDGE; LInk := LAZY_LITE_INK;
|
||||
if (ADraw.itemState and ODS_SELECTED) <> 0 then LFace := LAZY_LITE_DOWN;
|
||||
end;
|
||||
|
||||
LBrush := CreateSolidBrush(LFace);
|
||||
FillRect(ADraw.hDC, LRect, LBrush);
|
||||
DeleteObject(LBrush);
|
||||
LBrush := CreateSolidBrush(LEdge);
|
||||
FrameRect(ADraw.hDC, LRect, LBrush);
|
||||
DeleteObject(LBrush);
|
||||
|
||||
// Le libelle est celui de la fenetre-bouton : une seule verite, posee a la
|
||||
// creation, plutot qu'une table de correspondance a tenir a jour.
|
||||
GetWindowText(ADraw.hwndItem, LText, Length(LText));
|
||||
SetBkMode(ADraw.hDC, TRANSPARENT);
|
||||
SetTextColor(ADraw.hDC, LInk);
|
||||
DrawText(ADraw.hDC, LText, -1, LRect,
|
||||
DT_CENTER or DT_VCENTER or DT_SINGLELINE);
|
||||
end;
|
||||
|
||||
function TPMBridge.LazyBarVisible: Boolean;
|
||||
begin
|
||||
Result := FLazyWnd <> 0;
|
||||
@@ -1019,6 +1078,7 @@ end;
|
||||
procedure TPMBridge.LazyWindowHandler(var AMsg: TMessage);
|
||||
var
|
||||
LRect: TRect;
|
||||
LBrush: HBRUSH;
|
||||
begin
|
||||
case AMsg.Msg of
|
||||
// THE STRIP IS ITS OWN TITLE BAR. It has none to grab, and it will end up
|
||||
@@ -1034,7 +1094,20 @@ begin
|
||||
WM_ERASEBKGND:
|
||||
begin
|
||||
GetClientRect(FLazyWnd, LRect);
|
||||
FillRect(HDC(AMsg.WParam), LRect, HBRUSH(COLOR_BTNFACE + 1));
|
||||
LBrush := CreateSolidBrush(IfThen(FDarkTheme, LAZY_DARK_BG, LAZY_LITE_BG));
|
||||
FillRect(HDC(AMsg.WParam), LRect, LBrush);
|
||||
DeleteObject(LBrush);
|
||||
// Le cadre est peint ici plutot que par WS_BORDER : celui-ci se sert
|
||||
// dans les couleurs systeme, qui ignorent notre theme.
|
||||
LBrush := CreateSolidBrush(IfThen(FDarkTheme, LAZY_DARK_EDGE, LAZY_LITE_EDGE));
|
||||
FrameRect(HDC(AMsg.WParam), LRect, LBrush);
|
||||
DeleteObject(LBrush);
|
||||
AMsg.Result := 1;
|
||||
Exit;
|
||||
end;
|
||||
WM_DRAWITEM:
|
||||
begin
|
||||
DrawLazyButton(PDrawItemStruct(AMsg.LParam));
|
||||
AMsg.Result := 1;
|
||||
Exit;
|
||||
end;
|
||||
@@ -1044,6 +1117,7 @@ begin
|
||||
case LoWord(AMsg.WParam) of
|
||||
LAZY_ID_FULL: FireAutofillRequest(akFull);
|
||||
LAZY_ID_PWD: FireAutofillRequest(akPasswordOnly);
|
||||
LAZY_ID_TOTP: FireAutofillRequest(akTotp);
|
||||
end;
|
||||
AMsg.Result := 0;
|
||||
Exit;
|
||||
@@ -1054,12 +1128,16 @@ end;
|
||||
|
||||
procedure TPMBridge.SetLazyBar(AOn: Boolean);
|
||||
|
||||
procedure MakeButton(AId: Integer; const ACaption: string; AX: Integer);
|
||||
// BS_OWNERDRAW : le systeme garde le suivi de la souris et l'etat enfonce,
|
||||
// nous ne reprenons que les couleurs. Un bouton standard resterait gris clair
|
||||
// sur fond sombre, comme sur la capture qui a motive ce changement.
|
||||
procedure MakeButton(AId: Integer; const ACaption: string;
|
||||
AX, AWidth: Integer);
|
||||
var
|
||||
LBtn: HWND;
|
||||
begin
|
||||
LBtn := CreateWindow('BUTTON', PChar(ACaption),
|
||||
WS_CHILD or WS_VISIBLE or BS_PUSHBUTTON, AX, 5, 66, 28,
|
||||
WS_CHILD or WS_VISIBLE or BS_OWNERDRAW, AX, 5, AWidth, 28,
|
||||
FLazyWnd, HMENU(AId), HInstance, nil);
|
||||
// Without this the button wears the 1995 system font.
|
||||
if LBtn <> 0 then
|
||||
@@ -1083,11 +1161,10 @@ begin
|
||||
SetWindowLong(FLazyWnd, GWL_EXSTYLE,
|
||||
GetWindowLong(FLazyWnd, GWL_EXSTYLE) or
|
||||
WS_EX_NOACTIVATE or WS_EX_TOPMOST or WS_EX_TOOLWINDOW);
|
||||
SetWindowLong(FLazyWnd, GWL_STYLE,
|
||||
GetWindowLong(FLazyWnd, GWL_STYLE) or WS_BORDER);
|
||||
|
||||
MakeButton(LAZY_ID_FULL, 'Full', 5);
|
||||
MakeButton(LAZY_ID_PWD, 'Password', 77);
|
||||
MakeButton(LAZY_ID_FULL, 'Full', 5, 56);
|
||||
MakeButton(LAZY_ID_PWD, 'Password', 67, 76);
|
||||
MakeButton(LAZY_ID_TOTP, '2FA', 149, 52);
|
||||
|
||||
// Bottom right of the WORK area, so it does not start life under the
|
||||
// taskbar. From there the user drags it wherever the login form is.
|
||||
@@ -1330,6 +1407,13 @@ var
|
||||
DarkFlag: BOOL;
|
||||
FormHwnd: HWND;
|
||||
begin
|
||||
FDarkTheme := ADark;
|
||||
// La barrette ne suit aucun theme systeme : c'est nous qui la peignons, donc
|
||||
// c'est nous qui la redessinons quand la page bascule.
|
||||
if FLazyWnd <> 0 then
|
||||
RedrawWindow(FLazyWnd, nil, 0,
|
||||
RDW_INVALIDATE or RDW_ERASE or RDW_ALLCHILDREN or RDW_UPDATENOW);
|
||||
|
||||
if FMainForm = nil then Exit;
|
||||
FormHwnd := MainFormHWND(FMainForm);
|
||||
if FormHwnd = 0 then Exit;
|
||||
|
||||
Reference in New Issue
Block a user