一个友好的用户界面
,
必须具有下拉菜单,弹出菜单,工具条和快捷键。同样一个功能,程序员可能要提供几种操作方式,如文本拷贝,菜单命令
&Copy,
快捷键
Ctrl+C,
工具条上的拷贝按钮,都是程序员提供给用户的操作,可以大大方便了不同层次的用户。但是,多增加一种操作方式,就意味着增加响应事件的代码,还有,实现统一功能的多个操作必须一致,如剪切板上不为空的时候,菜单命令,快捷键,按钮,都是可以选择的
Enabled
状态,而剪切板上没有内容时,这些构件的
Enabled
状态都为假。当然,如果不集中控制这些细节的话,实现相同功能的构件要一致,必须多增加代码,控制较为复杂。
Action
就是将实现某个功能的细节统一管理起来,如
Caption, Checked,Enabled, HelpContext, Hint, ImageIndex, ShortCt, Visible, onExecute
等属性和事件。程序员设置
Action
属性的同时
,
还要实现执行
Action
的代码
onExecute
。定义了
Action
后,将其连接到一个菜单项,或者按钮上时,
Action
定义的属性和
OnExecute
事件,马上取代了原来的设置,并且建立了连接。通过这个连接,当
Action
的属性发生变化时,如
Enabled
发生变化,那么与之连接的构件属性都会自动更新;反过来,当构件对应的事件被执行时,
Action
的
onExecute
也被调用。
8.1.2 Action
和
ActionList
Action
是定义了最小的功能单位,使用它来在不同构件间,达到代码集中管理。表
4-12
定义了
Action
的一些属性:
ActionList
是将多个
Action
统一管理的构件,在窗体设计阶段,使用它的弹出菜单,可以增减
Action
和定义
Action
的属性。它本身的属性
Image
连接了一个
TImageList,
指出它所包含的
Action
使用那个
TImageList
来定义
ImageIndex
。
ActionLink
是一个看不见的构件,但是它是负责构件和
Action
之间建立连接的。
表
4-12 Action
属性和事件
属性和事件
具体功能
Caption
标题,可用于菜单项,
ToolButton
等。
Category
分类
Checked
设置选择状态,用于菜单项
Enabled
设置可用状态,用于与之连接的所有构件
HelpContext
帮助的索引项,用于与之相连的所有构件
Hint
智能感知,设置提示内容
ImageIndex
设置菜单项和按钮上的图片
Visible
指示与之连接的构件可否显示
ShortCut
设置菜单项的快捷键。
OnExecute
执行此
Action
的代码
OnHint
当被感知的构件显示
Hint
时调用的代码
OnUpdate
当
Action
更新构件的属性时调用的代码
我们先来认识
TActionList
。
TActionList
是从
TCustomAction
中继承来的,由它管理定义好的
Action
,是程序员在对
Action
编程的接口。
新建一个工程文件,在主窗体上增加一个
TActionList
,一个
TMemo
,一个
TImageList
,几个按钮,几个菜单项。双击
TActionlist
,会出现它的编辑界面。再单击右键选择
New standard action
,显示出预定义的
Action
类别,属性
Category
是用来表明
Action
所属类别,我们可以根据需要选择具体的类别,如图
4-10
所示,我们引入了文件操作的一些标准
Action
。
这里所列的
Action
,大部分属性已经定义好了,就是说只要把他们添加到
ActionList
中,就可以使用。同样的,也可以新建
Action
,在
Category
属性中加上自己定义的名字,之后再添加新的
Action
。
8.2.2
连接
Action
定义了
Action
后,不与菜单项和按钮连接,是不能使用的,也没有达到程序功能集中实现和管理。使用对象观察器,看看我们刚刚选择的菜单项和按钮上是否有属性
Action
。
在这些构件的
Action
属性内,选择一个
Action
之后,构件本身的很多属性都随着
Action
定义的属性发生了变化,例如菜单项的
Caption
与
Action
的属性
Caption
就一致了,构件的属性
Name
和
Tag
是不随着改变的。连接后,
Action
的属性值被拷贝到所连接构件的相应属性上,这种连接是动态地,当
Action
的属性值发生变化时,自动更新所联系的构件。
注意:如果使用的是一个
TToolButton
或着是菜单项,必须自己设置与它相联系的
Images
属性,虽然构件的
ImageIndex
属性已经动态的同
Action
相连接,但是属性
Images
并未自动连接。
继续本节的例子,通过设置菜单项和按钮的
Action
属性,完成
Action
的连接。
8.2.3
处理
Action
处理
Action
的代码可放置在
Action
的
onExecute
事件,也可以集中放置在
ActionList
的
onExecuteAction
中,还可以更集中的放置在
Application
的
onExecuteAction
事件中。改变了以往每个构件都必须对应事件的做法,程序设计上更系统化。
在本节的例子中,编写某几个
Action
的
onExecute
方法。如
FileOpenCmd
的
onExecute
事件如下:
if OpenDialog.Execute then
Memo1.LoadFromFile(OpenDialog.FileName);
8.2.3
更新
Action
属性
Action
的事件有
OnExecute
和
OnUpdate
,
OnExecute
事件在控制被触发时响应,比如说按钮被按下,菜单被按下,而
OnUpdate
事件是在应用程序空闲时被调用,用来更新
Action
的属性。
ActionList
中也有
OnUpdate,
可以用作设置菜单或者按钮的可选等属性使用。如下例
,
这个例子来自于
$Delphi\Demos\RichEdit\Richedit.Dpr
程序,有兴趣的读者可查看一下,以便更了解
Action
。
1 procedure TMainForm.ActionList2Update(Action: TBasicAction; varHandled: Boolean);
2 begin
3 EditCutCmd.Enabled := Editor.SelLength > 0;
4 EditCopyCmd.Enabled := EditCutCmd.Enabled;
5 if Editor.HandleAllocated then
6 begin
7 EditUndoCmd.Enabled := Editor.Perform(EM_CANUNDO,0, 0) <> 0;
8 EditPasteCmd.Enabled :=Editor.Perform(EM_CANPASTE, 0, 0) <> 0;
9 end;
10 end;
当应用程序空闲时,就执行这段代码,首先检查是否有被选定的文本,如果有则将
Cut
和
Copy
的
Enabled
属性设为
True
;当前控制是
Editor
时,设置
Undo
和
Paste
属性,
Perfom
是构件向自身发送消息的方法。
Delphi
已经定义了一些标准的
Action
,这些
Action
实现的功能和
VCL
代码已经结合起来。所以,程序员可以直接使用,有些
Action
甚至不需要定义
onExecute
事件。如
Cut
,
Copy
,
Paste
等剪切板操作,
Cancel
,
Delete
,
Edit
,
First
,
Insert
,
Last
,
Next
,
Prior
,
Post
,
Refresh
等数据导航功能,
Arrange
,
Cascade
,
Close
,
MinimizeAll
,
TileHorizontal
等窗口排布功能。