高手啊!请问tcontrol和twincontrol做parent到底有什么不同呢?(100分)

  • 主题发起人 主题发起人 dreamer567
  • 开始时间 开始时间
D

dreamer567

Unregistered / Unconfirmed
GUEST, unregistred user!
现在有这样一个类:
unit MustItem7Class;
interface
uses Windows, SysUtils, Classes, Messages, Controls, ExtCtrls, Graphics;
type
TMustItemPainter = class
private
FCtrl: TControl;
FImage: TImage;
FMustItem: Boolean;
FVisible: Boolean;
procedure SetMustImage(const Value: Boolean);
procedure SetMustItem(const Value: Boolean);
procedure SetVisible(const Value: Boolean);
public
constructor Create(Ctrl: TControl);
destructor Destroy; override;
procedure Repaint;
property MustItem: Boolean read FMustItem write SetMustItem;
property Visible: Boolean read FVisible write SetVisible;
end;
implementation
{$R ImgMustItem.res}
constructor TMustItemPainter.Create(Ctrl: TControl);
begin
FCtrl := Ctrl;
end;
destructor TMustItemPainter.Destroy;
begin
SetMustImage(False);
inherited;
end;
procedure TMustItemPainter.Repaint;
begin
if not Assigned(FImage) then Exit;
FImage.Visible := FVisible;
FImage.Left := FCtrl.Left + FCtrl.Width + 2;
FImage.Top := FCtrl.Top + (FCtrl.Height - FImage.Height) div 2;
end;
procedure TMustItemPainter.SetMustImage(const Value: Boolean);
begin
if Value then
begin
if not Assigned(FImage) then
begin
FImage := TImage.Create(FCtrl);
FImage.Parent := FCtrl.Parent;
FImage.Picture.Bitmap := TBitmap.Create;
FImage.Picture.Bitmap.LoadFromResourceName(HInstance, 'ImgMustItem');
//FImage.Picture.Bitmap.LoadFromFile('../MustItem.bmp');
FImage.AutoSize := True;
end;
Repaint;
end
else begin
FImage.Free;
FImage := nil;
end;
end;
procedure TMustItemPainter.SetMustItem(const Value: Boolean);
begin
FMustItem := Value;
SetMustImage(FMustItem);
end;
procedure TMustItemPainter.SetVisible(const Value: Boolean);
begin
FVisible := Value;
Repaint;
end;
end.
然后我想写一个继承tlabel的控件ttestlabel,加个mustitem属性,如果为真,就画出mustitem.res的图形。关键现在问题出现了,就是在ttestlabel的free的时候,fimagepainter.free出问题,然后发现是TMustItemPainter.fimage.free时出问题。好像是因为tcontrol接收不到焦点的关系。因为以前这个类放在tedit里面是好的,也就是fctrl是twincontrol型的。但是tlabel继承的是tcontrol类,我只好把fctrl改为tcontrol。可是free的问题怎么办?
ttestlabel的代码如下:
TWA7Label = class(TLabel)
private
{ Private 宣言 }
FMustItem: Boolean;
FMustItemImage: TMustItemPainter;
procedure SetMustItem(Value : Boolean);
function GetVisible: Boolean;
procedure SetVisible(value: Boolean);
protected
procedure loaded; override;
public
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
procedure SetBounds(ALeft, ATop, AWidth, AHeight: Integer); override;
published
property MustItem : boolean read FMustItem write SetMustItem;
property Visible : boolean read GetVisible write SetVisible;
end;

procedure Register;

implementation

uses StrUtils, Math;

procedure Register;
begin
RegisterComponents('Company', [TWA7Label]);
end;

{ TWA7Label }

constructor TWA7Label.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
FMustItemImage := TMustItemPainter.Create(Self);
FMustItemImage.Visible := Self.Visible;
end;
destructor TWA7Label.Destroy;
begin
FMustItemImage.Free;
inherited;
end;
procedure TWA7Label.SetMustItem(Value: Boolean);
begin
FMustItem := value;
FMustItemImage.MustItem := Value;
end;
procedure TWA7Label.SetVisible(Value: boolean);
begin
inherited Visible := Value;
FMustItemImage.Visible := Visible;
end;
function TWA7Label.GetVisible: Boolean;
begin
Result := inherited Visible;
end;
procedure TWA7Label.SetBounds(ALeft, ATop, AWidth, AHeight: Integer);
begin
inherited;
if Assigned(FMustItemImage) then FMustItemImage.Repaint;
end;
end.
高手啊,帮忙啊。
 
你的代码挺长的,我没仔细研究。但我建议你的类不要这样定义
TMustItemPainter = class
否则构建和析构可能都会遇到问题。

最好从delphi的类开始继承,这样很多最底层的构建和析构系统帮你处理了。至少应该从TObject开始吧。或其它的。
例:TMustItemPainter = class(TObject)
 
