Lazarus

Free Pascal => General => Topic started by: TheLastCayen on November 14, 2019, 12:47:17 am

Title: setwindowshookex Incompatible type for arg (SOLVED)
Post by: TheLastCayen on November 14, 2019, 12:47:17 am
Hi

I am using:
 - Windows 7 64 bit
 - Lazarus 2.0.6
 - FPC 3.0.4

I am using this function from windows:
  kHook := setwindowshookex(WH_KEYBOARD,@LowLevelKeybdHookProc,0,GetCurrentThreadID());

This is my function:
  function LowLevelKeybdHookProc(nCode: LongInt; WPARAM: WPARAM; lParam : LPARAM) : LRESULT; stdcall;

This is my error message:

Error: Incompatible type for arg no. 2: Got "<procedure variable type of function(LongInt;Int64;Int64):Int64 of object;StdCall>", expected "<procedure variable type of function(LongInt;Int64;Int64):Int64;StdCall>"


I found this function on that post:
https://forum.lazarus.freepascal.org/index.php?topic=24023.0

but also from many other sources on the web. Anyone know why it's not working anymore and how can I fix it?

Thank you
Title: Re: setwindowshookex Incompatible type for arg
Post by: 440bx on November 14, 2019, 01:47:31 am
This is my error message:

Error: Incompatible type for arg no. 2: Got "<procedure variable type of function(LongInt;Int64;Int64):Int64 of object;StdCall>", expected "<procedure variable type of function(LongInt;Int64;Int64):Int64;StdCall>"
The error message indicates that you are passing the address of a class method (indicated by "of object".)  The hook procedure _cannot_ be a class method, it _must_ be a normal function.
Title: Re: setwindowshookex Incompatible type for arg
Post by: jamie on November 14, 2019, 03:14:23 am
I believe a CLASS PROCEDURE or FUNCTION will also work if the compiler will accept the STDCALL attached on the end of it  :D
Title: Re: setwindowshookex Incompatible type for arg
Post by: balazsszekely on November 14, 2019, 05:31:24 am
@TheLastCayen
Replace {$mode objfpc}{$H+} with {$mode delphi}. Check the following thread for more details:
https://forum.lazarus.freepascal.org/index.php/topic,37049.0.html
Title: Re: setwindowshookex Incompatible type for arg
Post by: Thaddy on November 14, 2019, 06:04:29 am
I believe a CLASS PROCEDURE or FUNCTION will also work if the compiler will accept the STDCALL attached on the end of it  :D
with the static modifier. and yes, stdcall will be accepted.
Title: Re: setwindowshookex Incompatible type for arg
Post by: PascalDragon on November 14, 2019, 09:14:13 am
@TheLastCayen
Replace {$mode objfpc}{$H+} with {$mode delphi}. Check the following thread for more details:
https://forum.lazarus.freepascal.org/index.php/topic,37049.0.html
That won't make a difference. The problem here is instance method vs. static/global function.
Title: Re: setwindowshookex Incompatible type for arg
Post by: balazsszekely on November 14, 2019, 11:09:44 am
@PascalDragon
Quote
That won't make a difference. The problem here is instance method vs. static/global function.
True. I did not read the error message carefully. Nevertheless the above mentioned thread still has a nice example on hooking(for those who are interested).
Title: Re: setwindowshookex Incompatible type for arg
Post by: TheLastCayen on November 14, 2019, 11:39:04 pm
Thank you for all those answers.  When I look at LRESULT , it's defined in base.inc :
Line 193 : LRESULT = LONG_PTR; 

LONG_PTR define in base,inc :
Line 89: LONG_PTR = PtrInt;

PtrInt is define in systemh.inc:
Line 338 PtrInt = Int64;

