Différences

Ci-dessous, les différences entre deux révisions de la page.

Lien vers cette vue comparative

Prochaine révision
Révision précédente
prog:lazarus:cas:wm_messages:intercepter [06/04/2021 20:05]
thierry créée
prog:lazarus:cas:wm_messages:intercepter [18/03/2023 12:41] (Version actuelle)
thierry [Interception d'un Message Windows]
Ligne 1: Ligne 1:
 ====== Interception d'un Message Windows ====== ====== Interception d'un Message Windows ======
-Ci dessous on cherche a intercepter le Message Windows ''​WM_DEVICECHANGE''​+===== Intercepter les WMMessages d'un TForm ===== 
 +On detourne WNDProc avec la function ''​Windows.WNDPROC(SetWindowLongPtr(AFormHandle,​ GWL_WNDPROC,​ PtrUInt(@NewWndCallback)));''​ 
 +<code delphi uWMInterceptor.pas>​ 
 +unit uWMInterceptor;​ 
 + 
 +{$mode ObjFPC}{$H+} 
 +interface 
 + 
 +uses 
 +  SysUtils, ​ Forms, ​ Controls, ​ Windows, LazLogger;​ 
 +var 
 +  OldWndProc: WNDPROC; 
 + 
 +procedure InitWMInterception(AFormHandle:​ THandle); 
 + 
 +implementation 
 + 
 +function NewWndCallback(Ahwnd:​ HWND; uMsg: UINT; wParam: WParam; 
 +  lParam: LParam): LRESULT; stdcall; 
 +begin 
 +   { Traitement des messages intercéptés } 
 +  case uMsg of 
 +    WM_DEVICECHANGE:​ debugLn('​Message : %x, %x, %x', [uMsg, wParam, lParam]); 
 +  end; 
 +   
 +  { Appel de l'​ancienne WNDProc } 
 +  Result := Windows.CallWindowProc(OldWndProc,​ Ahwnd, uMsg, WParam, LParam); 
 +end; 
 + 
 +procedure InitWMInterception(AFormHandle:​ THandle); 
 +begin 
 +  if AFormHandle <> 0 then 
 +   
 +     { Defini NewWndCallback comme nouvel intercepteur et stock l'​ancien dans OldWinProc } 
 +    OldWndProc := Windows.WNDPROC(SetWindowLongPtr(AFormHandle,​ GWL_WNDPROC,​ PtrUInt(@NewWndCallback)));​ 
 +end; 
 + 
 +end. 
 +</​code>​ 
 + 
 +===== Interception dans une Classe ===== 
 + 
 +Ci dessous on cherche a intercepter le Message Windows ''​WM_DEVICECHANGE'' ​dans une class.
  
 Trois étapes :  Trois étapes : 
-  - Détournement ​de tous les messages grâce à ''​lclintf.AllocateHWnd(@MessageInterceptor);''​ +  - Dans le ''​Create''​ de notre class, détournement ​de tous les messages ​vers la procedure ''​MessageInterceptor''​\\ ​grâce à ''​lclintf.AllocateHWnd(@MessageInterceptor);''​\\ (ATTENTION ''​AllocateHWnd''​ seul ne fonctionne pas, il faut bien préciser ''​LCLIntf.AllocateHWnd''​) 
-  - Tri et traitement des massages ​dans la procedure ''​MessageInterceptor''​+  - Tri et traitement des messages ​dans la procedure ''​MessageInterceptor''​
   - Retransmission du message a la fin de la procedure ​ ''​MessageInterceptor''​ avec  ''​AMessage.Result := DefWindowProc(FHandle,​ AMessage.Msg,​ AMessage.wParam,​ AMessage.lParam);''​   - Retransmission du message a la fin de la procedure ​ ''​MessageInterceptor''​ avec  ''​AMessage.Result := DefWindowProc(FHandle,​ AMessage.Msg,​ AMessage.wParam,​ AMessage.lParam);''​
 <code delphi> <code delphi>
Ligne 43: Ligne 85:
 begin begin
    ​inherited Create;    ​inherited Create;
 +   { AllocateHWnd créé une fenêtre Windows invisible servant a recevoir les Messages Windows }
 +   { FHandle = le Handle de la fenêtre cree, sinon 0 }
    ​FHandle := lclintf.AllocateHWnd(@MessageInterceptor);​    ​FHandle := lclintf.AllocateHWnd(@MessageInterceptor);​
 end; end;
Ligne 54: Ligne 98:
 procedure TTICDeviceChangeNotifier.MessageInterceptor(var AMessage: TMessage); procedure TTICDeviceChangeNotifier.MessageInterceptor(var AMessage: TMessage);
 begin begin
 +  ​
 +  // Si le message recu est un WM_DEVICECHANGE alors on l'​affiche
    if (AMessage.Msg = WM_DEVICECHANGE) then    if (AMessage.Msg = WM_DEVICECHANGE) then
       DebugLn(TimeToStr(Time) + ' : ' + Format('​[%0.4x] - [%0.4x] ',       DebugLn(TimeToStr(Time) + ' : ' + Format('​[%0.4x] - [%0.4x] ',
          ​[AMessage.wParam,​ AMessage.lParam]));​          ​[AMessage.wParam,​ AMessage.lParam]));​
 +         
 +  // DefWindowProc = ???
    ​AMessage.Result := DefWindowProc(FHandle,​ AMessage.Msg,​ AMessage.wParam,​    ​AMessage.Result := DefWindowProc(FHandle,​ AMessage.Msg,​ AMessage.wParam,​
       AMessage.lParam);​       AMessage.lParam);​
Ligne 64: Ligne 112:
 end.                              end.                             
 </​code>​ </​code>​
 +====== Sources & Ressources ======
 +  * [[https://​rmdiscala.developpez.com/​cours/​LesChapitres.html/​Cours7/​Chap7.2.htm|Tout sur LES MESSAGES WINDOWS]]
 +  * [[https://​www.developpez.net/​forums/​d1446203/​autres-langages/​pascal/​lazarus/​interception-messages-windows-service/​|Discussion sur l'​interception d'un message au sein d'un service]]
 +  * [[https://​wiki.lazarus.freepascal.org/​Win32/​64_Interface#​Processing_non-user_messages_in_your_window]]
 +