1

Here is my simple code which compiles well, but raise Access Violation. It enters MD procedure and debugger displays some X and Y value, but after exiting procedure AV happens. Hope someone can help.

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Controls, Forms,  ExtCtrls;

type
  TForm1 = class(TForm)
    Panel1: TPanel;
    procedure FormCreate(Sender: TObject);
  end;

var
  Form1: TForm1;

implementation

    {$R *.dfm}

procedure MD(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
begin
  form1.caption:= inttostr(x)+ ' '+ inttostr(y);
end;

procedure TForm1.FormCreate(Sender: TObject);

function MakeMethod(data, code: pointer): TMethod;
begin
  result.Data:= data;
  result.Code:= code;
end;

begin
  panel1.OnMouseDown:= TMouseEvent(MakeMethod(nil, @MD));
end;

end.

Thanks

10
  • 1
    Are you surprised by the AV? - You passing Nil to MakeMethod. Commented Jul 12, 2016 at 8:27
  • Same happens if I put pointer to some array of bytes. Commented Jul 12, 2016 at 8:38
  • @MartynA, your comments are completely misleading, MD never references data pointer, the actual reason of failure is parameter mismatch. Commented Jul 12, 2016 at 9:23
  • 1
    If you don't want to make MD a method of TForm1 you could try the technique I described here: stackoverflow.com/questions/11083336/…. Commented Jul 12, 2016 at 9:37
  • 1
    @Uli Gerhardt - Yes, I was aware of that solution and it works OK. However solution with class procedures raises compile problems with Lazarus (it is my prime interest) which I didn't understand. However this should be for some other thread. Commented Jul 12, 2016 at 10:04

2 Answers 2

5

MD signature should include additional hidden parameter; it solves AV issue.

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, ExtCtrls;


type
  TForm1 = class(TForm)
    Panel1: TPanel;
    procedure FormCreate(Sender: TObject);
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure MD(Instance, Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
begin
  form1.caption:= inttostr(x)+ ' '+ inttostr(y);
end;

procedure TForm1.FormCreate(Sender: TObject);

function MakeMethod(data, code: pointer): TMethod;
begin
  result.Data:= data;
  result.Code:= code;
end;

begin
  panel1.OnMouseDown:= TMouseEvent(MakeMethod(nil, @MD));
end;

end.
Sign up to request clarification or add additional context in comments.

8 Comments

Care to explain why OnCreate isn't good place? I never have any problem with that. VCL/FMX also does that as the step of Create sequence.
@FreeConsulting - my fault, works with OnCreate too. Edited.
@Djole, it worked because not all TMouseEvent parameters can fit into registers, so uses stack. And so causes misaligned stack when you mismatch the signature.
This technique is basically the same without the hackery. :-)
Using a class method is without doubt a better solution.
|
1

Try making MD a member of your form class. Edit your example the following way: In the class definition:

type
TForm1 = class(TForm)
  Panel1: TPanel;
  procedure FormCreate(Sender: TObject);
  procedure MD(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
end;

Later in your code make sure to enter the owner of the MD method like so:

procedure TForm1.MD(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);

Finally, when assigning this eventhandler to your component, all you have to do is:

panel1.OnMouseDown:= MD;

I don't know what your intention was, but that is how you take care of eventhandlers at run time.

2 Comments

I know that, but I intentionally try to use global function, rather then method. It was just the matter of curiosity.
Perhaps clarify your intention. I simply don't see the need for doing things the way your example suggests. Perhaps try your method with something other than an event handler. Try something simple first, maybe a method without parameters, then work yourself up to methods with parameters.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.