#delphi #menu
#delphi #меню
Вопрос:
Я создаю свой собственный OnAdvancedDrawItem, чтобы изменить цвет основного меню. Это работает хорошо, но я получаю раздражающую белую линию внизу.
Он исчезает при наведении курсора мыши на меню, но возвращается при выборе другого приложения. Как я могу избавиться от этого?
Вот мой базовый код для окраски фона.
unit MenMain;
interface
uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,Dialogs, Menus, ImgList, StdCtrls;
type
TForm1 = class(TForm)
MainMenu1: TMainMenu;
File2: TMenuItem;
Edit1: TMenuItem;
Window1: TMenuItem;
procedure Window1AdvancedDrawItem(Sender: TObject; ACanvas: TCanvas; ARect: TRect; State: TOwnerDrawState);
private
public
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.Window1AdvancedDrawItem(Sender: TObject; ACanvas: TCanvas; ARect: TRect; State: TOwnerDrawState);
begin
with TMenuItem(Sender) do
begin
with ACanvas do
begin
Brush.Color := clMoneyGreen;
Inc(ARect.Bottom,1);
FillRect(ARect);
Font.Color := clBlue;
DrawText(ACanvas.Handle, PChar(Caption),Length(Caption),ARect, DT_SINGLELINE or DT_VCENTER);
end;
end;
end;
end.
Комментарии:
1. Это, кажется, доказывает, для чего нужен ‘aRect’, чтобы указать область, которую вы можете нарисовать. То, что вы рисуете снаружи, может быть перерисовано позже. В нижней строке, вероятно, находится область NC за пределами области элементов.
2. Могу я спросить, почему вы не используете
TMainActionMenuBar
? Вы можете подключить егоTStandardColorMap
и добиться желаемого эффекта.
Ответ №1:
ARect
Параметр обработчика OnAdvancedDrawItem
события rcItem
DRAWITEMSTRUCT
— это параметр, который передается в WM_DRAWITEM
сообщение. В документации есть это, чтобы сказать о прямоугольнике:
Прямоугольник, который определяет границы элемента управления, который нужно нарисовать. Этот прямоугольник находится в контексте устройства, указанном участником hDC. Система автоматически обрезает все, что окно владельца отображает в контексте устройства для полей со списком, списков и кнопок, но не обрезает пункты меню. При рисовании элементов меню окно владельца не должно выходить за границы прямоугольника, определенного элементом rcItem.
Таким образом, хотя контекст устройства не привязан к прямоугольнику, вы несете ответственность за то, чтобы не рисовать за его пределами. Это происходит, когда вы выполняете Inc(ARect.Bottom,1);
перед заполнением прямоугольника.
Комментарии:
1. Ваш ответ очень поучителен. Однако это все еще оставляет меня с проблемой предотвращения закрашивания Windows белой строки под строкой меню, когда перерисовка инициируется не действиями меню.
2. @Rudi — Ну, ответ по сути подразумевал «вы не можете от него избавиться». По крайней мере, нелегко. Вы не сможете добиться этого с помощью меню, нарисованных владельцем. Вы должны предположить, что не клиентская область рисуется самостоятельно. Я чувствую, что это сложная тема, которая выходит за рамки этого вопроса. Я, конечно, тоже не рекомендую. Как вы сами видели, ОС вмешивается в процесс рисования NC в довольно странные моменты, например, при деактивации окна.
Ответ №2:
Вы можете изменить цвет серой области. Используйте это в onCreate и OnCanResize
global var - fMenuBrushHandle: THandle;
var
lMenuInfo: TMenuInfo;
lMenuColor: TColor;
begin
lMenuColor := clRed;
DeleteObject(fMenuBrushHandle);
fMenuBrushHandle := CreateSolidBrush(ColorToRGB(lMenuColor));
FillChar(lMenuInfo, SizeOf(lMenuInfo), 0);
lMenuInfo.cbSize := SizeOf(lMenuInfo);
lMenuInfo.hbrBack := fMenuBrushHandle;
lMenuInfo.fMask := MIM_BACKGROUND;
SetMenuInfo(MainMenu1.Handle, lMenuInfo);
end;
или
global var - FBrush: TBrush;
var
lMenuInfo: TMenuInfo;
begin
if not Assigned(FBrush) then
FBrush := TBrush.Create;
FBrush.Color := clRed;
FBrush.Style := bsSolid;
lMenuInfo.cbSize := SizeOf(lMenuInfo);
lMenuInfo.fMask := MIM_BACKGROUND;
lMenuInfo.hbrBack := FBrush.Handle;
SetMenuInfo(MainMenu1.Handle, lMenuInfo);
end;
или даже нарисовать растровое изображение
global var
fMenuHandle:THandle;
fBitmap:Tbitmap;
var
lMenuInfo:TMenuInfo;
begin
if Assigned(fBitmap) then
fBitmap.Free;
fBitmap:=TBitmap.Create;
fBitmap.Width:=21;
fBitmap.Height:=Form1.Width;
DeleteObject(fMenuHandle);
fMenuHandle:=CreatePatternBrush(fBitmap.Handle);
Fillchar(lMenuInfo,SizeOf(lMenuInfo),0);
lMenuInfo.cbSize:=SizeOf(lMenuInfo);
lMenuInfo.fMask:=MIM_BACKGROUND;
lMenuInfo.hbrBack:=fMenuHandle;
SetMenuInfo(MainMenu1.Handle,lMenuInfo);
end;