Delphi 5:将点击事件分配给 TImage 时出错

问题描述

我为 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 问题中。如果您这样做了,我们本可以就您的特定问题为您提供更具体的答案。你会回来抱怨一些其他错误,但至少你会了解第一个,希望如此。