* * *

Author Topic: Receive and Handle Windows Messages  (Read 783 times)

DelphiBoy

  • Newbie
  • Posts: 3
Receive and Handle Windows Messages
« on: April 09, 2017, 07:28:17 am »
I'm trying to port a class I've written in Delphi to Lazarus. It relies on WM_DEVICECHANGE to detect attached USB devices (need to derive from TComponent). I can't get my component to receive Windows messages, while it was working perfectly in Delphi.

I know that AllocateHwnd is just a placeholder in Free Pascal, so I'm trying to mimic what LCL does (here I'm using WM_PAINT for testing):

Code: Pascal  [Select]
  1. TUSB = class(TComponent)
  2. private
  3.     FHandle: HWND;
  4.     procedure WndProc(var Msg: TMessage);
  5. public
  6.      constructor Create(AOwner: TComponent);
  7. end;
  8. .
  9. .
  10. .
  11. procedure CallbackAllocateHWnd(Ahwnd: HWND; uMsg: UINT; wParam: WParam; lParam: LParam); stdcall;
  12. var
  13.   Msg: TMessage;
  14.   PMethod: ^TWndMethod;
  15. begin
  16.   FillChar(Msg{%H-}, SizeOf(Msg), #0);
  17.  
  18.   Msg.msg := uMsg;
  19.   Msg.wParam := wParam;
  20.   Msg.lParam := lParam;
  21.  
  22.   PMethod := {%H-}Pointer(GetWindowLong(ahwnd, GWL_USERDATA));
  23.  
  24.   if Assigned(PMethod) then PMethod^(Msg);
  25.  
  26.   Windows.DefWindowProc(ahwnd, uMsg, wParam, lParam);
  27. end;
  28.  
  29. function MyAllocateHwnd(Method: TWndMethod):HWND;
  30. var
  31.   PMethod: ^TWndMethod;
  32.  
  33. begin
  34.   Result := Windows.CreateWindow(PChar('STATIC'),
  35.    '', WS_OVERLAPPED, 0, 0, 0, 0, HWND_MESSAGE, 0, MainInstance, nil);
  36.  
  37.   if (Result = 0) then ShowMessage('error:'+IntToStr(GetLastError));
  38.  
  39.   if Assigned(Method) then
  40.   begin
  41.     Getmem(PMethod, SizeOf(TMethod));
  42.     PMethod^ := Method;
  43.  
  44.     SetWindowLong(Result, GWL_USERDATA, {%H-}PtrInt(PMethod));
  45.   end;
  46.  
  47.   SetWindowLong(Result, GWL_WNDPROC, {%H-}PtrInt(@CallbackAllocateHWnd));
  48. end;
  49.  
  50. procedure TUSB.WndProc(var Msg: TMessage);
  51. begin
  52.   if Msg.Msg = WM_PAINT then
  53.     ShowMessage('message received')
  54.   else
  55.     Msg.Result:= DefWindowProc(FHandle, Msg.Msg, Msg.WParam, Msg.LParam);
  56. end;
  57.  
  58. constructor TUSB.Create(AOwner: TComponent);
  59. begin
  60.   inherited Create(AOwner);
  61.  
  62.   FHandle:= MyAllocateHwnd(@WndProc);
  63. end;  
  64.  
  65.  

This gives me a valid window handle, but a breakpoint in CallbackAllocateHWnd is never hit by SendMessage(). Exactly the same lines of code, works in Delphi (without using built-in AllocateHwnd). What am I missing?

PS: I know this is specific to Windows and not portable. That's fine.
« Last Edit: April 09, 2017, 07:32:56 am by DelphiBoy »

Handoko

  • Hero Member
  • *****
  • Posts: 1008
  • My goal: build my own game engine using Lazarus
Re: Receive and Handle Windows Messages
« Reply #1 on: April 09, 2017, 09:31:18 am »
Hello DelphiBoy,
Welcome to this forum.

I found that this link below maybe useful for you:
http://forum.lazarus.freepascal.org/index.php?topic=6062.0

marcov

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 5338
Re: Receive and Handle Windows Messages
« Reply #2 on: April 09, 2017, 12:32:38 pm »
He registers an own handle, so it should be entirely outside of the lcl's control.

At first glace everything is ok. Checking return values from functions seems most prudent

DelphiBoy

  • Newbie
  • Posts: 3
Re: Receive and Handle Windows Messages
« Reply #3 on: April 10, 2017, 08:09:33 am »
I just found out that after line

Code: Pascal  [Select]
  1. SetWindowLong(Result, GWL_WNDPROC, {%H-}PtrInt(@CallbackAllocateHWnd));
  2.  

GetLastError returns 1413, which is "invalid index". I added SetLastError(0) as per instructions here: https://msdn.microsoft.com/en-us/library/windows/desktop/ms633591(v=vs.85).aspx

Just to test, I replaced SetWindowLong, with GetWindowLong and it also gives me 1413.

Any ideas?
« Last Edit: April 10, 2017, 08:27:31 am by DelphiBoy »

DonAlfredo

  • Hero Member
  • *****
  • Posts: 677
Re: Receive and Handle Windows Messages
« Reply #4 on: April 10, 2017, 08:50:32 am »
I use an LCL function to alloc:

Code: Pascal  [Select]
  1. {$ifdef FPC}
  2.     FHWnd := LCLIntf.AllocateHWnd(EventPipe);
  3. {$else}
  4.     FHWnd := AllocateHWnd(EventPipe);
  5. {$endif}

DelphiBoy

  • Newbie
  • Posts: 3
Re: Receive and Handle Windows Messages
« Reply #5 on: April 10, 2017, 05:55:12 pm »
What is EventPipe? Can you please share more code?

What I'm doing is very similar to what LCL does. Why  do I get 1413?


 

Recent

Get Lazarus at SourceForge.net. Fast, secure and Free Open Source software downloads Open Hub project report for Lazarus