Beautify your menu with Delphi
Many programs under Windows have very beautiful menus, such as the long Windows Banner from top to bottom on the left side of the Windows "Start" menu, or there is a small icon on the left side of each menu bar like Word. Seeing these cool menus, do you feel that your own menu looks boring? No third-party controls are needed, and the above functions can be achieved using Delphi.
If you want to implement a custom menu, you need to change the size of the menu when drawing the menu to adapt to the graphics drawn on the menu, and then draw the menu effect you need on it. In Delphi, each menu item corresponds to a TmenuItem control. This type of control has two events: OnDrawItem and OnMeasureItem. To implement a custom menu, you must first introduce these two events:
The OnMeasureItem event is defined as follows:
type TMenuMeasureItemEvent = PRocedure (Sender: TObject; ACanvas: TCanvas;
var Width, Height: Integer) of object;
property OnMeasureItem: TMenuMeasureItemEvent;
This event is generated when the menu bar monitors its own size. The parameter Acanvas defines the drawing object to be drawn, and the parameters Width and Height specify the default size of the menu item. Have you noticed the var before these two definitions? It means that you can use the OnMeasureItem event Changing these two values in the processing function means changing the size of the menu.
The OnDrawItem event is defined as follows:
type TMenuDrawItemEvent = procedure (Sender: TObject; ACanvas: TCanvas;
ARect: TRect; Selected: Boolean) of object;
property OnDrawItem: TMenuDrawItemEvent;
This event is triggered when the menu is drawn. The parameter Acanvas defines the menu drawing object, the parameter Arect specifies the drawing area of the menu, and the parameter Selected defines whether the current menu item is selected.
As you can see from the above introduction, to implement a customized menu, you only need to write code in the OnMeasureItem event to change the size of the menu items, and then draw the effect you need in the OnDrawItem event.
Below I will give a specific example to illustrate. This example is to make your own menu display the Banner bar function like the Windows Start menu. At the same time, this program can also fill the selected menu bar with gradient color (just like the taskbar menu of 3721 Chinese website software). The idea of the program is this: first create a long bitmap, and then change the width and height of the menu items in the OnMeasureItem event of each menu bar according to the text and images to be displayed on the menu and the needs of the program, and then Copy the corresponding part of the bitmap to the menu item in the OnDrawItem event. If the menu bar is selected, first change the brush color of the Acanvas parameter, and then fill in the corresponding parts of the menu bar in turn, thus realizing gradient color filling of the selected menu bar. Finally, the text is output to the menu bar.
Let's introduce the specific procedure. First, use image software to create a long bitmap file (you can set the aspect ratio of the image according to your needs, in my image it is 10:1). Create a new project in Delphi, add a TImage control to Form1, and set the AutoSize property of the control to True. Then add a TMainMenu control to Form1, set its OwnerDraw property to True (this is very important, otherwise the program cannot be implemented) and add 6 TMenuItem objects under the TMainMenu (right-click the TMainMenu control, and then click on the pop-up menu Menu Designer item, you can add a menu bar in the design window), set their Name properties to Caption1, Caption2, ..., Caption6 respectively.
The following is a specific program list:
unit OwnerMenu;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
Menus, ExtCtrls, StdCtrls, ImgList;
type
TForm1 = class(TForm)
MainMenu1: TMainMenu;
Main1: TMenuItem;
Caption1: TMenuItem;
Caption2: TMenuItem;
Caption3: TMenuItem;
Caption4: TMenuItem;
Caption5: TMenuItem;
Caption6: TMenuItem;
Image1: TImage;
procedure Caption1MeasureItem(Sender: TObject; ACanvas: TCanvas;
var Width, Height: Integer);
procedure Caption2MeasureItem(Sender: TObject; ACanvas: TCanvas;
var Width, Height: Integer);
procedure Caption3MeasureItem(Sender: TObject; ACanvas: TCanvas;
var Width, Height: Integer);
procedure Caption4MeasureItem(Sender: TObject; ACanvas: TCanvas;
var Width, Height: Integer);
procedure Caption5MeasureItem(Sender: TObject; ACanvas: TCanvas;
var Width, Height: Integer);
procedure Caption6MeasureItem(Sender: TObject; ACanvas: TCanvas;
var Width, Height: Integer);
procedure Caption1DrawItem(Sender: TObject; ACanvas: TCanvas;
ARect: TRect; Selected: Boolean);
procedure Caption2DrawItem(Sender: TObject; ACanvas: TCanvas;
ARect: TRect; Selected: Boolean);
procedure Caption3DrawItem(Sender: TObject; ACanvas: TCanvas;
ARect: TRect; Selected: Boolean);
procedure Caption4DrawItem(Sender: TObject; ACanvas: TCanvas;
ARect: TRect; Selected: Boolean);
procedure Caption5DrawItem(Sender: TObject; ACanvas: TCanvas;
ARect: TRect; Selected: Boolean);
procedure Caption6DrawItem(Sender: TObject; ACanvas: TCanvas;
ARect: TRect; Selected: Boolean);
private
{Private declarations}
public
procedure DrawItem(Sender: TMenuItem; ACanvas: TCanvas;ARect: TRect;
Selected: Boolean;strOUt:String);
{Public declarations}
end;
var
Form1: TForm1;
i,iH,Ind,iW,iRate:Integer;
rTemp:TRect;
iG1,iG2:Integer;
implementation
{$R *.DFM}
procedure TForm1.DrawItem(Sender: TMenuItem; ACanvas: TCanvas;ARect: TRect;
Selected: Boolean;strOut:String);
var
j:Integer;
begin
i:=ARect.Bottom -ARect.Top; //Get the height and width of the texture
Ind:=Sender.MenuIndex;
iH:=Round(Image1.Height/6*Ind); //Get the texture position
//Copy the bitmap at the corresponding position on the Image to the menu
StretchBlt(ACanvas.Handle,ARect.Left,ARect.Top,iW,i,Image1.Canvas.Handle,0,iH,
Image1.Width,Round(Image1.Height/6),SRCCOPY);
if Selected then begin //The menu item is selected
ACanvas.Font.Color := clWhite;
rTemp:=ARect;
rTemp.Left := rTemp.left+iW;
iG1:=Round((rTemp.Right - rTemp.Left)/10);
rTemp.Right := rTemp.Left +iG1;
for j:= 0 to 9 do begin //Set color gradient effect through loop
ACanvas.Brush.Color := RGB(0,0,j*25);
ACanvas.FillRect(rTemp);
rTemp.Left := rTemp.Left +iG1;
rTemp.Right := rTemp.Left +iG1;
end;
end
else begin //This menu item is not selected
ACanvas.Brush.Color := cl3DLight; //Set the background color to light gray
rTemp:=ARect;
rTemp.Left := rTemp.left+iW;
ACanvas.FillRect(rTemp);
ACanvas.Font.Color := clBlack;
end;
//Set the Canvas brush fill mode to transparent
ACanvas.Brush.Style:=bsClear;
//Output text on the menu
ACanvas.TextOut(ARect.Left+iW+5,ARect.Top,strOut);
end;
procedure TForm1.Caption1MeasureItem(Sender: TObject; ACanvas: TCanvas;
var Width, Height: Integer);
begin
//Change the width and height of the menu in the OnMeasureItem event. The following five programs are the same
//Change the width and height of the menu to accommodate the text
Height:=ACanvas.TextHeight('Caption1')+5;
Width:=ACanvas.TextWidth('Caption1')+5;
iRate:=Round(Image1.Height/(Height*6));
iW:=Round(Image1.Width /iRate);
Width:=Width+iW; //Change menu width based on calculation to accommodate additional text
end;
procedure TForm1.Caption2MeasureItem(Sender: TObject; ACanvas: TCanvas;
var Width, Height: Integer);
begin
Height:=ACanvas.TextHeight('Caption1')+5;
Width:=ACanvas.TextWidth('Caption1')+5;
iRate:=Round(Image1.Height/(Height*6));
iW:=Round(Image1.Width /iRate);
Width:=Width+iW;
end;
procedure TForm1.Caption3MeasureItem(Sender: TObject; ACanvas: TCanvas;
var Width, Height: Integer);
begin
Height:=ACanvas.TextHeight('Caption1')+5;
Width:=ACanvas.TextWidth('Caption1')+5;
iRate:=Round(Image1.Height/(Height*6));
iW:=Round(Image1.Width /iRate);
Width:=Width+iW;
end;
procedure TForm1.Caption4MeasureItem(Sender: TObject; ACanvas: TCanvas;
var Width, Height: Integer);
begin
Height:=ACanvas.TextHeight('Caption1')+5;
Width:=ACanvas.TextWidth('Caption1')+5;
iRate:=Round(Image1.Height/(Height*6));
iW:=Round(Image1.Width /iRate);
Width:=Width+iW;
end;
procedure TForm1.Caption5MeasureItem(Sender: TObject; ACanvas: TCanvas;
var Width, Height: Integer);
begin
Height:=ACanvas.TextHeight('Caption1')+5;
Width:=ACanvas.TextWidth('Caption1')+5;
iRate:=Round(Image1.Height/(Height*6));
iW:=Round(Image1.Width /iRate);
Width:=Width+iW;
end;
procedure TForm1.Caption6MeasureItem(Sender: TObject; ACanvas: TCanvas;
var Width, Height: Integer);
begin
Height:=ACanvas.TextHeight('Caption1')+5;
Width:=ACanvas.TextWidth('Caption1')+5;
iRate:=Round(Image1.Height/(Height*6));
iW:=Round(Image1.Width /iRate);
Width:=Width+iW;
end;
procedure TForm1.Caption1DrawItem(Sender: TObject; ACanvas: TCanvas;
ARect: TRect; Selected: Boolean);
begin
DrawItem(TMenuItem(Sender),ACanvas,ARect,Selected,'Caption1');
end;
procedure TForm1.Caption2DrawItem(Sender: TObject; ACanvas: TCanvas;
ARect: TRect; Selected: Boolean);
begin
DrawItem(TMenuItem(Sender),ACanvas,ARect,Selected,'Caption2');
end;
procedure TForm1.Caption3DrawItem(Sender: TObject; ACanvas: TCanvas;
ARect: TRect; Selected: Boolean);
begin
DrawItem(TMenuItem(Sender),ACanvas,ARect,Selected,'Caption3');
end;
procedure TForm1.Caption4DrawItem(Sender: TObject; ACanvas: TCanvas;
ARect: TRect; Selected: Boolean);
begin
DrawItem(TMenuItem(Sender),ACanvas,ARect,Selected,'Caption4');
end;
procedure TForm1.Caption5DrawItem(Sender: TObject; ACanvas: TCanvas;
ARect: TRect; Selected: Boolean);
begin
DrawItem(TMenuItem(Sender),ACanvas,ARect,Selected,'Caption5');
end;
procedure TForm1.Caption6DrawItem(Sender: TObject; ACanvas: TCanvas;
ARect: TRect; Selected: Boolean);
begin
DrawItem(TMenuItem(Sender),ACanvas,ARect,Selected,'Caption6');
end;
end.