[SOLVED] TImage TmouseEvent stackframe issue lazarus / 21-General ---------------------------------------------------------------------- 4nlegion · 2021-08-03 03:03 Hi, i have a problem with the stackframe of the OnMouseDown event of a TImage created at runtime. Note the Timage.OnMouseDown assignment via TMethod. Upon MouseDown, MouseDownEvent is called with the wrong stackframe. It appears to be off by sizeof(TMouseButton). Is my definition of TMouseEvent incorrect? Regards. Also, is there a recommended practice to preclude such a declaration mismatch? Details: Ubuntu 20.04, FPC version 3.2.0 [2020/07/07] for x86_64, Lazarus: 2.0.12 Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i procedure MouseDownEvent(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X,Y: Integer);begin        if not (Sender is TImage) then exit;        Form1.ListBox1.Items.AddText(format('[x,y]: [%d,%d]',[x,y]));   // note incorrect [x,y] reportingend; procedure TForm1.FormCreate(Sender: TObject);var        e:      TMethod;begin      img:=TImage.create(Form1);        img.Parent:=Form1;        img.left:=32;        img.top:=32;        img.width:=400;        img.height:=400;        img.Canvas.Brush.Color := clgreen;        img.Canvas.Brush.style := bsSolid;        img.canvas.FillRect(0,0,400,400);         e.Data:=img;        e.Code:=@MouseDownEvent;        img.OnMouseDown:=TMouseEvent(e);end; ---------------------------------------------------------------------- lucamar · 2021-08-03 04:10 No, it isn't. Events are declared as "of object" which means that they have to be declared/defined as methods of an object (usually, though not always, of the form itself). Try something like: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i {in the interface section ...}   TForm1 = class(TForm)    {... other declarations ...}    procedure ImageMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X,Y: Integer);  end;  {then, in the implementation section ...}  procedure TForm1.ImageMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X,Y: Integer);begin        if not (Sender is TImage) then exit;        Form1.ListBox1.Items.AddText(format('[x,y]: [%d,%d]',[x,y]));   // note incorrect [x,y] reportingend; Any reason why you're using an assignment through TMethod? Normally that's used only when you need to access the RTTI of an object's methods. ---------------------------------------------------------------------- 4nlegion · 2021-08-03 04:16 This was an example distilled from a larger unit. I am working on an editor unit that handles many of it's own events and exhibits this issue. I was (lucky?) that this smaller code showed the same symptom. ---------------------------------------------------------------------- 4nlegion · 2021-08-03 04:40 I just read a different Forum Post https://forum.lazarus.freepascal.org/index.php?topic=31306.0 and Thaddy replied with: "...procedure of object has a hidden self pointer..." Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i   procedure DoSomeThing(Dummy:Pointer;Sender:TObject);  begin    writeln('Hello');  end;   so changing the previous event handler to: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i procedure MouseDownEvent(Dummy:Pointer; Sender: TObject; Button: TMouseButton; Shift: TShiftState; X,Y: Integer);begin        if not (Sender is TImage) then exit;        Form1.ListBox1.Items.AddText(format('[x,y]: [%d,%d]',[x,y]));   // note NOW correct [x,y] reportingend;   ...works as intended. Many thanks! ---------------------------------------------------------------------- 4nlegion · 2021-08-03 06:55 In case anyone cares... Combining lucamar's solution we have: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i unit Unit1;{$mode objfpc}{$H+}interfaceuses        Classes, SysUtils, Forms, Controls, Graphics,Dialogs, StdCtrls, ExtCtrls;type        TImage1 = class(TImage)                procedure DoOnMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X,Y: Integer);      end;         TForm1 = class(TForm)                ListBox1: TListBox;                procedure FormCreate(Sender: TObject);      private        public        end; var        Form1:  TForm1;        img:    TImage; implementation{$R *.lfm}{ TForm1 }procedure MouseDownEvent(Dummy:Pointer; Sender: TObject; Button: TMouseButton; Shift: TShiftState; X,Y: Integer);begin        if not (Sender is TImage) then exit;        Form1.ListBox1.Items.AddText(format('[x,y]: [%d,%d]',[x,y]));   // now is correct [x,y] reportingend; procedure TImage1.DoOnMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X,Y: Integer);begin        if not (Sender is TImage) then exit;        Form1.ListBox1.Items.AddText(format('[x,y]: [%d,%d]',[x,y]));   // now is correct [x,y] reportingend; procedure TForm1.FormCreate(Sender: TObject);var        e:      TMethod;begin      img:=TImage.create(Form1);        img.Parent:=Form1;        img.left:=32;        img.top:=32;        img.width:=400;        img.height:=400;        img.Canvas.Brush.Color := clgreen;        img.Canvas.Brush.style := bsSolid;        img.canvas.FillRect(0,0,400,400);         e.Data:=img;        e.Code:=@TImage1.DoOnMouseDown; //MouseDownEvent;        img.OnMouseDown:=TMouseEvent(e);end; end.