Подложка полосы меню задаётся, когда у меню уже есть дескриптор

Цвет подложки задаётся кистью через SetMenuInfo по дескриптору меню, а
дескриптор появляется только когда меню отдано окну. Вызов стоял до
присваивания, условие HandleAllocated не выполнялось, и подложка не
задавалась ни разу: пункты рисовались нашими руками, а полоса правее
последнего названия оставалась светлой.

Теперь вызов идёт дважды и оба раза нужны: до присваивания — расставить
обработчики отрисовки к первому показу, после — задать подложку. Полоса
меню живёт в неклиентской части окна и сама себя не перерисовывает,
поэтому следом идёт DrawMenuBar.
This commit is contained in:
4aiman 2026-08-21 12:31:44 +03:00
commit bc7418ac35
2 changed files with 25 additions and 3 deletions

View file

@ -572,10 +572,16 @@ begin
AddItem(MProject, 'Добавить дорожку', @MenuAddTrack);
AddItem(MProject, 'Удалить последнюю дорожку', @MenuRemoveTrack);
{ Цвета назначаются до того, как меню отдано окну: под win32 обработчики
отрисовки должны быть на месте к первому показу. }
{ Дважды, и оба раза нужны.
До присваивания — чтобы обработчики отрисовки стояли к первому показу.
После — чтобы задать подложку полосы: она задаётся через SetMenuInfo по
дескриптору меню, а дескриптор появляется только когда меню отдано
окну. Первый вызов до этого просто пропускал подложку, и справа от
последнего названия оставалась светлая полоса. }
ApplyDarkMenu(FMenu);
Menu := FMenu;
ApplyDarkMenu(FMenu);
end;
{ Показ фоновой работы.

View file

@ -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;