[fpc-pascal]About callbacks method of a class

memsom at interalpha.co.uk memsom at interalpha.co.uk
Wed Nov 13 16:36:26 CET 2002


Noting that I know nothing about the way GTK works with Object Pascal from a 
FPC perspective...

Your problem is the callback itself. The procedure has the right signature, but 
it is attached to the Class, and so is going to cause you untold woes.

You want (by the look of it) the following:

type
  procedure (widget:PGtkWidget; data:Object); cdecl;

but what you actually have is:

type
  procedure (widget:PGtkWidget; data:Object) of object; cdecl;

I once found a convoluted way of converting the VMT pointer to a Function 
pointer, but it was unreliable. 

A nasty, but fairly simple, solution would be to write a single callback and 
dispatch it to the correct control. If anyone knows a better way, please feel 
free to chip in ;-) (NB. I have *not* compiled the code below, indeed I doubt 
it will compile without modification. It is meant to be a guide of sorts.)

e.g.

  TButton = class(Tobject)
  private
    FButton:PGtkWidget;
  public
    constructor Create; virtual;
    destructor  Destroy; override;
    property OnClick: TNotifyEvent; //this is the usual Delphi way
  end;//TButton

  var
    ButtonList: TStringList; //just for look up simplicity

  procedure InitList; //this has to be called before using controls
  begin
    ButtonList := TStringList.Create; 
  end;

  function RegButton(name: string; Button: TButton): integer;
  begin
    Buttonlist.AdObject(name, Button);
  end;
 
  function FindButton(name: string): TButton;
  var
    idx: integer;
  begin
    idx := Buttonlist.Indexof(name);
    if idx > -1 then begin
      Result := TButton(ButtonList.Objects[i]);
    end
    else
      Result := nil;
  end;

  function FindPointer(widget:PGtkWidget): TButton;
  var
    aname: string;
  begin
    //get the widgets name..
    aname := ???? //must be a way of doing this... 
                  //I have no knowledge of GTK though
    
    Result := FindButton(aname);
  end;

  procedure globalCallback_OnClick(widget:PGtkWidget; data:Object); cdecl;
  var
    abutton: TButton;
  begin
    abutton := FindPointer(widgit);
    if assigned(abutton) then
       abutton.OnCLick(nil); //you'll have to decide who the sender is I guess
  end;

  constructor TButton.Create;
  begin
    inherited Create;
    FButton:=gtk_button_new_with_label('Click Me!');
    gtk_widget_show(FButton);
    g_signal_connect(G_OBJECT(FButton),'clicked',
      TGCALLBACK(@globalCallback_OnClick),self);
    ...
  end;//TButton.Create




> Hello, everybody
> 
>   I am using gtk2forpascal. I want to program as follows:
> >>>>>
> TButton = class(Tobject)
>   private
>     FButton:PGtkWidget;
>   public
>     constructor Create;
>     destructor  Destroy;
>     procedure   Callback_OnClick(widget:PGtkWidget; data:Object); cdecl;
> end;//TButton


---------------------------------------------
This message was sent using Mistral WebMail.
http://www.mistral.co.uk/






More information about the fpc-pascal mailing list