|
DELPHI 程序设计讲座(四)
一个动态菜单演示程序
董占山
(中国农科院棉花所,河南安阳,455112)
提要 本文详细地介绍了使用DELPHI创建WINDOWS应用程序主菜单的方法和步骤,并重点讲解了隐藏/显示菜单项、动态修改菜单项、增加/删除菜单项、操纵系统控制菜单的方法。
大多数 WINDOWS应用程序都拥有一个菜单条,单击菜单条,可以从弹出的下拉菜单中执行各种菜单命令,用来启动应用程序的各种功能。由于使用了菜单,使WINDOWS应用程序变得简明易用,倍受用户称赞。用DELPHI可以方便快捷地创建WINDOWS应用程序的主菜单或弹出菜单,通过调用WINDOWS的API函数还可以操纵WINDOWS应用程序的系统控制菜单。
程序界面设计
首先设计并创建动态菜单演示程序的用户界面。为了完成动态菜单的演示,最基本的组件有:一个窗体组件 Form和一个菜单组件MainMenu。为了使程序主窗口不显得单调乏味,在窗体中再加入一个Memo组件,其中显示一些说明性的文字。表1列出了这3个组件的主要创建属性。
表 1 主窗体及其组件的主要创建属性
组件名 |
属性名 |
取值 |
Form |
Caption
Name
Position
Height
Width |
动态菜单
frmMain
DefaultPosOnly
213
483 |
Memo |
Alignment
Color
Cursor
DragCursor
Height
Left
Modify
Name
Top
Width |
taLeftJustify
clBtnFace
crArrow
crArrow
145
8
FALSE
Memo1
8
321 |
MainMenu |
Name |
MainMenu |
为了让 Memo组件显示文字,需要设置“Line”属性,具体步骤如下:
选中窗体中的“Memo”组件;
单击“Object Inspector”窗口中属性页中的“Lines”属性的右边的省略号按钮,弹出一个串表编辑器,见图1所示;
在编辑框中输入图1所示的文字,单击〖OK〗按钮返回,在窗体的Memo组件中就立即显示出刚输入的文字了。
图1 Lines属性编辑器
这时 Memo组件中的文字的式样和窗体标题的一样,为了美观,再设置一下“Font”属性,使文字以“黄色”、“宋体”、“Bold”、“小四”显示。具体步骤如下:
单击“Object Inspector”窗口中“Font”属性右边的省略号按钮,弹出一个字体属性的编辑窗口,见图2所示;
选中“字体”列表框中的“宋体”选项;
选中“字体样式”列表框中的“Bold”选项;
选中“大小”列表框中“小四”选项;
单击“颜色”下拉列表框,弹出一个颜色列表框;
选中“黄色”选项;
单击对话窗口的〖确定〗按钮完成设置,这时在窗体中可以看到刚才设置的实际效果。
图2 字体属性编辑器
主菜单的设计
主菜单的设计是本文的主要目的。使用 DELPHI的菜单设计器(Menu Designer),可以快捷地设计出应用程序的主菜单。具体步骤如下:
选中主菜单组件MainMenu;
将鼠标指针定位在主菜单组件MainMenu上,单击鼠标右键,弹出一个快捷菜单;
单击快捷菜单中的“Menu
Designer”命令,弹出类似于图3所示的窗口;
在“Object Inspector”窗口的“Caption”属性的编辑框中输入“文件[&F]”,在“Name”属性的编辑框中输入“mnFile”;
按回车键,开始设计“文件”菜单,与第4步类似,设置“Caption”属性为“新建[&N]”,设置“Name”属性为“mnNew”;
依次类推,可以很容易地按表2所列出的菜单项目设置完“文件”菜单;注意:只要将菜单项的“Caption”属性设置为单字节连字符“-”,就可以得到一个横隔线;
用鼠标单击“文件[F]”项目右边的虚线框,可以设计下一个菜单;重复步骤4~7可以很快地设计好该程序的主菜单;
图3 菜单编辑器
注意:需要在两个菜单项目之间插入一个菜单项目时,首先用鼠标指针单击下面(后面)的项目,然后按一次 <INSERT>键,即可在两个项目之间插入一个空项目。
欲为菜单项设计一个快捷键时,单击“ Object Inspector”窗口中“ShortCut”属性右半部,从弹出的列表框中选择一个合适的快捷键即可。
根据表 2所给出的属性值,利用“Menu
Designer”和“Object
Inspector”设计所有菜单项,设计完成的主菜单如图3所示。
表 2 菜单项目的创建属性
菜单 |
标题 (Caption) |
标识名称 (Name) |
快捷键 (ShortCut) |
可见性 (Visible) |
| |
文件 [&F] |
mnFile |
|
TRUE |
文件 |
新建 [&N] |
mnNew |
|
TRUE |
文件 |
打开 [&O] |
mnOpen |
CTRL+O |
TRUE |
文件 |
保存 [&S] |
mnSave |
CTRL+S |
TRUE |
文件 |
-( 分隔符) |
N1 |
|
TRUE |
文件 |
打印机设置 [&U] |
mnPrinterSetup |
|
FALSE |
文件 |
打印 [&P] |
mnPrint |
CTRL+P |
FALSE |
文件 |
-( 分隔符) |
N2 |
|
FALSE |
文件 |
退出 [&X] |
mnExit |
CTRL+X |
TRUE |
| |
编辑 [&E] |
mnEdit |
|
FALSE |
编辑 |
取消删除 [&U] |
mnUndo |
|
TRUE |
编辑 |
-( 分隔符) |
N3 |
|
TRUE |
编辑 |
剪切 [&C] |
mnCut |
|
TRUE |
编辑 |
复制 [&O] |
mnCopy |
|
TRUE |
编辑 |
粘贴 [&P] |
mnPaste |
|
TRUE |
编辑 |
-( 分隔符) |
N4 |
|
TRUE |
编辑 |
全选 [&A] |
mnAll |
|
TRUE |
| |
窗口 [&W] |
mnWindow |
|
FALSE |
| |
帮助 [&H] |
mnHelp |
|
TRUE |
帮助 |
关于 [&A] |
mnAbout |
|
TRUE |
本例的宗旨是演示动态菜单的设计,所以只对“文件”菜单中的“退出”菜单项和“帮助”菜单中的“关于”菜单项设计了事件响应程序,其余菜单项均不加解释。下面就是单击“退出”菜单项时的事件响应过程:
procedure TfrmMain.mnExitClick(Sender: TObject);
begin
Close;
end;
现在需要保存一下刚才的工作,将窗体单元命名为 MainForm,将项目命名为Menu。
为程序增加一个窗体
为了显示系统的版本信息,需要为程序增加一个对话窗口,在其中显示程序的版本、设计目的、版权等信息,也就是创建一个关于 (About)对话窗口,具体步骤如下:
单击“文件”菜单中“New”命令,弹出“New Item”对话窗口;
单击该对话窗口中的“Forms”选项卡标签;
选中“About box”项;
单击〖OK〗按钮返回,这时在屏幕上出现一个About对话窗口的样板,在相应的栏目中输入合适的文字,About窗体就设计好了。设计完成的About对话窗口如图4所示。
图4 关于对话窗口
将与刚设计好的 About窗体对应的代码单元保存为ABOUT.PAS。下一步的工作是将About窗体连接到主窗体上。切换到代码编辑窗口,在MainForm单元的“implementation”下面加上一条命令:
uses About;
然后,单击“帮助”菜单中的“关于”命令,创建“关于”命令的事件响应程序如下:
procedure TfrmMain.mnAboutClick(Sender: TObject);
begin
AboutBox1.ShowModal;
end;
这样, About窗体和主窗体就连接在一起了。单击DELPHI的“File”菜单中“Save All”命令,保存与项目有关的所有文件。
改变主菜单
为了动态地改变主菜单,现在在窗体内增加 3个按钮,分别用来完成显示/隐藏部分菜单项、添加/删除菜单项、动态修改/恢复菜单项。表3列出了3个按钮的设计属性。
表 3 三个按钮的设计属性
组件 |
属性 |
取值 |
Button1 |
Caption
Name
Left
Top |
显示整个菜单
btnShowHide
344
8 |
Button2 |
Caption
Name
Left
Top |
添加菜单项
btnAddDelete
344
48 |
Button3 |
Caption
Name
Left
Top |
动态修改菜单项
btnModify
344
88 |
那么如何控制菜单项的显示与否呢?其实很简单,在设计菜单时,我们曾经将某些菜单项的“ Visible”属性设置为“FALSE”,所以在程序运行时,这些菜单项就未显示在主菜单上。在程序运行过程中,只要将他们的“Visible”属性设置为“TRUE”,就可以使他们显示到菜单中。下面就是单击btnShowHide按钮时的事件响应程序。在这段程序的最后用了一个IF语句,以便让按钮的标题根据菜单的当前状态不断切换。
procedure TfrmMain.btnShowHideClick(Sender: TObject);
begin
mnEdit.Visible := not mnEdit.Visible;
mnWindow.Visible := not mnWindow.Visible;
mnPrinterSetup.Visible := not mnPrinterSetup.Visible;
mnPrint.Visible := not mnPrint.Visible;
n4.Visible := not n4.Visible;
btnAddDelete.Enabled := not btnAddDelete.Enabled;
if btnShowHide.Caption = ' 显示整个菜单' then
btnShowHide.Caption := ' 隐藏部分菜单'
else
btnShowHide.Caption := ' 显示整个菜单';
end;
动态地修改菜单项的提示,就是改变菜单项的“ Caption”属性,使其随环境的变化而变化。下面是单击btnModify按钮时的事件响应程序。
procedure TfrmMain.btnModifyClick(Sender: TObject);
begin
if btnModify.Caption = ' 动态修改菜单项' then
begin
btnModify.Caption := ' 恢复菜单项' ;
mnFile.Caption := '&File';
mnNew.Caption := '&New';
mnOpen.Caption := '&Open';
mnSave.Caption := '&Save';
mnExit.Caption := 'E&xit';
end
else
begin
btnModify.Caption := ' 动态修改菜单项';
mnFile.Caption := ' 文件[&F]';
mnNew.Caption := ' 新建[&N]';
mnOpen.Caption := ' 打开[&O]';
mnSave.Caption := ' 保存[&S]';
mnExit.Caption := ' 退出[&X]';
end;
end;
要向菜单中添加一个菜单项或删除一个菜单项就比较复杂了。要添加一个菜单项,必须先声明一个类型为 TMenuItem的变量,例如mnFile1,然后用TMenuItem的Create方法创建它,接着赋予它一个名称,即设置其Caption属性,最后用TMenuItem的Insert方法将它插入到菜单中。删除一个菜单项较为简单,只要调用TMenuItem的Delete方法即可。具体方法见下面单击btnAddDelete按钮时的事件响应程序。
procedure TfrmMain.btnAddDeleteClick(Sender: TObject);
var mnFile1,mnFile2,mnFile3 : TMenuItem;
begin
if btnAddDelete.Caption = ' 添加菜单项' then
begin
mnFile1 := TMenuItem.Create(mnWindow);
mnFile1.Caption := '&1 Dong';
mnWindow.Insert(0, mnFile1);
mnFile2 := TMenuItem.Create(mnWindow);
mnFile2.Caption := '&2 Li';
mnWindow.Insert(1, mnFile2);
mnFile3 := TMenuItem.Create(mnWindow);
mnFile3.Caption := '&3 Zhu';
mnWindow.Insert(2, mnFile3);
btnAddDelete.Caption := ' 删除菜单项';
end
else
begin
mnWindow.Delete(2);
mnWindow.Delete(1);
mnWindow.Delete(0);
btnAddDelete.Caption := ' 添加菜单项';
end;
end;
操纵系统控制菜单
为了演示操纵系统控制菜单的方法,还需要向窗体增加一个按钮,其设计属性见表 4。
表 4 操纵系统控制菜单按钮的属性
组件 |
属性 |
取值 |
Button4 |
Caption
Name
Left
Top |
修改系统菜单
btnSystemMenu
344
128 |
要操纵窗口的系统控制菜单,需要用到 Windows应用程序接口(API)中的几个函数,这些函数的头部在输入单元Windows中进行了定义。本例中使用了GetSystemMenu、AppendMenu、CheckMenuItem、DeleteMenu、GetMenuItemCount等5个函数,其实还有许多函数,在此,笔者将不详细介绍这些函数的使用方法,有兴趣的读者可以参考DELPHI提供的在线帮助信息,查阅每个函数的具体使用方法。下面是单击btnSystemMenu按钮时的事件响应程序。
procedure TfrmMain.btnSystemMenuClick(Sender: TObject);
var
hSysMenu,AppendItem,i : Integer;
begin
AppendItem := $FFF;
hSysMenu := GetSystemMenu(frmMain.Handle,False);
if btnSystemMenu.Caption = ' 修改系统菜单' then
begin
btnSystemMenu.Caption := ' 恢复系统菜单';
AppendMenu(hSysMenu,MF_ENABLED or MF_STRING,AppendItem,' 演示添加项目');
for i := 0 to GetMenuItemCount(hSysMenu) - 1 do
CheckMenuItem(hSysMenu,i,MF_BYPOSITION or MF_Checked);
end
else
begin
btnSystemMenu.Caption := ' 修改系统菜单' ;
DeleteMenu(hSysMenu,AppendItem,MF_BYCOMMAND);
for i := 0 to GetMenuItemCount(hSysMenu) - 1 do
CheckMenuItem(hSysMenu,i,MF_BYPOSITION or MF_UNChecked);
end;
end;
至此,这个演示程序已经设计完毕,先保存这个项目,然后,单击“ Run”菜单中“Run”命令,编译并运行项目,如果出现编译错误,回过头与文中的程序清单对照一下,看那里打错了,纠正之,再编译运行。最后完成的动态菜单演示程序的运行窗口如图5所示。
图 5 动态菜单演示程序的运行窗口
|