Delphi 5: Error asigning click event to TImage

249 Views Asked by At

I created an custom control for the TStatusbar. Its in old Delphi5 for windows. The goal is, if I click the panel or the image, an event should be raise. But I get an error by assigning the click event to the image. The error is in line starts with _Image.OnClick := ButtonClick; Can anyone solve this? Thank you!

I modified the code, it works now. Any suggestions to make it even better? My main mistake was that I misunderstand

self := TPanelImageButton(template);

I read, that in this case self should inherit all from template. But I guess this was wrong. So I now set the properties I need in code.

Thank you!

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, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, StdCtrls, ExtCtrls;
uses
  Windows, Messages, Classes, SysUtils, FileUtil, Forms, Controls,
  Graphics, Dialogs, StdCtrls, 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.
1

There are 1 best solutions below

3
Blurry Sterk On

I propose that you read up on:

  • Self - and what it is for and that assigning something else to it basically makes it useless. You could have made it _Image.Parent := template;. But you assigned template to self and then later you do self.OnResize := Resizeing;. Do you want to handle OnResize for this TPanelImageButton (which should have been Self if you did not change it) or do you want to handle OnResize for template? Leave self alone. Use it to access this instance of the class you are currently coding in.
  • Events - You are trying to free an event variable. Why? It only points to a method. It was not created. Go see how the components that are included with Delphi do events.
  • @ operator - In one of you comments above you do buttonUser.OnClick := @buttonUserClick;. What is that about? The @ operator is discussed everywhere. Read up. Its a cool thing but should be used correctly. This blog post is so cool: http://rvelthuis.de/articles/articles-pointers.html

There are some basics that needs to be addressed and I strongly recommend you study how components in Delphi are made.

The last very important thing is for you to include the errors you see into the Stack Overflow question. If you did that we could have given you more specific answers on your particular issue. You would have returned complaining about some other error but at least you would have learned about the first one, hopefully.