扫一扫
分享文章到微信
扫一扫
关注官方公众号
至顶头条
BOOL AppendMenu(
HMENU hMenu, // 要定制的菜单句柄
UINT uFlags, // 怎样定制菜单项
UINT uIDNewItem, // 要定制的菜单项标识或子菜单句柄
LPCTSTR lpNewItem // 要定制的菜单项(字串)
);
在 AppendMenu 函数里,lpNewItem 和 uIDNewItem 参数依赖 uFlags 的不同
标志而有所变化,让我们来看一看 uFlags 到底有那一些定义值:
MF_BITMAP 指明该菜单项是一位图,在 lpNewItem 参数代表位图句柄
MF_CHECKED 在菜单项的前面放上一个“选中”标记
MF_DISABLED 屏蔽该菜单项,但不象平常那样变成灰色
MF_ENABLED 与 MF_DISABLED 相反
MF_GRAYED 除了有 MF_DISABLED 的作用以外,还把该菜单项变灰
MF_MENUBREAK 把该菜单与现有菜单并排放在一起
MF_MENUBARBREAK 与 MF_MENUBREAK 相同,除了在中间放一条竖线外
MF_OWNERDRAW 表明该菜单项为自绘菜单项,还必须处理一切的显示、更新问题
MF_POPUP 该菜单项为一子菜单,uIDNewItem 参数代表其句柄
MF_SEPARATOR 与上一菜单项画上一分割线,系统将忽略 lpNewItem 和
uIDNewItem 参数
MF_STRING 该菜单项是一文本字串,lpNewItem 是其内容
MF_UNCHECKED 取消该菜单项前面的“选中”标记
我们看到,除了MF_POPUP,MF_BITMAP,MF_OWNERDRAW以外,MF_STRING是最常用的菜单? 义方法,uIDNewItem在这里是命令消息的wParam参数。朋友们还记得获取普通菜单的句柄用GetMenu,那么获取系统菜单的句柄就应该用GetSyst-emMenu。这时有一个问题:程序怎么知道该获取的系统菜单是窗口上的系统菜单,还是任务栏上的系统菜单呢?这就依靠传递给GetSystemMenu的是哪一个参数。因为我们当前考虑的是任栏,因此这个参数就必须是Application.Handle。如果这时候就着手编制一个Project检验一下,朋友们就会发现...“我”定义的菜单怎么没有反应!原来该菜单项根本没有在Application里处理过。显然,我们还得过滤一下传到Application的WM_SYSCOMMAND消息。为了加深了解,我们首先追加一个简单的任务栏系统菜单:
Unit AddMenuDemo;
interface
uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms,
Dialogs,Menus;
type
TDemoForm = class(TForm)
procedure FormCreate(Sender: TObject);
...private
{ Private declarations }
// 我的消息过滤器
procedure OnAppMessage(var Msg: TMsg; var Handled: Boolean);
...public
{ Public declarations }
...end;
var
DemoForm1: TDemoForm;
implementation
constMy_SimpleCMD1 = WM_USER + 1; // 定义三个用户消息,用来处理菜单项被点击
// 时相应的动作
My_SimpleCMD2 = WM_USER + 2;
My_SimpleCMD3 = WM_USER + 3;
...
procedure TDemoForm1.FormCreate(Sender: TObject);
beginApplication.OnMessage := OnAppMessage; //定义自己的消息处理过程
//定义了提交、反馈、处理三个菜单项
AppendMenu(GetSystemMenu(Application.Handle, FALSE),MF_STRING,
My_SimpleCMD1,提交);
AppendMenu(GetSystemMenu(Application.Handle, FALSE),MF_STRING,
My_SimpleCMD2,反馈);
AppendMenu(GetSystemMenu(Application.Handle, FALSE),MF_SEPARATOR,
0, ); // 定义一分割线
AppendMenu(GetSystemMenu(Application.Handle, FALSE),MF_STRING,
My_SimpleCMD3,处理);end;
procedure TDemoForm1.OnAppMessage(var Msg: TMsg; var Handled: Boolean);
begin
// 定制自己的消息处理过程if (Msg.message = WM_SYSCOMMAND) and (Msg.wParam = My_SimpleCMD1) then
beginShowMessage(正在提交...);
Handled := True;
...end;
if (Msg.message = WM_SYSCOMMAND) and (Msg.wParam = My_SimpleCMD2) then
beginShowMessage(正在反馈...);
Handled := True;
...end;
if (Msg.message = WM_SYSCOMMAND) and (Msg.wParam = My_SimpleCMD3) then
beginShowMessage(正在处理...);
Handled := True;
...end;
end;
....
当我们处理的事务比较多并且可分组,以上的做法就比较烦琐,这时就应该定义成多个 MF_POPUP ,其各个子菜单除了uIDNewItem 传递这个子菜单的句柄外,另外独特之处在于消息过滤器的 Msg.wParam 是各个菜单项的 Command。这个Command是在构建 TPopupMenu 时就定义了。无论是否是 MenuItem 或 PopupMenu,其Command的值都是顺序递增的。以下是一范例:
unit Unit1;
interface
uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms,
Dialogs, Menus;
typeTForm1 = class(TForm)
PopupMenu1: TPopupMenu;
N1: TMenuItem; // Caption := 范例一;
N2: TMenuItem; // Caption := 范例二;
N3: TMenuItem; // Caption := 范例三;
procedure FormCreate(Sender: TObject);
...
private{ Private declarations }
// 我的消息过滤器
procedure OnAppMessage(var Msg: TMsg; var Handled: Boolean);
...public
{ Public declarations }
...end;
...
var
Form1: TForm1;
implementation
{$R *.DFM}
procedure TForm1.FormCreate(Sender: TObject);
beginApplication.OnMessage := OnAppMessage; //定义自己的消息处理过程
// 定义一分割线
AppendMenu(GetSystemMenu(Application.Handle, FALSE), MF_SEPARATOR, 0, );
// 定义提交子菜单
AppendMenu(GetSystemMenu(Application.Handle, FALSE), MF_POPUP,
PopupMenu1.Handle,提交);end;
procedure TForm1.OnAppMessage(var Msg: TMsg; var Handled: Boolean);
begin
// 定制自己的消息处理过程
if (Msg.message = WM_SYSCOMMAND) AND (Msg.wParam $#@60; WM_USER) then
beginCase Msg.wParam of
// N1.Command = 1
1:ShowMessage(范例一 Command:+ IntToStr(N1.Command));
// N1.Command = 2
2:ShowMessage(范例二 Command:+ IntToStr(N2.Command));
// N1.Command = 3
3:ShowMessage(范例三 Command:+ IntToStr(N3.Command));end;
Handled := True;end;
...
end;
...
可以看出,MF_STRING 与 MF_POPUP 在消息处理机制上是稍微有点不同的,另外,如果要在菜单前面加上图标的话,这在Delphi 4.x、Delphi 5.x 版本下是不成问题,如果是在 Delphi 3.x 下的话,只要定义成自绘 MenuItem即可,不过稍许复杂了一点。在应用过程中,需要提醒的是,这几组定义不能一起使用:
A. MF_DISABLED, MF_ENABLED, 和 MF_GRAYED
B. MF_BITMAP, MF_STRING, 和 MF_OWNERDRAW
C. MF_MENUBARBREAK 和 MF_MENUBREAK
D. MF_CHECKED 和 MF_UNCHECKED
如果您非常迫切的想了解IT领域最新产品与技术信息,那么订阅至顶网技术邮件将是您的最佳途径之一。
现场直击|2021世界人工智能大会
直击5G创新地带,就在2021MWC上海
5G已至 转型当时——服务提供商如何把握转型的绝佳时机
寻找自己的Flag
华为开发者大会2020(Cloud)- 科技行者