From bc7418ac356f4b91c77e6f0296b4c0323a1b0ca3 Mon Sep 17 00:00:00 2001 From: 4aiman Date: Fri, 21 Aug 2026 12:31:44 +0300 Subject: [PATCH] =?UTF-8?q?=D0=9F=D0=BE=D0=B4=D0=BB=D0=BE=D0=B6=D0=BA?= =?UTF-8?q?=D0=B0=20=D0=BF=D0=BE=D0=BB=D0=BE=D1=81=D1=8B=20=D0=BC=D0=B5?= =?UTF-8?q?=D0=BD=D1=8E=20=D0=B7=D0=B0=D0=B4=D0=B0=D1=91=D1=82=D1=81=D1=8F?= =?UTF-8?q?,=20=D0=BA=D0=BE=D0=B3=D0=B4=D0=B0=20=D1=83=20=D0=BC=D0=B5?= =?UTF-8?q?=D0=BD=D1=8E=20=D1=83=D0=B6=D0=B5=20=D0=B5=D1=81=D1=82=D1=8C=20?= =?UTF-8?q?=D0=B4=D0=B5=D1=81=D0=BA=D1=80=D0=B8=D0=BF=D1=82=D0=BE=D1=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Цвет подложки задаётся кистью через SetMenuInfo по дескриптору меню, а дескриптор появляется только когда меню отдано окну. Вызов стоял до присваивания, условие HandleAllocated не выполнялось, и подложка не задавалась ни разу: пункты рисовались нашими руками, а полоса правее последнего названия оставалась светлой. Теперь вызов идёт дважды и оба раза нужны: до присваивания — расставить обработчики отрисовки к первому показу, после — задать подложку. Полоса меню живёт в неклиентской части окна и сама себя не перерисовывает, поэтому следом идёт DrawMenuBar. --- src/uMainForm.pas | 10 ++++++++-- src/uTheme.pas | 18 +++++++++++++++++- 2 files changed, 25 insertions(+), 3 deletions(-) diff --git a/src/uMainForm.pas b/src/uMainForm.pas index 37a675c..92d8b51 100644 --- a/src/uMainForm.pas +++ b/src/uMainForm.pas @@ -572,10 +572,16 @@ begin AddItem(MProject, 'Добавить дорожку', @MenuAddTrack); AddItem(MProject, 'Удалить последнюю дорожку', @MenuRemoveTrack); - { Цвета назначаются до того, как меню отдано окну: под win32 обработчики - отрисовки должны быть на месте к первому показу. } + { Дважды, и оба раза нужны. + + До присваивания — чтобы обработчики отрисовки стояли к первому показу. + После — чтобы задать подложку полосы: она задаётся через SetMenuInfo по + дескриптору меню, а дескриптор появляется только когда меню отдано + окну. Первый вызов до этого просто пропускал подложку, и справа от + последнего названия оставалась светлая полоса. } ApplyDarkMenu(FMenu); Menu := FMenu; + ApplyDarkMenu(FMenu); end; { Показ фоновой работы. diff --git a/src/uTheme.pas b/src/uTheme.pas index f8dcd88..f1c5278 100644 --- a/src/uTheme.pas +++ b/src/uTheme.pas @@ -209,6 +209,11 @@ const function SetMenuInfo(AMenu: HMENU; const AInfo: TMenuInfoRec): LongBool; stdcall; external 'user32' name 'SetMenuInfo'; + +{ Имя своё, а не DrawMenuBar: так называется и функция LCL, а имена в + Паскале нечувствительны к регистру. } +function SysDrawMenuBar(AWnd: HWND): LongBool; + stdcall; external 'user32' name 'DrawMenuBar'; {$ENDIF} type @@ -879,7 +884,11 @@ begin создаёт его принудительно, и у всплывающего меню, до показа которого ещё далеко, это ломает само меню: оно перестаёт открываться. Цена отказа — тонкая рамка вокруг раскрытого списка остаётся системной; - сами пункты рисуются нами и цвет берут. } + сами пункты рисуются нами и цвет берут. + + Отсюда следует, что для полосы меню эту процедуру надо звать дважды: + до присваивания окну — чтобы расставить обработчики отрисовки, и после + — когда дескриптор уже есть и подложку можно задать. } if AMenu.HandleAllocated then begin FillChar(Info{%H-}, SizeOf(Info), 0); @@ -887,6 +896,13 @@ begin Info.fMask := MIM_BACKGROUND or MIM_APPLYTOSUBMENUS; Info.hbrBack := MenuBrush; SetMenuInfo(AMenu.Handle, Info); + + { Полоса меню живёт в неклиентской части окна и сама себя не + перерисовывает: без этого новая подложка появилась бы только при + следующем изменении размера окна. } + if (AMenu.Parent is TCustomForm) and + TCustomForm(AMenu.Parent).HandleAllocated then + SysDrawMenuBar(TCustomForm(AMenu.Parent).Handle); end; {$ENDIF} end;