我看了一下午的帮助也没弄清楚Taction是干什么的?
他什么时候触发Execute和Update
有什么经典的Tacion应用吗?

解决方案 »

  1.   

    第十六章   操作界面与操作逻辑 我们在前面的第八章曾经讨论过 ,用户界面与商业逻辑分离的好处。这样的分离可以让软件体系结构更加合理 ,结构易于理解 ,从而增强软件的灵活性和可维护性。   正如我谈到过 ,我们讨论的目的是为了寻找将软件结构从混沌归于有序的实用方法 ,这是编写本书的主要目的之一。有序的东西易于理解 ,易于理解就便于掌握 ,掌握之后你将会发现其背后的哲理是那样的简单 ,从而升华到更高的境界去感受良好软件结构的协调美。   本章的话题将重点讨论如何将客户端的程序有序化 ,希望我们的讨论对所有的软件同行和朋友都有所帮助。   第一节   分离操作界面与操作逻辑   怎样设计友好的软件操作界面 ,是人机工程学研究的一个重要课题。好用的软件都有清秀可爱的面容 ,不但布局匀称合理 ,对你的操作意图也是善解人意 ,并且处理大方得体 ,就连对你的回答也体贴入微。如果 ,你编写的软件象这样将关键字重复的错误告诉你的用户 :" 亲爱的 ,你以前已经输入了编号为 991028 的出库单 ,不可重复输入。是否想查看以前的出库单呢? ",你的软件一定会销量大增。可能当年 IBM 的 OS2 就是因为说了很多用户看不懂的废话 ,才被用户遗弃 ,失去民心 ,而被 Bill Gates 一统天下。   我们今天不打算讨论怎样打扮软件的容颜 ,而要谈谈在漂亮的界面后面 ,应该如何更好地组织软件结构 ,大大方方地处理用户的操作命令。   假如 ,你已经规划好软件初步的操作模式 ,用带图标的菜单作为用户发号司令的工具 ,并在 MenuItem 的 OnClick 事件中编写完成业务处理的过程语句。一切都不错 ,而商业的逻辑处理也是放到服务器端的 RemoteDataMoudle 中处理的 ,经典的三层体系结构。可是你的老板不喜欢菜单 ,他对按钮情有独钟 ,于是你需要将 Menu 换成 Button,然后将操作实现代码移到 Button 的 OnClick 事件过程中 ,或者将 Button 的 OnClick 事件指向原来的 MenuItemClick 事件处理过程。软件提交用户试用之后 ,用户强烈要求将软件修改为 Microsoft Word 2000 那样的界面 ,既有菜单又有按钮 ,而且还能提供键盘的快捷键输入 ( 因为他们的老总习惯了原来 DOS 下那套老程序的键盘输入方式 ) 。于是 ,你又不得不修改软件的界面控件 ,并再次将操作处理代码调整 ,以便每种命令输入方式都能被响应。最后 ,历经千辛万苦终于能完成整个软件界面的修改工作。   由此可见 ,不同的人有不同的爱好和需求 ,他们各自都有操作软件的习惯。但是他们使用软件的目的是相同的 ,就是 ,向你的软件发出指定的操作指令 ,使用该操作所代表的软件功能!   在种种不同的用户的需求之中 ,搞清所有用户的最终目的之后 ,我们应该仔细地想一想 ,不同的用户为了达到相同目的 ,使用了不同的手段。哦!原来目的和手段是两回事 ,只不过每个人用不同的手段达到相同的目的。   因此 ,我们应该将操作界面与操作逻辑分离 ,应该首先分清手段和目的 ,然后将手段与目的联系起来。这样 ,操作界面的更改将不会影响到操作逻辑 ,手段是手段 ,目的是目的。为了达到目的 ,可以不择手段 ,就是这个道理!   说道这里 ,也许有人会说 : 这个道理谁都懂。那么 ,如果在我们开发软件的过程中 ,多运用这些浅显的道理 ,就不难设计出简单而又实用的软件结构。   操作界面与操作逻辑的分离可以为我们带来哪些好处呢?  1 .   易于理解   你可以在编写业务操作代码时 ,不关心软件的界面操作模式 ,而在美化你的软件时 ,只考虑界面的美学问题。外表是外表 ,内心是内心 ,只有你知道 ,外表美观的界面连接着精巧内秀的操作代码 ,表里如一。你的朋友们既可欣赏到漂亮的软件外表 ,也容易读懂你的内心。  2 .   易于维护   不管将来流行什么软件界面 ,是时新 HomePage 式样还是 OutLook 的经典面版。你可以只修改与界面有关的部分 ,就可满足要求。也可将你的软件彻底改头换面 ,以崭新的面容出现。甚至 ,可表演川剧名家传内不传外传男不传女的独门绝技 - 变脸。但软件还是软件 ,软件的内在功能逻辑并未改变。不过 ,由于满足了用户喜新厌旧 ,追逐流行时尚的习惯 ,将使软件公司的老板们的腰包越来越鼓。  3 .   可扩充性强   人机工程学不断取得的新突破 ,将为软件使用者提供更多的命令输入方式。现在 ,语音识别技术已逐渐商用化。你已经可以利用 IBM ViaVoice 提供的语音识别支持模块 ,开发能识别语音命令的控件。将这样的控件加入你的软件中 ,并与你以前编写的操作逻辑关联 ,你的软件就象长了耳朵 ,有了灵气 ,可以倾听你的述说。我也相信 ,总有一天可编写一种可以看懂你的表情的控件 ,那么 ,软件将可以根据你的情绪对你抚以不同冷暖的关怀。但软件的灵魂还是原来的操作逻辑代码!  4 .   适合大规模软件开发   大规模软件开发讲求分工协作 ,各尽其才。如果你是软件公司的老板 ,那么 ,在系统分析设计人员完成软件设计之后 ,你可以找一批时装设计师为你的软件设计漂亮性感的界面 ,请精于编码的程序员编写操作逻辑。而你可以轻松地管理和控制各道工序的质量 ,而且责任分明。   尽管天涯海角的吹了一通 ,但我们还得回到我们主题。操作界面与操作逻辑的分离 ,到底要遵循哪些方法和原则呢?   首先 ,你应当归纳整理当前模块要向用户提供的功能 ,划分出明确的操作命令集。也就是说 ,设计可提供给用户的命令 ,这有点象老式命令行程序的可用命令清单列表。记住 ,这些命令集体现的是用户执行操作的目的。   然后 ,在根据命令集中的每一命令规划操作逻辑代码 ,按照编写程序的一般原则编制操作逻辑代码。有关编写程序的一般原则 ,可参阅《初恋 DELPHI 》一书。   最后 ,要提醒一点的就是 ,操作命令有时是受程序状态控制的。有的程序员为了实现在某中状态下禁止用户发出指定的操作命令 ,想尽办法控制菜单、按钮等命令控件的属性 ,封杀和打压所有可执行命令的控件。但是 ,你想禁止的是命令 ,而不是控件!   下面我们将会讨论在分离操作界面和操作逻辑方面 ,DELPHI 为我们提供的很有价值的东西 ,即 TActionList 和 TAction 。   第二节   使用 TActionList 和 TAction "Action" 一词的含义是行为、行动或动作 ,TAction 就是抽象了用户想要通过软件界面表现的行为、开展的行动或执行的动作 ,而 TActionList 就描述了动作的命令清单。你可以将一个 TActionList 元件加入到你的 Form 、 Frame 或 DataModule 中 ,双击此元件可定义需要的 TAction 对象。   缔造 DELPHI 大厦的设计师和工程师们 ,为绝大多数命令控件 ( 如 TButton,TMenuItem 等等 ) 设计了 Action 属性 ,并且常常碰巧出现在 Object Inspecter 窗口属性页面的第一项上 ,由此可见他们的用心良苦。但不管怎样 ,他们为我们提供了一个简单的方法 ,将命令控件的 Action 属性与 TActionList 元件中定义的 TAction 对象关联。   由于 ,在 TAction 对象的 OnExecute 事件中编写的操作逻辑代码可自动被关联的命令控件调用 ,因此 ,更换命令控件的类型 ,不用修改或调整操作逻辑代码。这样就可将操作界面与操作逻辑分开。   如果在某些状态下你要禁止用户执行某种操作 ,可设置相关 TAction 对象的 Enabled 属性为 FALSE,则相关的命令控件将通通被冷冻 ,该变白脸的变脸白 ,该变灰脸的变灰脸 ,而不管他是生旦净末丑。   再次感谢缔造 DELPHI 的大师们 ,是他们在台后为我们做了一切 ,而且还将他们的九阴真经放到 Source\VCL\ActnList.pas 单元中。   既然有大师们的九阴真经 ,我们就应该拿来修炼 ,增强我们的内功。   首先 ,在 ActnList 单元中 ,TActionList 是这样声明的 : TActionList = class(TCustomActionList) published property Images; property OnChange; property OnExecute; property OnUpdate; end; TActionList 只发表了 TCustomActionList 的一些属性和事件。其实 ,TActionList 就是用来装 TAction 的容器 ,并提供了管理 TAction 的方法。有关 TActionList 的详细用法 ,我们将在随后开发的 TActionManager 控件中讨论。   再来看看 TAction 的声明的 : TAction = class(TCustomAction) published property Caption; property Checked; property Enabled; property HelpContext; property Hint; property ImageIndex; property ShortCut; property Visible; property OnExecute; property OnHint; property OnUpdate; end; TAction 是从 TCustomAction 类继承的 ,与前面一样 ,只不过将父类的一些特征发表。我不想逐一解读 TAction 的各个类层次的原代码 ,相信读过《初恋 DELPHI 》一书的朋友都能够解读这些代码。我只想讨论 TAction 发表给我们的这些特性 ,能为我们提供什么功能。由于还有一些特性是在 TAction 的父辈类中发表的 ,在讨论时也将一起谈到 ,不过一些不重要的特性就不再废话了。  Caption 属性 : 填写此属性 ,你可以用简短的标题向用户说明命令操作的含义。此属性将自动更新相关命令控件的 Caption 属性 ,所以按钮和菜单的 Caption 属性要在此输入。  Category 属性 : 操作命令的类别 ,主要是为了方便你分类管理你的操作命令集。此属性是在 TAction 的爷爷辈 TContainedAction 中发表的 ,在我们随后开发的 TActionManager 控件中 ,你将看到如何此属性管理操作命令。  Enabled 属性 : 控制命令操作是否可执行 ,可自动控制关联命令控件是否允许执行。封杀命令控件应该从这里下手。  ImageIndex 属性 : 表示操作命令的图标索引 ,与 TActionList 的 Images 联系。有图标的命令控件可以享受到他的恩惠。  ShortCut 属性 : 用键盘发出操作命令的快捷键 ,为喜好键盘操作的人们带来的福音。  Visible 属性 : 控制 Enabled 可以让命令控件变灰 ,控制此属性可以让命令控件消失在用户面前。注意 ,虽然命令控件消失 ,但用户仍可通过快捷键发出操作命令 ,而 Enabled 才可真正封杀命令。  OnExecute 事件 : 可以在此事件中编写操作逻辑代码 ,用户触发相关的命令控件时 ,将自动调用此事件的操作逻辑代码。   其他的特性就自己查看 DELPHI 的联机帮助吧!   初步了解 TActionList 和 TAction 之后 ,我们将开始实践。下面的 PRETTYPOEM 程序演示了 T
      

  2.   

    文件 PRETTYPOEM.DPR program PRETTYPOEM; uses Forms, Main in 'Main.pas' {fMain}; {$R *.RES} begin Application.Initialize; Application.CreateForm(TfMain, fMain); Application.Run; end.  文件 Main.pas unit Main; interface uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, Menus, ActnList, ComCtrls, ToolWin, StdCtrls, ImgList; type TfMain = class(TForm) MainMenu: TMainMenu; ActionList: TActionList; actGuCheng: TAction; actXiMuRong: TAction; actLiQingZhao: TAction; actSuShi: TAction; N1: TMenuItem; N2: TMenuItem; N3: TMenuItem; N4: TMenuItem; N5: TMenuItem; N6: TMenuItem; ToolBar1: TToolBar; ToolButton1: TToolButton; ToolButton2: TToolButton; ToolButton3: TToolButton; ToolButton4: TToolButton; Button1: TButton; Button2: TButton; Button3: TButton; Button4: TButton; cbDisableLiQingZhao: TCheckBox; actDisableLiQingZhao: TAction; actHideLiQingZhao: TAction; cbHideLiQingZhao: TCheckBox; ImageList: TImageList; labPoem: TLabel; labShadow: TLabel; procedure actGuChengExecute(Sender: TObject); procedure actXiMuRongExecute(Sender: TObject); procedure actDisableLiQingZhaoExecute(Sender: TObject); procedure actHideLiQingZhaoExecute(Sender: TObject); procedure actSuShiExecute(Sender: TObject); procedure actLiQingZhaoExecute(Sender: TObject); private { Private declarations } procedure RecitePoem(Poem:string); public { Public declarations } end; var fMain: TfMain; implementation {$R *.DFM} procedure TfMain.RecitePoem(Poem: string); begin labPoem.Caption:=Poem; labShadow.Caption:=Poem; end; procedure TfMain.actGuChengExecute(Sender: TObject); begin RecitePoem(' 黑夜给我黑色的眼睛   我却用她寻找光明 '); end; procedure TfMain.actXiMuRongExecute(Sender: TObject); begin RecitePoem(' 溪水急着要流向大海   而浪潮却渴望重归土地 '); end; procedure TfMain.actSuShiExecute(Sender: TObject); begin RecitePoem(' 人有悲欢离合   月有阴晴圆缺 '); end; procedure TfMain.actLiQingZhaoExecute(Sender: TObject); begin RecitePoem(' 生当做人杰   死亦为鬼雄 '); end; procedure TfMain.actDisableLiQingZhaoExecute(Sender: TObject); begin actLiQingZhao.Enabled:=not cbDisableLiQingZhao.Checked; end; procedure TfMain.actHideLiQingZhaoExecute(Sender: TObject); begin actLiQingZhao.Visible:=not cbHideLiQingZhao.Checked; end; end.  文件 Main.dfm object fMain: TfMain Left = 192 Top = 107 Width = 442 Height = 195 BorderIcons = [biSystemMenu, biMinimize] Caption = ' 谈古论今 ' Color = clBtnFace Font.Charset = GB2312_CHARSET Font.Color = clWindowText Font.Height = -12 Font.Name = ' 宋体 ' Font.Style = [] Menu = MainMenu OldCreateOrder = False PixelsPerInch = 96 TextHeight = 12 object labShadow: TLabel Left = 17 Top = 41 Width = 380 Height = 20 Caption = ' 古今诗词名句欣赏 ,请选择你喜爱的诗人。 ' Font.Charset = GB2312_CHARSET Font.Color = clBlack Font.Height = -20 Font.Name = ' 隶书 ' Font.Style = [] ParentFont = False Transparent = True end object labPoem: TLabel Left = 16 Top = 40 Width = 380 Height = 20 Caption = ' 古今诗词名句欣赏 ,请选择你喜爱的诗人。 ' Font.Charset = GB2312_CHARSET Font.Color = clBlue Font.Height = -20 Font.Name = ' 隶书 ' Font.Style = [] ParentFont = False Transparent = True end object ToolBar1: TToolBar Left = 0 Top = 0 Width = 434 Height = 26 AutoSize = True ButtonWidth = 63 Caption = 'ToolBar' EdgeBorders = [ebTop, ebBottom] Flat = True Images = ImageList List = True ShowCaptions = True TabOrder = 0 object ToolButton1: TToolButton Left = 0 Top = 0 Action = actGuCheng end object ToolButton2: TToolButton Left = 63 Top = 0 Action = actXiMuRong end object ToolButton3: TToolButton Left = 126 Top = 0 Action = actSuShi end object ToolButton4: TToolButton Left = 189 Top = 0 Action = actLiQingZhao end end object Button1: TButton Left = 12 Top = 80 Width = 75 Height = 25 Action = actGuCheng TabOrder = 1 end object Button2: TButton Left = 116 Top = 80 Width = 75 Height = 25 Action = actXiMuRong TabOrder = 2 end object Button3: TButton Left = 12 Top = 112 Width = 75 Height = 25 Action = actSuShi TabOrder = 3 end object Button4: TButton Left = 116 Top = 112 Width = 75 Height = 25 Action = actLiQingZhao TabOrder = 4 end object cbDisableLiQingZhao: TCheckBox Left = 232 Top = 116 Width = 81 Height = 17 Action = actDisableLiQingZhao TabOrder = 5 end object cbHideLiQingZhao: TCheckBox Left = 328 Top = 116 Width = 81 Height = 17 Action = actHideLiQingZhao TabOrder = 6 end object MainMenu: TMainMenu Images = ImageList Left = 332 Top = 4 object N1: TMenuItem Caption = ' 现代情怀 ' object N2: TMenuItem Action = actGuCheng end object N3: TMenuItem Action = actXiMuRong end end object N4: TMenuItem Caption = ' 古典风范 ' object N5: TMenuItem Action = actSuShi end object N6: TMenuItem Action = actLiQingZhao end end end object ActionList: TActionList Images = ImageList Left = 360 Top = 4 object actGuCheng: TAction Category = ' 现代情怀 ' Caption = ' 顾城 ' ImageIndex = 0 ShortCut = 16455 OnExecute = actGuChengExecute end object actXiMuRong: TAction Category = ' 现代情怀 ' Caption = ' 席慕容 ' ImageIndex = 1 ShortCut = 16472 OnExecute = actXiMuRongExecute end object actSuShi: TAction Category = ' 古典风范 ' Caption = ' 苏轼 ' ImageIndex = 2 ShortCut = 16467 OnExecute = actSuShiExecute end object actLiQingZhao: TAction Category = ' 古典风范 ' Caption = ' 李清照 ' ImageIndex = 3 ShortCut = 16460 OnExecute = actLiQingZhaoExecute end object actDisableLiQingZhao: TAction Category = ' 控制 ' Caption = ' 禁止李清照 ' OnExecute = actDisableLiQingZhaoExecute end object actHideLiQingZhao: TAction Category = ' 控制 ' Caption = ' 隐藏李清照 ' OnExecute = actHideLiQingZhaoExecute end end object ImageList: TImageList Left = 388 Top = 4 end end  此程序运行之后 ,你可以通过菜单、工具条、按钮和快捷键调出你喜欢的诗句。 Action 的标题和图标都自动反映在菜单、工具条和按钮上 ,细心的朋友会发现 ,菜单上还同时将我们定义的快捷键显示出来 ,可见 VCL 的开发者所做的工作比我们想象的还要多。至于菜单名后的热键字符 ,是由 MainMenu 的 AutoHotKeys 属性引起的。   你可以用选择框禁止或隐藏李清照的名字 ,不过只隐藏李清照的名字时 ,仍然可通过 Ctrl+L 调出她的诗句。   休息一下 ,在我们开始讨论运行时更改软件界面的话题之前 ,感受以下诗人们的情怀。诗人们的诗句是美丽的 ,但诗句中隐含的哲理才是他们内心所追求的境界。编写程序也是如此。   此程序运行之后 ,你可以通过菜单、工具条、按钮和快捷键调出你喜欢的诗句。 Action 的标题和图标都自动反映在菜单、工具条和按钮上 ,细心的朋友会发现 ,菜单上还同时将我们定义的快捷键显示出来 ,可见 VCL 的开发者所做的工作比我们想象的还要多。至于菜单名后的热键字符 ,是由 MainMenu 的 AutoHotKeys 属性引起的。   你可以用选择框禁止或隐藏李清照的名字 ,不过只隐藏李清照的名字时 ,仍然可通过 Ctrl+L 调出她的诗句。   休息一下 ,在我们开始讨论运行时更改软件界面的话题之前 ,感受以下诗人们的情怀。诗人们的诗句是美丽的 ,但诗句中隐含的哲理才是他们内心所追求的境界。编写程序也是如此。
      

  3.   

    happyzsl(学习) 
    谢谢,写得很好。
    不过我不太清楚的是dephi开发的程序太大了,比VC的大很多,不只为什么?
      

  4.   

    你写的vc程序一般是选动态链接的,而delphi是静态的