正文

在DELPHI中实现控件的多样性编程2007-07-23 14:00:00

【评论】 【打印】 【字体: 】 本文链接:http://blog.pfan.cn/otot/27775.html

分享到:

用delphi也可以象C++一样,通过定义类,派生,重写函数等,制作出具控件有多样性的程序来,下面是一个文本编辑器的编程笔记。 定义一个接口类(祖先),只有定义而没有任何实际内容的类,所有实际的控件的类都从它那里派生,它不能用来产生具体的控件。例子:unit IddEditor;interface uses Controls,Graphics; type  Idd_Editor=classPublicFunction Save():boolean;Virtual;abstract;//纯虚函数,用于给继承者重写,并且没有任何内容Procedure Copy(); Virtual;abstract;Function CanCopy():boolean; Virtual;abstract;Procedure SelectAll(); Virtual;abstract;end; implementation end. 从接口类可以派生出具体一点的类了(父亲),(当然接口类也会派生出其他的类,这些类之间由于拥有共同的祖先,所以沟通成为可能)父亲把接口类的纯虚函数内容定义具体,同时也根据需要,生成一些新的虚函数,父亲把自己能做的都摆出来了,但是具体怎么做,留给儿子们去重写吧。例子:unit Editor; interface uses Controls,Graphics,Classes,IddEditor; type   TddEditor=Class(Idd_Editor)  Private    m_FileName:string;//多了一个成员变量,用来记录文件名字  Protected    Procedure OnEditorSelectionChange(Sender:Tobject);//这是这个类自己特有的函数    Function GetText():String;Virtual;abstract;//新增加的纯虚函数  Public    Constructor Create(ParentCtrl:TwinControl);//构造函数,是必须的    Destructor Destroy();   //解构函数,也是必须的    Procedure DoSaveToFile(FileName:String);Virtual;abstract;    Function Save():Boolean;Override;  //保存函数,不定义不行,定义得太死也不行,所以增加一个纯虚函数DoSaveToFile给后代重写,算是保留一点灵活性。  end; implementation uses GlobalObject; {TddEditor} Constructor TddEditor.Create(ParentCtrl:TwinControl);beginend; Destructor TddEditor.Destroy();beginend; Procedure TddEditor.OnEditorSelectionChange(Sender:Tobject);beging_EditorEvent.OnEditorSelectionChange(sender);end; Function TddEditor.Save():Boolean;//Override;beginif m_FileName ='' then  begin  Result:=SaveAs();  Exit;  end;DoSaveToFile(m_FileName);Result:=True;end; end. 好了,丑妇终需见家翁,最后派生定义一个具体化的类吧(儿子),这个类可是实际要变出实际控件来干活的,因此该定义就都得定义完,不能再偷懒了。例子:unit memoEditor; interface uses StdCtrls,Controls,Graphics,Classes,Dialogs,SysUtils,ExtCtrls,Math,Editor,IddEditor; type  TddmemoEditor=Class(TddEditor)Private  m_Edit:TMemo;//既然是TddmemoEditor,里面肯定是包含一个Memo了  Protected  Function GetText():String;Override; Public  Constructor Create(ParentCtrl:TwinControl);  Destructor Destroy();  Procedure DoSavetoFile(FileName:String);Override;  Function GetSelectionText():String;Override;  Procedure Copy(); Override;  Function CanCopy():boolean; Override;  Procedure SelectAll(); Override;  end; implementation uses GlobalObject; {TddmemoEditor} Function TddmemoEditor.GetText():String;//Override;beginend; Constructor TddmemoEditor.Create(ParentCtrl:TwinControl);beginm_Edit:=TMemo.Create(nil);//memo控件诞生了with m_Edit do  begin  Parent:=ParentCtrl;  WordWrap:=False;  Align:=AlClient;  ScrollBars:=ssBoth;  m_Edit.Font.Name:='宋体';  m_Edit.Font.Size:=12;  if CanFocus() then SetFocus();  end;end; Destructor TddmemoEditor.Destroy();//Override;begininherited;  //继承一下m_Edit.Free;  //memo控件完成历史使命了m_Edit:=nil;end; Procedure TddmemoEditor.DoSavetoFile(FileName:String);//Override;beginm_Edit.Lines.SaveToFile(FileName);//把实际功能都传交MEMO干了end; Function TddmemoEditor.GetSelectionText():String;//Override;beginResult:=m_Edit.SelText;end; Procedure TddmemoEditor.Copy(); //Override;beginm_Edit.CopyToClipboard;end; Function TddmemoEditor.CanCopy():boolean; //Override;beginResult:=m_Edit.SelLength<>0;end; Procedure TddmemoEditor.SelectAll(); //Override;             beginend; end. 要制作一个控件,还要派生两次,到底为什么不一下子就定义一个完整的类呢?就是为了所谓的多样性,例如突然间想改用其他文本容器做Editor,只需要定义一个TddmemoEditor的兄弟(儿子类),就可以了,爸爸和祖先都是不用动的,有些时候还很贪心的,想一会用TddmemoEditor,一会用它的兄弟,换来换去的,于是想到建一个制作控件的机器,程序依靠制作器,就可以制造出实际控件,不用自己建立。例子:unit EditorCtor; interface uses StdCtrls,Controls,Editor; typeTddEditorCtor=Class //Editor控件的制作工厂,可以制作很多种控件,但需要子孙自己定义。Protected  Function DoCreateAnEditor(Var Editor:TddEditor;ParentCtrl:Twincontrol):Integer;virtual;abstract;Public  Function CreateAnEditor(Var Editor:TddEditor;ParentCtrl:Twincontrol):integer;end; TddmemoEditorCtor=Class(TddEditorCtor) //派生一个MemoEditor控件的制作工厂,它就只能产生一种控件。Protected  Function DoCreateAnEditor(Var Editor:TddEditor;ParentCtrl:Twincontrol):Integer;OverRide;end; implementation uses memoEditor,  SettingMgr,  GlobalObject  ; {TddEditorCtor}Function TddEditorCtor.CreateAnEditor(Var Editor:TddEditor;ParentCtrl:Twincontrol):integer;beginResult:=DoCreateAnEditor(Editor,ParentCtrl);end; {TddMemoEditorCtor}Function TddmemoEditorCtor.DoCreateAnEditor(Var Editor:TddEditor;ParentCtrl:Twincontrol):Integer;beginEditor:=TddmemoEditor.Create(ParentCtrl);Result:=Integer(Editor<>nil);end; end. 程序中,需要产生控件实例时用以下命令: g_EditorCtor :TddEditorCtor=nil;//定义控件制作器,但是到底是那种制作器呢,这里还不明确。 m_Editor:TddEditor;//以父亲的名义定义一个控件,具体生成的是MemoEditor还是他的其他兄弟呢,看下面一句。 g_EditorCtor:=TddmemoEditorCtor.Create;//这里就明确了。只需要把TddmemoEditorCtor换成它的兄弟,就所有都跟着变化了,程序却还一样的照用,这里体现多样性的好处。 g_EditorCtor.CreateAnEditor(m_Editor,ParentCtrl);//由于g_EditorCtor实际是MemoEditorCtor,当然产生的控件是TddmemoEditor。 

阅读(3619) | 评论(0)


版权声明:编程爱好者网站为此博客服务提供商,如本文牵涉到版权问题,编程爱好者网站不承担相关责任,如有版权问题请直接与本文作者联系解决。谢谢!

评论

暂无评论
您需要登录后才能评论,请 登录 或者 注册