没用的,因为class这样定义的话,delphi会默认的认为你是继承了tobject类的。
我又这样改写:
type
TMustItemPainter = class(TComponent)
private
FCtrl: TWinControl;
FImage: TImage;
FMustItem: Boolean;
FVisible: Boolean;
procedure SetMustImage(const Value: Boolean);
procedure SetMustItem(const Value: Boolean);
procedure SetVisible(const Value: Boolean);
public
constructor Create(Ctrl: TComponent); override;
destructor Destroy; override;
procedure Repaint;
property MustItem: Boolean read FMustItem write SetMustItem;
property Visible: Boolean read FVisible write SetVisible;
end;
implementation
{$R ImgMustItem.res}
constructor TMustItemPainter.Create(Ctrl: TComponent);
begin
inherited;
FCtrl := TWinControl(Ctrl);
end;
事实证明不行。
 
FImage := TImage.Create(FCtrl);

说明FCtrl一定是要TWinControl, 而TtestLabel不是从TWinControl继承下来的
将 FCtrl: TControl; 改为 FCtrl: TWinControl; 也没有用, 因为
TImage.Create的参数一定是TWincontrol


 
jackchin, 你说得简直太对了。
可是为什么?help上面写timage create的参数只是tcomponent的程度而已呀。
还有,有什么办法能解决呢?
难道说tlabel就一定不行了吗?
 
TImage.Create的参数一定是TWincontrol? 什么意思?

Timage的 parent 一定是Twincontrol, 不能为TGraphicControl,你的代码能通过,但Tlabel没有处理消息的能力,它的消息交给它的parent处理。将Timage的parent set 为Tlabel,行不通的。

我建议你不用TImage, 就直接paint bitmap
 
怎么样直接画bitmap呢?
我舍弃了这个mustitemclass,在ttestlabel里面声明了一个tbitmap,但是无论如何它也显示不出来,痛苦,郁闷……
TWA7Label = class(TLabel)
private
{ Private 宣言 }
FMustItem: Boolean;
FMustItemBmp: TBitmap;
procedure SetMustItem(Value : Boolean);
function GetVisible: Boolean;
procedure SetVisible(value: Boolean);
procedure Repaint; override;
protected
procedure loaded; override;
public
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
procedure SetBounds(ALeft, ATop, AWidth, AHeight: Integer); override;
published
property MustItem : boolean read FMustItem write SetMustItem;
property Visible : boolean read GetVisible write SetVisible;
end;

procedure Register;

implementation

uses StrUtils, Math;

procedure Register;
begin
RegisterComponents('Company', [TWA7Label]);
end;

{ TWA7Label }

constructor TWA7Label.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
FMustItemBmp := TBitmap.Create;
end;
destructor TWA7Label.Destroy;
begin
FMustItemBmp.Free;
inherited;
end;
procedure TWA7Label.SetMustItem(Value: Boolean);
begin
FMustItem := value;
if FMustItem then
begin
if not Assigned(FMustItemBmp) then
FMustItemBmp := TBitmap.Create;
FMustItemBmp.LoadFromResourceName(Hinstance, 'ImgMustItem');
end
else
begin
FMustItemBmp.Free;
FMustItemBmp := nil;
end;
Self.Repaint;
end;
procedure TWA7Label.SetVisible(Value: boolean);
begin
inherited Visible := Value;
end;
function TWA7Label.GetVisible: Boolean;
begin
Result := inherited Visible;
end;
procedure TWA7Label.SetBounds(ALeft, ATop, AWidth, AHeight: Integer);
begin
inherited;
if Assigned(FMustItemBmp) then
begin
Inc(AWidth, FMustItemBmp.Width + 2);
Inc(AHeight, FMustItemBmp.Height);
end;
end;
procedure TWA7Label.Repaint;
var
DC: HDC;
begin
inherited;
if Visible and Assigned(FMustItemBmp) then
begin
Canvas.Draw(Left + Width + 2, Top + (Height - FMustItemBmp.Height) div 2, FMustItemBmp);
end;
end;
end.
 
为什么tlabel上面不能画图片啊?
 
tlabel没有画布Canvas。
画图的组件必须要有画布(Canvas)。它最早的基类好像是TGraphicControl
 
楼上,tlabel有canvas的,也能画图片,刚刚我没有定义bitmap的长宽。
但是form上直接画的时候,不需要定义长宽的。
 
不好意思,我想当然了,再看看
 
Canvas.Draw(Left + Width + 2, Top + (Height - FMustItemBmp.Height) div 2, FMustItemBmp);
结果是这句话出错,大汗。left 和top去掉就好了。
不管,要结贴了。
 
多人接受答案了。
 
后退
顶部