J'essaie de porter un cours que j'ai écrit en Delphi sur Lazarus. Il s'appuie sur WM_DEVICECHANGE
pour détecter les périphériques USB connectés. Je n'arrive pas à recevoir les messages Windows de mon composant alors qu'il fonctionnait parfaitement dans Delphi. Après avoir réalisé que AllocateHwnd
est juste un espace réservé dans Free Pascal, j'ai commencé à imiter ce que fait LCL dans ce but.Recevoir et gérer les messages Windows dans Lazarus
TUSB = class(TComponent)
private
FHandle: HWND;
procedure WndProc(var Msg: TMessage);
procedure AllocHandle(Method: TWndMethod);
public
constructor Create(AOwner: TComponent);
end;
.
.
.
procedure CallbackAllocateHWnd(Ahwnd: HWND; uMsg: UINT; wParam: WParam; lParam: LParam); stdcall;
var
Msg: TMessage;
PMethod: ^TWndMethod;
begin
FillChar(Msg{%H-}, SizeOf(Msg), #0);
Msg.msg := uMsg;
Msg.wParam := wParam;
Msg.lParam := lParam;
PMethod := {%H-}Pointer(GetWindowLong(ahwnd, GWL_USERDATA));
if Assigned(PMethod) then PMethod^(Msg);
Windows.DefWindowProc(ahwnd, uMsg, wParam, lParam);
end;
procedure TUSB.AllocHandle(Method: TWndMethod);
var
PMethod: ^TWndMethod;
begin
FHandle := Windows.CreateWindow(PChar('STATIC'), '', WS_OVERLAPPED, 0, 0, 0, 0, 0, 0, MainInstance, nil);
if Assigned(Method) then
begin
Getmem(PMethod, SizeOf(TMethod));
PMethod^ := Method;
SetWindowLong(FHandle, GWL_USERDATA, {%H-}PtrInt(PMethod));
end;
SetWindowLong(FHandle, GWL_WNDPROC, {%H-}PtrInt(@CallbackAllocateHWnd));
end;
constructor TUSB.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
AllocHandle(@WndProc);
end;
Cela me donne une poignée de fenêtre valide, mais CallbackAllocateHWnd
est jamais appelé. Je sais que ce genre de choses est propre à Windows et non portable, mais ce n'est pas le problème maintenant. Je veux juste dériver une classe de TComponent
et pouvoir recevoir et manipuler des messages de Windows. Les mêmes lignes de code exactes, fonctionnent en Delphi.
Modifier: également essayé HWND_MESSAGE comme hWndParent
.
Édition 2: J'ai trouvé que l'appel GetLastError
après SetWindowLong(FHandle, GWL_WNDPROC, {%H-}PtrInt(@CallbackAllocateHWnd));
renvoie 1413 ce qui signifie un index invalide. J'ai même essayé GetWindowLong
là et me donne la même erreur!
Est-ce que allochandle s'exécute? Afaik setwindowlong retourne l'ancien wndproc, l'enregistre et l'appelle dans votre wndproc –
FHandle a un handle de fenêtre valide après l'exécution de AllocHandle, mais mon WndProc personnalisé n'est pas déclenché lorsqu'un message lui est envoyé. –