类的设计方案(TCustomControl ,TGraphicControl) ( 积分: 300 )

  • 主题发起人 主题发起人 xuxiaohan
  • 开始时间 开始时间
X

xuxiaohan

Unregistered / Unconfirmed
GUEST, unregistred user!
我有两个类
TxButton =class(TGraphicControl)
protectd
procedure paint; override;
end;

TyButton = class(TCustomControl)
protectd
procedure paint; oveeride;
end

因为这两个类实现的功能基本相同, 有很多相同是属性,paint 的代码也很多很多而且实现相同的功能,
我想简化, 有没有办法简化为: 一个基类, 加 两个比较小的类, 其中大部分代码写到基本类里面;重要的是包括 piant 的代码;
 
我有两个类
TxButton =class(TGraphicControl)
protectd
procedure paint; override;
end;

TyButton = class(TCustomControl)
protectd
procedure paint; oveeride;
end

因为这两个类实现的功能基本相同, 有很多相同是属性,paint 的代码也很多很多而且实现相同的功能,
我想简化, 有没有办法简化为: 一个基类, 加 两个比较小的类, 其中大部分代码写到基本类里面;重要的是包括 piant 的代码;
 
从TGraphic,TCustomControl的公共基类出发建立你的自己的公共基类。
然后分别按TGraphic与TCustomControl实现的方式,分别实现你的子类。
 
TCustomControl, TGraphicControl都是从TControl继承下来的。
TGraphicControl都直接从TControl继承下来的, 而TCustomControl是通过TWinControl从TControl继承下来的。
所以你可以从TControl继承来创建控件,加上你所需要的属性和方法。
 
看了楼主的内文,我不知道该用哪个角度来向您解释这个问题。我尽量解说得浅一些,
希望您能够得到一些东西。

首先您不能笔误到这种程度:TGraphic ? TGraphicControl ?
TGraphic 是一个操作某种二进制数据,以便让它在 TCanvas 中显示出来的一个类,其中
包括对这个二进制数据的一些操作。TGraphicControl 却不是。这是一。

第二,VCL 体系在 TControl 后就分枝了,分别走向 TGraphicControl 类和 TWinControl
类,这个非常重要。假如您的二个控件,一个走 TWinControl 类、一个走 TGraphicControl
类,最好的建议是您不要把它们放到同一个基类下,否则您的基类就没有了方向,也就意味
着您会重复您的基类的基类的很多已经实现的功能,直至您几乎完全重写它们。

第三,一个明显的基类,应该有很明确的目标,假如我们只是对该类的行为进行规范,我们
也可以通过接口来进行,假如我们要对外观进行规范,那就套上一层很薄的一个层次去调整
基类的基类的一些性能,这样没有什么不妥,但我们尽量不要跨越不同的分枝,以使基类变
得徒有形式。

因此,您问题中的二个控件,不提倡您把它们揉合到一个基类下。
 
“小雨哥”真是高明!!佩服!!
 
我觉得也不是不可以。不要用继承的方法。

可以声明一个TBUTTON类,把大多数操作都写进去,然后在分别用组合方式(或聚合方式——区别我忘了)和TCustomControl, TGraphicControl出带窗口句柄和不带窗口句柄的两个按钮。

就是这样的代码:
TXXXButton=class(TPersistent)
procedure paint;
end;

TxButton =class(TGraphicControl)
private
FButton:TXXXButton;
protectd
procedure paint; override;
end;

TyButton = class(TCustomControl)
private
FButton:TXXXButton;
protectd
procedure paint; oveeride;
end
 
非常惭愧, 匆匆忙忙写错了 TGraphicControl;
几乎完全一样的代码,但要做一个Copy, 仅仅是继承 的 基类不同而已; 一个是继承于TGraphicControl, 这个可以用做ToolBar的Button, 节约资源; 另一个继承于TCustomControl, 目的是有handle,可以得到焦点,做普通的按钮;

其实是可以实现的, 改写TControl的代码,
TControl = class(TComponent)
private
...
FCanvas: TCanvas;
protected
...
procedure InternalPaint; virtual;
public
...
property btCanvas: TCanvas read FCanvas;
end;
TxButton =class(TGraphic)
protectd
procedure paint; override;
end;

TyButton = class(TCustomControl)
protectd
procedure paint; oveeride;
end

...
procedure TControl.internatPaint;
begin
with FCanvas do
begin
....
end;
end;

procedure TxButton.paint;
begin
InternalPaint;
end;
...

是由于代码比较多, 我才产生懒惰的思想, 上面的方法我不会采用;有没有其他的方法?
 
procedure paint; override;
begin
FButton.Paint;
end;

这样就可以了么!
 
wk_knife:
你的方法我也考虑过, 这样只能将部分代码简化,例如属性, 一些过程, 但是另外一些消息, 还有 MouseMove, keyDown 等等就不好放到 TXXXButton 中;
TXXXButton=class(TPersistent)
procedure paint;
end;

TxButton =class(TGraphicControl)
private
FButton:TXXXButton;
procedure CmMouseEnter(var msg: Tmessage); message CM_MOUSEENTER;
procedure CmMouseLeave(var msg: Tmessage); message CM_MOUSELEAVE;
procedure CMDesignHitTest( var Msg: TCMDesignHitTest ); message cm_DesignHitTest;

protectd
procedure paint; override;
end;

TyButton = class(TCustomControl)
private
FButton:TXXXButton;
protectd
procedure paint; override;
end
 
怎么会不能放呢?
procedure CmMouseEnter(var msg: Tmessage); message CM_MOUSEENTER;
begin
inherited;//或不继承处理
FButton.MouseEnter(msg);
end;

即使不使用这样的方法,在VCL中任何一个对象都可以处理消息的啊,看看关于DISPATCH方法的说明吧
 
我的意思是将这些代码放到 TXXXButton 中,不好放。
procedure TxButton.CmMouseEnter(var msg: Tmessage);
begin
inherited;//或不继承处理
FButton.MouseEnter(msg);
end;
这样还不是要在 TxButton 和 TyButton, 代码还是多哦,而且TxButton 和 TyButton 是相同的。
 
先说一点,从TControl开始分家,派生出TWinControl和TGraphicControl,
TGraphicControl有Paint方法,但TWinControl没有,TCustomControl派生自TWinControl
有Paint方法,但这个Paint是重写的,和TGraphicControl里的不是一个东西。
而你要是改他们的祖宗TControl的话可能会影响其他派生类,TControl的后代多了去了
大概你可以复制一份在自己目录里
所以唯一办法就是聚合了就像wk_knife说的一样
要是嫌这个内部对象太大的话就直接从TObject派生
TInnerButton = class
public
procedure Paint;
procedure CmMouseEnter(var msg: Tmessage);
end;
把每个接口都缝合吧,处理的消息多的话确实挺累的
 
那就是没有办法偷懒咯。。。
 
多人接受答案了。
 
后退
顶部