动态彩色菜单(带图标)制作的问题?
各位大虾把我的下面的程序拷到unit1(新建一个Application,然后全部删除unit1单元内容,再拷贝,这也是为了大家节省点时间,呵呵)单元中调试一下,为什么主菜单(指的是显示在最前头的主菜单0,主菜单1……主菜单5等),没有响应我的N0DrawItem事件设置背景和字体大小等呢?而且只有主菜单5的一级子菜单和二级子菜单响应了我的N1DrawItem和N2DrawItem事件,这是为什么……,能不能帮忙看看,另外,如果要给每个菜单项(所有的,包括主菜单、一级子菜单和二级子菜单)添加一个图标,如何实现?请各位高手赐教,泻分100!
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, Menus, StdCtrls;
type
TForm1 = class(TForm)
procedure N0DrawItem(Sender: TObject; ACanvas: TCanvas; ARect: TRect;
Selected: Boolean); //完绘成主菜单背景、字体颜色及制区域设置
procedure N1DrawItem(Sender: TObject; ACanvas: TCanvas; ARect: TRect;
Selected: Boolean); //完绘一级菜单背景、字体颜色及制区域设置
procedure N2DrawItem(Sender: TObject; ACanvas: TCanvas; ARect: TRect;
Selected: Boolean); //完绘二级菜单背景、字体颜色及制区域设置
procedure FormCreate(Sender: TObject);
private
objMenuItem,objSMenuItem,objSSMenuItem:TMenuItem;
objMainMenu:TMainMenu;
{MainMenu1: TMainMenu;
M: TMenuItem; //主菜单
S1:TMenuItem; // 一级子菜单
S2:TMenuItem; //二级子菜单 }
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.N0DrawItem(Sender: TObject; ACanvas: TCanvas; ARect: TRect;
Selected: Boolean);
begin
ACanvas.Font.Color:=clRed;
ACanvas.Font.Size:=18;
if Selected then
SetBkColor(ACanvas.Handle,clSkyBlue)
else
SetBkColor(ACanvas.Handle,clWhite);
ACanvas.TextRect(ARect,ARect.Left,ARect.Top,(Sender as TMenuItem).Caption);
end;
procedure TForm1.N1DrawItem(Sender: TObject; ACanvas: TCanvas;
ARect: TRect; Selected: Boolean);
begin
ACanvas.Font.Color:=clYellow;
ACanvas.Font.Size:=14;
if Selected then
SetBkColor(ACanvas.Handle,clRed) //设置选中时的背景色
else
SetBkColor(ACanvas.Handle,clWhite); //设置未选中时的背景色
ACanvas.TextRect(ARect,ARect.Left,ARect.Top,(Sender as TMenuItem).Caption);
end;
procedure TForm1.N2DrawItem(Sender: TObject; ACanvas: TCanvas;
ARect: TRect; Selected: Boolean);
begin
ACanvas.Font.Color:=clLime;
ACanvas.Font.Size:=10;
if Selected then
SetBkColor(ACanvas.Handle,clBlue)
else
SetBkColor(ACanvas.Handle,clWhite);
ACanvas.TextRect(ARect,ARect.Left,ARect.Top,(Sender as TMenuItem).Caption);
end;
procedure TForm1.FormCreate(Sender: TObject);
var i,j,k:Integer;
begin
objMainMenu:=TMainMenu.Create(self);
objMainMenu.AutoHotkeys:=maManual;
objMainMenu.OwnerDraw:=True;
for i:=0 to 5 do
begin
objMenuItem:=TMenuItem.Create(self);
objMenuItem.Caption:='主菜单'+Inttostr(i);
objMenuItem.Name:='MenuE'+inttostr(i);
objMainMenu.Items.Add(objMenuItem);
for j:=0 to 5 do
begin
objSMenuItem:=TMenuItem.Create(self);
objSMenuItem.Caption:='一级子菜单'+Inttostr(j);
objSMenuItem.Name:='SMenuEx'+Inttostr(i)+Inttostr(j);
objMainMenu.Items[i].add(objSMenuItem);
for k:=0 to 5 do
begin
objSSMenuItem:=TMenuItem.Create(self);
objSSMenuItem.Caption:='二级子菜单'+inttostr(k);
objSSMenuItem.Name:='SSMenuExs'+Inttostr(i)+Inttostr(j)+Inttostr(k);
objMainMenu.Items[i].Items[j].add(objSSMenuItem);
end;
end;
end;
objMainMenu.Items.OnDrawItem:= N0DrawItem; //注意这句话不起作用,没有对主菜单进行相应设置,为什么?
for i:=0 to 5 do
begin
objMenuItem.Items[i].OnDrawItem:= N1DrawItem;
for j:=0 to 5 do
objMenuItem.Items[i].Items[j].OnDrawItem:=N2DrawItem;
end;
end;
end.
问题点数:100、回复次数:22Top
1 楼jinjazz(近身剪)回复于 2006-03-15 17:02:26 得分 0
参考http://borland.mblogger.cn/jinjazz/posts/21287.aspxTop
2 楼zyr76(Andy)回复于 2006-03-15 17:16:15 得分 0
我已经参考过了,不过还没怎么弄明白,请问就这个问题怎么办?Top
3 楼zyr76(Andy)回复于 2006-03-16 09:44:28 得分 0
为什么没有人回答我呀,郁闷!请高手赐教吧Top
4 楼hahafan(注意!此人前途迷茫)回复于 2006-03-16 10:11:38 得分 100
添加DrawItem事件的方法不对,应该放在创建菜单的循环中
procedure TForm1.FormCreate(Sender: TObject);
var i,j,k:Integer;
begin
objMainMenu:=TMainMenu.Create(self);
objMainMenu.AutoHotkeys:=maManual;
objMainMenu.OwnerDraw:=True;
for i:=0 to 5 do
begin
objMenuItem:=TMenuItem.Create(self);
objMenuItem.Caption:='主菜单'+Inttostr(i);
objMenuItem.Name:='MenuE'+inttostr(i);
objMainMenu.Items.Add(objMenuItem);
objMenuItem.OnDrawItem := N0DrawItem; //一级菜单绘制
for j:=0 to 5 do
begin
objSMenuItem:=TMenuItem.Create(self);
objSMenuItem.Caption:='一级子菜单'+Inttostr(j);
objSMenuItem.Name:='SMenuEx'+Inttostr(i)+Inttostr(j);
objMainMenu.Items[i].add(objSMenuItem);
objSMenuItem.OnDrawItem := N1DrawItem; //二级菜单绘制
for k:=0 to 5 do
begin
objSSMenuItem:=TMenuItem.Create(self);
objSSMenuItem.Caption:='二级子菜单'+inttostr(k);
objSSMenuItem.Name:='SSMenuExs'+Inttostr(i)+Inttostr(j)+Inttostr(k);
objMainMenu.Items[i].Items[j].add(objSSMenuItem);
objSSMenuItem.OnDrawItem := N2DrawItem; //三级菜单绘制
end;
end;
end;
// objMainMenu.Items.OnDrawItem:= N0DrawItem; //注意这句话不起作用,没有对主菜单进行相应设置,为什么?
// for i:=0 to 5 do
// begin
// objMenuItem.Items[i].OnDrawItem:= N1DrawItem;
// for j:=0 to 5 do
// objMenuItem.Items[i].Items[j].OnDrawItem:=N2DrawItem;
// end;
end;
Top
5 楼zyr76(Andy)回复于 2006-03-21 09:38:18 得分 0
先感谢hahafan,此方法可行,再请教如果要改变菜单项的字体大小,并且在其前面加图标,怎么办?谢谢!,先给部分分,如何!Top
6 楼zyr76(Andy)回复于 2006-03-21 09:41:26 得分 0
hahafan,好像部分分给不了,您能否好人做到底,给我一个满意的答复,马上给分,也欢迎其他高手参与,同样给分,先谢了!Top
7 楼hahafan(注意!此人前途迷茫)回复于 2006-03-21 11:18:43 得分 0
图标可以在DrawItem画,比如你有个ImageList1,下面是给你的一级菜单画图标的方法:
procedure TForm1.N0DrawItem(Sender: TObject; ACanvas: TCanvas; ARect: TRect;
Selected: Boolean);
begin
ACanvas.Font.Color:=clRed;
ACanvas.Font.Size:=18;
if Selected then
SetBkColor(ACanvas.Handle,clSkyBlue)
else
SetBkColor(ACanvas.Handle,clWhite);
ACanvas.TextRect(ARect,ARect.Left,ARect.Top,(Sender as TMenuItem).Caption);
ImageList1.Draw(ACanvas, ARect.Left, ARect.Top,0, True);//画图标
end;
Top
8 楼zyr76(Andy)回复于 2006-03-28 09:21:16 得分 0
hahafan,我知道你是个高手,那就请问字体大小设置后,如何使菜单项适应其大小呢?这是最后一个问题了,答后马上给分!Thank you so much……Top
9 楼hahafan(注意!此人前途迷茫)回复于 2006-03-28 10:42:22 得分 0
设置菜单大小可以在TMenuItem的OnMeasureItem中处理。
不过顶层菜单的高度可能会受限于标题栏的高度。Top
10 楼yq3woaini(哈哈镜 选择好心情)回复于 2006-03-28 21:59:52 得分 0
参看 raise控件的写法,里面都有Top
11 楼zyr76(Andy)回复于 2006-03-29 09:45:31 得分 0
不处理顶层菜单高度也可以,你能不能结合我的问题给个代码呢?raise控件在哪看呀?Top
12 楼hahafan(注意!此人前途迷茫)回复于 2006-03-29 11:02:54 得分 0
在创建菜单时把该方法赋给菜单的OnMeasureItem
procedure TForm1.N1MeasureItem(Sender: TObject; ACanvas: TCanvas;
var Width, Height: Integer);
begin
ACanvas.Font.Size:=14;
Width := ImageList1.Width + ACanvas.TextWidth(TMenuItem(Sender).Caption) + 5;
Height := Canvas.TextHeight(TMenuItem(Sender).Caption) + 5;
end;
Top
13 楼yq3woaini(哈哈镜 选择好心情)回复于 2006-03-29 12:40:04 得分 0
2ccc.com
中国盟动力
下载一个看看里面有源代码Top
14 楼zyr76(Andy)回复于 2006-03-29 15:50:07 得分 0
hahafan,我试了一下你的方法,发现字体未变化(改变字体时),但菜单项的宽度有变化,为什么?另外,你的Width和Height参数代表菜单项的宽度和高度嘛?Top
15 楼hahafan(注意!此人前途迷茫)回复于 2006-03-29 17:28:43 得分 0
不太清除你说的是什么情况,能不能具体点或把代码贴出来看看。
Width和Height就是代表菜单的宽和高,就是通过设置他们来设置菜单大小。Top
16 楼reborter(www.xqblog.net我的博客)回复于 2006-03-29 20:54:18 得分 0
学习
Top
17 楼zyr76(Andy)回复于 2006-04-03 13:25:13 得分 0
hahafan,我按你的代码演示了一下,发现设置字体大小时(运行时字体大小不变)但菜单项的宽度有变化,为什么?代码如下:(新建一个APPLICATON后在FORM上添加IMAGELIST控件即可),下面的代码是Unit1单元代码:
-----------------------------------------
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, Menus, StdCtrls, ImgList;
type
TForm1 = class(TForm)
ImageList1: TImageList;
procedure N0DrawItem(Sender: TObject; ACanvas: TCanvas; ARect: TRect;
Selected: Boolean); //完绘成主菜单背景、字体颜色及制区域设置
procedure N1DrawItem(Sender: TObject; ACanvas: TCanvas; ARect: TRect;
Selected: Boolean); //完绘一级菜单背景、字体颜色及制区域设置
procedure N2DrawItem(Sender: TObject; ACanvas: TCanvas; ARect: TRect;
Selected: Boolean); //完绘二级菜单背景、字体颜色及制区域设置
// procedure MenuMeasureItem(Sender: TObject; ACanvas: TCanvas; var Width, Height: Integer);
procedure N1MeasureItem(Sender: TObject; ACanvas: TCanvas;
var Width, Height: Integer);
procedure FormCreate(Sender: TObject);
private
objMenuItem,objSMenuItem,objSSMenuItem:TMenuItem;
objMainMenu:TMainMenu;
{MainMenu1: TMainMenu;
M: TMenuItem; //主菜单
S1:TMenuItem; // 一级子菜单
S2:TMenuItem; //二级子菜单 }
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
{procedure TForm1.MenuMeasureItem(Sender: TObject; ACanvas: TCanvas; var Width, Height: Integer);
begin
Height:=20;
end; }
procedure TForm1.N1MeasureItem(Sender: TObject; ACanvas: TCanvas;
var Width, Height: Integer);
begin
ACanvas.Font.Size:=14; //修改字体大小可使菜单项宽度增加或减小,但运行时字体大小不变,为什么???
Width := ImageList1.Width + ACanvas.TextWidth(TMenuItem(Sender).Caption)+ 5 ;
Height := Canvas.TextHeight(TMenuItem(Sender).Caption)+ 5 ;
end;
procedure TForm1.N0DrawItem(Sender: TObject; ACanvas: TCanvas; ARect: TRect;
Selected: Boolean);
begin
ACanvas.Font.Color:=clRed;
ACanvas.Font.Size:=12;
if Selected then
SetBkColor(ACanvas.Handle,clSkyBlue)
else
SetBkColor(ACanvas.Handle,clGray);
ACanvas.TextRect(ARect,ARect.Left,ARect.Top,(Sender as TMenuItem).Caption);
ImageList1.Draw(ACanvas, ARect.Left, ARect.Top,0, true);//画图标
end;
procedure TForm1.N1DrawItem(Sender: TObject; ACanvas: TCanvas;
ARect: TRect; Selected: Boolean);
begin
ACanvas.Font.Color:=clYellow;
ACanvas.Font.Size:=12;
if Selected then
SetBkColor(ACanvas.Handle,clRed) //设置选中时的背景色
else
SetBkColor(ACanvas.Handle,clGray); //设置未选中时的背景色
ACanvas.TextRect(ARect,ARect.Left,ARect.Top,(Sender as TMenuItem).Caption);
ImageList1.Draw(ACanvas, ARect.Left, ARect.Top,1, true);//画图标
end;
procedure TForm1.N2DrawItem(Sender: TObject; ACanvas: TCanvas;
ARect: TRect; Selected: Boolean);
begin
ACanvas.Font.Color:=clLime;
ACanvas.Font.Size:=12;
if Selected then
SetBkColor(ACanvas.Handle,clBlue)
else
SetBkColor(ACanvas.Handle,clGray);
ACanvas.TextRect(ARect,ARect.Left,ARect.Top,(Sender as TMenuItem).Caption);
ImageList1.Draw(ACanvas, ARect.Left, ARect.Top,2, true);//画图标
end;
procedure TForm1.FormCreate(Sender: TObject);
var i,j,k:Integer;
begin
objMainMenu:=TMainMenu.Create(self);
objMainMenu.AutoHotkeys:=maManual;
objMainMenu.OwnerDraw:=True;
for i:=0 to 5 do
begin
objMenuItem:=TMenuItem.Create(self);
objMenuItem.Caption:='主菜单'+Inttostr(i);
objMenuItem.Name:='MenuE'+inttostr(i);
objMainMenu.Items.Add(objMenuItem);
objMenuItem.OnDrawItem := N0DrawItem; //主菜单单绘制
objMenuItem.OnMeasureItem:=N1MeasureItem;
//objMenuItem.OnMeasureItem:=MenuMeasureItem;
for j:=0 to 5 do
begin
objSMenuItem:=TMenuItem.Create(self);
objSMenuItem.Caption:='一级子菜单'+Inttostr(j);
objSMenuItem.Name:='SMenuEx'+Inttostr(i)+Inttostr(j);
objMainMenu.Items[i].add(objSMenuItem);
objSMenuItem.OnDrawItem := N1DrawItem; //一级菜单绘制
objSMenuItem.OnMeasureItem:=N1MeasureItem;
for k:=0 to 5 do
begin
objSSMenuItem:=TMenuItem.Create(self);
objSSMenuItem.Caption:='二级子菜单'+inttostr(k);
objSSMenuItem.Name:='SSMenuExs'+Inttostr(i)+Inttostr(j)+Inttostr(k);
objMainMenu.Items[i].Items[j].add(objSSMenuItem);
objSSMenuItem.OnDrawItem := N2DrawItem; //二级菜单绘制
objSSMenuItem.OnMeasureItem:= N1MeasureItem;
end;
end;
end;
end;
end.Top
18 楼hahafan(注意!此人前途迷茫)回复于 2006-04-03 17:47:54 得分 0
MeasureItem设置字体大小是为了用来计算文字的长宽,对运行时字体大小没有影响,
设置运行时字体大小应该在DrawItem中,
所以你在MeasureItem设置字体大小同时应该在DrawItem也设置同样大小。Top
19 楼zyr76(Andy)回复于 2006-04-07 16:18:14 得分 0
hahafan,您好,请不要急,我会马上结贴了,但是,菜单的字体大了后,菜单项的高度又没变,导致菜单项有部分重叠现象,字体越大越明显,怎么设置来使菜单项的高度适应字体的变化?Top
20 楼hahafan(注意!此人前途迷茫)回复于 2006-04-07 17:02:26 得分 0
Height := Canvas.TextHeight(TMenuItem(Sender).Caption)+ 5;
不起作用?那改成下面试试:
Height := Abs(ACanvas.Font.Height) + 5;
Top
21 楼zyr76(Andy)回复于 2006-04-10 14:01:27 得分 0
hahafan,你好,你有没有电子邮件什么的,有机会再请教,先结贴,谢谢!Top
22 楼hahafan(注意!此人前途迷茫)回复于 2006-04-11 09:16:25 得分 0
hahafan1030@163.com
共同进步Top




