正文

在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=class
Public
Function 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);
begin
end;

Destructor TddEditor.Destroy();
begin
end;

Procedure TddEditor.OnEditorSelectionChange(Sender:Tobject);
begin
g_EditorEvent.OnEditorSelectionChange(sender);
end;

Function TddEditor.Save():Boolean;//Override;
begin
if 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;
begin
end;

Constructor TddmemoEditor.Create(ParentCtrl:TwinControl);
begin
m_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;
begin
inherited;  //继承一下
m_Edit.Free;  //memo控件完成历史使命了
m_Edit:=nil;
end;

Procedure TddmemoEditor.DoSavetoFile(FileName:String);//Override;
begin
m_Edit.Lines.SaveToFile(FileName);//把实际功能都传交MEMO干了
end;

Function TddmemoEditor.GetSelectionText():String;//Override;
begin
Result:=m_Edit.SelText;
end;

Procedure TddmemoEditor.Copy(); //Override;
begin
m_Edit.CopyToClipboard;
end;

Function TddmemoEditor.CanCopy():boolean; //Override;
begin
Result:=m_Edit.SelLength<>0;
end;

Procedure TddmemoEditor.SelectAll(); //Override;            
begin
end;

end.

要制作一个控件,还要派生两次,到底为什么不一下子就定义一个完整的类呢?就是为了所谓的多样性,例如突然间想改用其他文本容器做Editor,只需要定义一个TddmemoEditor的兄弟(儿子类),就可以了,爸爸和祖先都是不用动的,有些时候还很贪心的,想一会用TddmemoEditor,一会用它的兄弟,换来换去的,于是想到建一个制作控件的机器,程序依靠制作器,就可以制造出实际控件,不用自己建立。例子:
unit EditorCtor;

interface

uses StdCtrls,Controls,Editor;

type
TddEditorCtor=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;
begin
Result:=DoCreateAnEditor(Editor,ParentCtrl);
end;

{TddMemoEditorCtor}
Function TddmemoEditorCtor.DoCreateAnEditor(Var Editor:TddEditor;ParentCtrl:Twincontrol):Integer;
begin
Editor:=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。
 

阅读(3571) | 评论(0)


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

评论

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