[转]李战大师-悟透delphi 第十回 操作界面与操作逻辑

第十章          操作界面与操作逻辑

咱俩以面前的已经讨论过,用户界面及商逻辑分离的裨益。这样的离别可以为软件体系结构更加客观,结构易于理解,从而提高软件之油滑与可维护性。
刚巧使我出口到过,我们谈谈的目的是以追寻将软件结构从一无所知归于有序的实用方法,这是编写本书的显要目的之一。有序的物容易理解,易于掌握就是好控制,掌握后你拿会发现该背后的哲理是那么的简单,从而提高到重胜之境地去感受地道软件结构的调和美。
本章的话题将重点讨论哪边拿客户端的先后有序化,希望咱们的讨论对富有的软件同行和情侣都具备助。

第一节 分离操作界面与操作逻辑
如何设计自己的软件操作界面,是人机工程学研究之一个重中之重课题。好用底软件还来秀丽可爱之形容,不但布局均衡合理,对而的操作意图也是善解人意,并且处理大方得体,就连对您的报也体贴入微。如果,你编的软件象这样以根本字又的一无是处报告你的用户:“亲爱的,你以前就输入了数码吧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程序演示了TActionList和TAction的核心用法,很简短。如果您莫思浪费时间可一直跨越到末端的MULTIFACE程序,看看如何表演川剧的绝活儿-变脸。
公可于随书所倚的光盘中找到这程序的原代码。

文件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调出她底诗句。
休息一下,在咱们开始谈论运行时移软件界面的话题之前,先来感受以下诗人们的心情。诗人们的诗是漂亮之,但诗歌中富含的哲理才是他们心坎所追求的地步。编写程序也是这样。