At the end, LRESULT should be an int64, not Int64 of object... I have a hard time understanding what I am doing wrong:( someone can tell me how I can modify this function so it will work?

Thank you
Title: Re: setwindowshookex Incompatible type for arg
Post by: PascalDragon on November 15, 2019, 09:10:38 am
I have a hard time understanding what I am doing wrong:( someone can tell me how I can modify this function so it will work?
Your function LowLevelKeybdHookProc is contained inside a class (probably your form class), thus it is an instance method, but it must not be such. So either move your function to outside of the class into the implementation section of your unit or declare your function as class function LowLevelKeybdHookProc(...): LRESULT; stdcall; static. Please note however that in both cases you can not directly access your class using Self.
Title: Re: setwindowshookex Incompatible type for arg
Post by: Thaddy on November 15, 2019, 09:51:58 am
Indeed, and you can pass self  as the lparam. See the documentation on msdn. (maybe in some cases self.handle, i need to check that)
And use PtrUint as the type to keep 32/64 bit compatibility. You are on 64 bit and compiling for 64 bit, it seems.
Title: Re: setwindowshookex Incompatible type for arg
Post by: TheLastCayen on November 15, 2019, 11:42:28 pm
Thank you for your reply.

Programming for windows using windows dll is always a nightmare:( My code is already working well under Linux and I start considering dropping the windows part:(

When I add static, I get that error message:
Error: Directive "STATIC" not allowed here


If I try to write the code for that function over implementation I get
Fatal: Syntax error, "IMPLEMENTATION" expected but "BEGIN" found

I should have mentioned, my lazarus/FPC are also 64bit.

I am getting really desperate here. Any other recommendations?

Title: Re: setwindowshookex Incompatible type for arg
Post by: 440bx on November 16, 2019, 12:22:29 am
I am getting really desperate here. Any other recommendations?
Yes, post the entire code of your hook function.   That would help figure out why you're having trouble with it.
Title: Re: setwindowshookex Incompatible type for arg
Post by: lucamar on November 16, 2019, 12:40:09 am
If I try to write the code for that function over implementation I get
Fatal: Syntax error, "IMPLEMENTATION" expected but "BEGIN" found

not over implementation but under it. That is, the function body (definition) should be inside the implementation section, as in:

Code: Pascal  [Select][+][-]
  1. implementation
  2.  
  3. function LowLevelKeybdHookProc(nCode: LongInt; WPARAM: WPARAM; lParam : LPARAM) : LRESULT; stdcall;
  4. begin
  5.   { Do something }
  6. end;
Title: Re: setwindowshookex Incompatible type for arg
Post by: jamie on November 16, 2019, 01:01:41 am
This is against my religion but here goes.. ;D

Code: Pascal  [Select][+][-]
  1. unit Unit1;
  2.  
  3. {$mode objfpc}{$H+}
  4.  
  5. interface
  6.  
  7. uses
  8.   Windows, Classes, SysUtils, Forms, Controls, Graphics, Dialogs;
  9.  
  10. type
  11.  
  12.   { TForm1 }
  13.  
  14.   TForm1 = class(TForm)
  15.     procedure FormCreate(Sender: TObject);
  16.   private
  17.  
  18.   public
  19.   HookHandle:Int64;
  20.   Class Function AHookProc(nCode:LongInt; awParam:WPARAM;aLparam:LParam):LRESULT; StdCall; Static;
  21.   end;
  22.  
  23. var
  24.   Form1: TForm1;
  25.  
  26. implementation
  27.  
  28. {$R *.lfm}
  29.  
  30. procedure TForm1.FormCreate(Sender: TObject);
  31. begin
  32.   HookHandle := SetWindowsHookEx(WH_KEYBOARD, HookPROC(@TForm1.AHookProc),HInstance, GetThreadID);
  33. end;
  34.  
  35. class Function Tform1.AHookProc(nCode:LongInt; awParam:WPARAM;aLparam:LParam):LRESULT; StdCall;
  36. Begin
  37.  // Hit a key...
  38.   Beep;
  39.  Result :=  CallnextHookEx(Form1.HookHandle,nCode,AwParam, ALparam);
  40. end;
  41.  
  42. end.
  43.  
  44.  
Title: Re: setwindowshookex Incompatible type for arg
Post by: TheLastCayen on November 16, 2019, 05:20:43 am
Thank you for your help everyone.
 
Jamie, with your code I can finally compile without an error message:)
Title: Re: setwindowshookex Incompatible type for arg (SOLVED)
Post by: jamie on November 16, 2019, 11:04:49 pm
Yeah no problem, I'll most likely get castrated for giving you that bit of info. >:(
Title: Re: setwindowshookex Incompatible type for arg (SOLVED)
Post by: PascalDragon on November 17, 2019, 10:53:58 am
Yeah no problem, I'll most likely get castrated for giving you that bit of info. >:(
Why? It was one of the two solutions suggested by me as well.
Title: Re: setwindowshookex Incompatible type for arg (SOLVED)
Post by: 440bx on November 17, 2019, 11:39:55 am
Why? It was one of the two solutions suggested by me as well.
Because he bought cheap real estate, consequently he gets bad schools and extreme neighbors ;) 
Title: Re: setwindowshookex Incompatible type for arg (SOLVED)
Post by: jamie on November 17, 2019, 05:24:38 pm
You may have a point there but the real-estate here isn't cheap although we just don't seem to use any of our tax money at work.. I think it has something to do with over paid gov workers and too many free lunch programs.
Title: Re: setwindowshookex Incompatible type for arg
Post by: Remy Lebeau on November 22, 2019, 03:58:59 am
Indeed, and you can pass self  as the lparam.

No, you can't, because SetWindowsHookEx() does not allow you to pass any user-defined values to its hooks.  So you will have to use either a global variable or a thunk to get the Self pointer into the hook procedure.
TinyPortal © 2005-2018