问题描述
我为 TStatusbar 创建了一个自定义控件。 它在用于 Windows 的旧 Delphi5 中。 目标是,如果我单击面板或图像,则应引发事件。 但是我通过将点击事件分配给图像来得到一个错误。 错误是从 _Image.OnClick := ButtonClick; 任何人都可以解决这个问题吗?谢谢!
我修改了代码,现在可以使用了。 有什么建议可以让它变得更好吗? 我的主要错误是我误解了
self := TPanelImageButton(template);
我读到,在这种情况下,self 应该从模板继承所有内容。 但我想这是错误的。所以我现在在代码中设置我需要的属性。
谢谢!
unit PanelImageButton;
{
Usage:
var
PanelUser: TPanelImageButton;
PanelUser :=TPanelImageButton.Create(self,PanelUserTemplate,Image1);
PanelUser.OnClick:= PanelUserClicked;
procedure TForm1.PanelUserClicked(Sender:TObject);
begin
end;
FormClose() -> FreeAndNil(PanelUser);
}
interface
//Delphi: uses Windows,Messages,SysUtils,Variants,Classes,Graphics,Controls,Forms,Dialogs,StdCtrls,ExtCtrls;
//Lazarus: uses Classes,FileUtil,ExtCtrls;
uses
Windows,ExtCtrls,{für Fehler}debug;
type
//define usercontrol
TPanelImageButton = class(TPanel)
private
_PanelIndex: integer;
_Image: timage;
//define event
FOnClick: TNotifyEvent;
procedure ButtonClick(Sender: TObject);
procedure Resizeing(Sender: TObject);
protected
procedure Click; override; //override;//dynamic;
public
constructor Create(TheOwner: TComponent); overload; override;
constructor Create(TheOwner: TComponent; template: TPanel; imageTemplate: timage);
reintroduce; overload;
destructor Destroy; override;
function HasImage(): boolean;
published
property PanelIndex: integer read _PanelIndex write _PanelIndex;
property OnClick: TNotifyEvent read FOnClick write FOnClick;
end;
procedure Register;
implementation
procedure Register;
begin
RegisterComponents('PHOENIX',[TPanelImageButton]);
end;
constructor TPanelImageButton.Create(TheOwner: TComponent);
begin
inherited Create(TheOwner);
PanelIndex := -1;
_Image := nil;
self.Caption := '';
end;
constructor TPanelImageButton.Create(TheOwner: TComponent;
template: TPanel; imageTemplate: timage);
begin
inherited Create(TheOwner);
try
PanelIndex := -1;
self.Caption := template.Caption;
self.Color := template.Color;
self.Font := template.Font;
if (assigned(imageTemplate)) then
begin
_Image := timage.Create(self);
_Image.Picture.Assign(imageTemplate.Picture);
_Image.Transparent := True;
_Image.Parent := self;
_Image.Visible := True;
_Image.AutoSize := False;
_Image.Stretch := True;
_Image.OnClick := ButtonClick;
imageTemplate.Visible := False;
_Image.Cursor := crHandPoint;
end
else
if assigned(_Image) then
FreeAndNil(_Image);
self.OnResize := Resizeing;
//keine Ränder:
self.BevelOuter := bvNone;
self.BevelInner := bvNone;
self.Cursor := crHandPoint;
except
on e: Exception do
WriteDebug('PanelImageButton: ' + e.Message);
end;
end;
destructor TPanelImageButton.Destroy;
begin
try
self.Parent := nil;
if assigned(_Image) then
begin
_Image.parent := nil;
FreeAndNil(_Image);
end;
except
on e: Exception do
WriteDebug('TPanelImageButton.Destroy: ' + e.Message);
end;
inherited;
end;
function TPanelImageButton.HasImage(): boolean;
begin
Result := False;
if assigned(_Image) then
Result := True;
end;
procedure TPanelImageButton.Resizeing(Sender: TObject);
begin
if not (assigned(_Image)) then
exit;
try
_Image.Left := 6;
_Image.Height := self.Height - 12;
_Image.Top := 6;
_Image.Width := _Image.Height;
except
on e: Exception do
WriteDebug('PanelImageButton: ' + e.Message);
end;
end;
procedure TPanelImageButton.ButtonClick(Sender: TObject);
begin
Click;
end;
procedure TPanelImageButton.Click;
begin
try
if Assigned(FOnClick) then
FOnClick(Self);
except
on e: Exception do
WriteDebug('PanelImageButton: ' + e.Message);
end;
end;
end.
解决方法
我建议你仔细阅读:
-
Self
- 以及它的用途以及为其分配其他东西基本上使它变得无用。你本可以做到_Image.Parent := template;
。但是您将template
分配给self
,然后您执行self.OnResize := Resizeing;
。您想为这个OnResize
处理TPanelImageButton
(如果您没有更改它应该是Self
)还是想为 {{1} 处理OnResize
}?不理会template
。使用它来访问您当前正在编码的类的这个实例。 - 事件 - 您正在尝试释放事件变量。为什么?它只指向一个方法。它不是创建的。去看看 Delphi 中包含的组件如何处理事件。
-
self
运算符 - 在上面的评论中,您执行了@
。那是关于什么的?buttonUser.OnClick := @buttonUserClick;
运算符到处都有讨论。阅读。这是一件很酷的事情,但应该正确使用。这篇博文太酷了:http://rvelthuis.de/articles/articles-pointers.html
有一些基础知识需要解决,我强烈建议您研究 Delphi 中的组件是如何制作的。
最后一件非常重要的事情是将您看到的错误包含在 Stack Overflow 问题中。如果您这样做了,我们本可以就您的特定问题为您提供更具体的答案。你会回来抱怨一些其他错误,但至少你会了解第一个,希望如此。