Hook WH_GETMESSAGE

Partagez votre expérience de PureBasic avec les autres utilisateurs.
nico
Messages : 3702
Inscription : ven. 13/févr./2004 0:57

Hook WH_GETMESSAGE

Message par nico »

Cet exemple montre l'utilisation du Hook WH_GETMESSAGE, il se compose d'une Dll et de l'appli qui va appeler cette Dll.

Pour le voir en fonctionnement , créer la Dll avec le code fourni ensuite lancer l'appli pui lancer la calculatrice de window (Démarrer-->exécuter-->calc).

Dans le menu système de la calculatrice (cliquer sur l'icône), il y a un nouvel Item qui apparait; si vous cliquer dessus l'appli va récupérer l'évènement et l'affiche dans le débugger.

La Dll qui portera le nom de WH_GETMESSAGE.dll:

Code : Tout sélectionner

Structure Partage 
     hook.l 
     hwnd.l 
     Donnee1.l 
     Donnee2.l 
     Donnee3.l 
     Donnee4.l 
     Donnee5.l      
EndStructure 

Global MemoirePartagee,*VueDonnees.Partage 

#WM_MONMESSAGE= #WM_USER+1 
#MF_STRING = $0 
#MF_ENABLED = $0 
#IDM_MYMENUITEM = 2006
#MSGF_MENU = 2

Procedure NouvelleProc( hwnd, msg,  wParam, lParam) 
     OriginProc.l= GetProp_(hwnd, "OriginProc") 
     *VueDonnees\Donnee1 = msg 
     *VueDonnees\Donnee2 = wParam                
     *VueDonnees\Donnee3 = lParam
     Select msg
          Case #WM_SYSCOMMAND
               If wParam = 2006
                    SendMessage_(*VueDonnees\hwnd, #WM_MONMESSAGE, 0, 0)  
               EndIf 
               
          Case #WM_DESTROY 
               RemoveProp_(*VueDonnees\Donnee5, "OriginProc") 
               SetWindowLong_(*VueDonnees\Donnee5, #GWL_WNDPROC, *VueDonnees\Donnee4)
               ProcedureReturn 0
     EndSelect 
     
     ProcedureReturn CallWindowProc_(OriginProc,hwnd,msg,wParam,lParam) 
EndProcedure  
     
     
Procedure GetMsgProc(nCode,wParam,lParam) 
     If nCode < 0 
          ProcedureReturn CallNextHookEx_(hook,nCode,wParam,lParam) 
     Else 
          Select nCode 
               Case #HC_ACTION
                    *pointeur.MSG=lParam 
                    Texte.s=Space(13)
                    GetWindowText_(*pointeur\hwnd,@Texte,13)
                    If Texte="Calculatrice"
                         If GetProp_(*pointeur\hwnd, "OriginProc")=0
                              hSystemMenu.l = GetSystemMenu_(*pointeur\hwnd, #False) 
                              AppendMenu_(hSystemMenu,#MF_STRING+#MF_ENABLED, #IDM_MYMENUITEM, "My Menu ITEM") 
                              OriginProc = SetWindowLong_(*pointeur\hwnd, #GWL_WNDPROC, @NouvelleProc()) 
                              SetProp_(*pointeur\hwnd, "OriginProc", OriginProc) 
                              *VueDonnees\Donnee4=OriginProc
                              *VueDonnees\Donnee5=*pointeur\hwnd
                         EndIf
                    EndIf       
          EndSelect 
          wParam=#PM_NOREMOVE
     EndIf 
     ProcedureReturn CallNextHookEx_(hook,nCode,wParam,lParam) 
EndProcedure 

     
ProcedureDLL AttachProcess(Instance) 
     MemoirePartagee=CreatefileMapping_($FFFFFFFF,#Null, #PAGE_READWRITE, 0, SizeOf(Partage),"Mapping") 
     *VueDonnees=MapViewOfFile_(MemoirePartagee, #FILE_MAP_WRITE, 0, 0, 0) 
EndProcedure 

ProcedureDLL DetachProcess(Instance) 
     UnmapViewOfFile_(*VueDonnees) 
     CloseHandle_(MemoirePartagee) 
EndProcedure 

ProcedureDLL AttachThread(Instance) 
EndProcedure 

ProcedureDLL DetachThread(Instance) 
EndProcedure 

ProcedureDLL Initialiser_Hook(Handle,hinst) 
     *VueDonnees\hwnd=Handle 
     hook = SetWindowsHookEx_(#WH_GETMESSAGE,@GetMsgProc(),hinst,0) 
     If hook = #False 
          MessageRequester("","Echec du Hook") 
          ProcedureReturn 0 
     EndIf 
     *VueDonnees\hook=hook 
     ProcedureReturn *VueDonnees 
EndProcedure    


ProcedureDLL Fermeture_Hook()
     SendMessage_(*VueDonnees\Donnee5,#WM_DESTROY,0,0)
     UnhookWindowsHookEx_(*VueDonnees\hook) 
     ProcedureReturn 1 
EndProcedure
Le code de l'appli:

Code : Tout sélectionner

#Librairie=0 
#WM_MONMESSAGE= #WM_USER+1 

Structure Partage2 
     hook.l 
     hwnd.l 
     Donnee1.l 
     Donnee2.l 
     Donnee3.l 
     Donnee4.l 
     Donnee5.l      
EndStructure 

Global *Vue.Partage2,ID 

Procedure ProcedureCallback(WindowID, Message, wParam, lParam) 
     Resultat = #PB_ProcessPureBasicEvents 
     Select Message 
          Case #WM_MONMESSAGE
               Select *Vue\Donnee1
                    Case #WM_SYSCOMMAND
                         Select *Vue\Donnee2
                              Case 2006
                                   Debug "2006"
                         EndSelect
               EndSelect 
     EndSelect 
     ProcedureReturn Resultat 
EndProcedure 


If OpenWindow(0,0,0,120,0,#PB_Window_SystemMenu|#PB_Window_TitleBar,"Pour quitter") 
     
     SetWindowCallback(@ProcedureCallback()) 
     
     Hmodule = OpenLibrary(#Librairie, "WH_GETMESSAGE.dll") 
     Debug Hmodule 
     
     *Vue=CallFunction(#Librairie, "Initialiser_Hook", WindowID(0),Hmodule) 
     
     If *Vue=0 
          MessageRequester("Info", "Erreur") 
     EndIf 
     
     
     Repeat  
     Until WaitWindowEvent() = #PB_EventCloseWindow 
     
     If CallFunction(#Librairie, "Fermeture_Hook")=0 
          MessageRequester("Info", "Erreur") 
     EndIf 
     
EndIf
:)
Dernière modification par nico le mer. 24/juin/2009 19:47, modifié 1 fois.
LOULOU25
Messages : 150
Inscription : mer. 19/mai/2004 20:40

Message par LOULOU25 »

Je viens de tester la DLL sous Windows XP Pack SP2 en ayant au préalable créer la dll avec purebasic
Le menu systéme est bien créé et le message du Debug s'affiche bien.
Je vais encore abuser de ta bonté, car en fait c'est d'un sous menu dont j'ais besoin. Je vais essayer de le créer à partir de ton modéle et ensuite je t'en reparlerais. En tout cas Merci car j'aurais bien été incapable de faire celà.
nico
Messages : 3702
Inscription : ven. 13/févr./2004 0:57

Message par nico »

Le debugger doit afficher à son lancement le Handle de la lib, as tu une valeur différente de 0 ?
LOULOU25
Messages : 150
Inscription : mer. 19/mai/2004 20:40

Message par LOULOU25 »

nico a écrit :Le debugger doit afficher à son lancement le Handle de la lib, as tu une valeur différente de 0 ?
Oui Aucun problême de ce coté, Je continuerais les tests ce soir.
nico
Messages : 3702
Inscription : ven. 13/févr./2004 0:57

Message par nico »

J'ai la même config que toi XP SP2 et j'ai refait les tests avec le code que j'ai posté et je n'ai pas rencontré de problème.

Si l'item est ajouté dans le menu, c'est que la dll est bien chargé!

Je vois pas trop, à part que certains progs comme les antivirus serait en mesure de détecter les hooks et peut être en empêcher le fonctionnement mais je ne crois pas que ce soit ça, à mon avis ce n'est pas à ce niveau la qu'ils interviennent.

Fait un debug à ce niveau là pour voir si tu vois quelquechose passer:

Code : Tout sélectionner

Procedure ProcedureCallback(WindowID, Message, wParam, lParam) 
     Resultat = #PB_ProcessPureBasicEvents 
     Debug Message
LOULOU25
Messages : 150
Inscription : mer. 19/mai/2004 20:40

Message par LOULOU25 »

J'ais réussi à mettre un sous menu dans un menu mais je ne réussit pas à intercepter le message WM_COMMANd avec ta dl ? As-tu une idée
nico
Messages : 3702
Inscription : ven. 13/févr./2004 0:57

Message par nico »

Tu parles de quoi là ?

du code que j'ai posté ou de ce même code que tu t'amuses à modifier?
LOULOU25
Messages : 150
Inscription : mer. 19/mai/2004 20:40

Message par LOULOU25 »

Code : Tout sélectionner


Structure Partage 
     hook.l 
     hwnd.l 
     Donnee1.l 
     Donnee2.l 
     Donnee3.l 
     Donnee4.l 
     Donnee5.l      
EndStructure 

Global MemoirePartagee,*VueDonnees.Partage 

#WM_MONMESSAGE= #WM_USER+1 
#MF_STRING = $0 
#MF_ENABLED = $0 
#IDM_MYMENUITEM = 2006 
#MSGF_MENU = 2 

Procedure NouvelleProc( hwnd, msg,  wParam, lParam) 
     OriginProc.l= GetProp_(hwnd, "OriginProc") 
     *VueDonnees\Donnee1 = msg 
     *VueDonnees\Donnee2 = wParam                
     *VueDonnees\Donnee3 = lParam 
     Select msg 
          Case #WM_COMMAND
          
               If wParam = 2006 
                    SendMessage_(*VueDonnees\hwnd, #WM_MONMESSAGE, 0, 0)  
               EndIf 
                
          Case #WM_DESTROY 
               RemoveProp_(*VueDonnees\Donnee5, "OriginProc") 
               SetWindowLong_(*VueDonnees\Donnee5, #GWL_WNDPROC, *VueDonnees\Donnee4) 
               ProcedureReturn 0 
     EndSelect 
      
     ProcedureReturn CallWindowProc_(OriginProc,hwnd,msg,wParam,lParam) 
EndProcedure  
      
      
Procedure GetMsgProc(nCode,wParam,lParam) 
     If nCode < 0 
          ProcedureReturn CallNextHookEx_(hook,nCode,wParam,lParam) 
     Else 
          Select nCode 
               Case #HC_ACTION 
                    *pointeur.MSG=lParam 
                    Texte.s=Space(13) 
                    GetWindowText_(*pointeur\hwnd,@Texte,13) 
                    If Texte="Calculatrice" 
                         If GetProp_(*pointeur\hwnd, "OriginProc")=0 
                          hSystemMenu.l= GetSubMenu_( GetMenu_(*pointeur\hwnd) ,0)                                     AppendMenu_(hSystemMenu,#MF_STRING+#MF_ENABLED, #IDM_MYMENUITEM, "My Menu ITEM") 
                            
                              OriginProc = SetWindowLong_(*pointeur\hwnd, #GWL_WNDPROC, @NouvelleProc()) 
                              SetProp_(*pointeur\hwnd, "OriginProc", OriginProc) 
                              *VueDonnees\Donnee4=OriginProc 
                              *VueDonnees\Donnee5=*pointeur\hwnd 
                         EndIf 
                    EndIf        
          EndSelect 
          wParam=#PM_NOREMOVE 
     EndIf 
     ProcedureReturn CallNextHookEx_(hook,nCode,wParam,lParam) 
EndProcedure 

      
ProcedureDLL AttachProcess(Instance) 
     MemoirePartagee=CreateFileMapping_($FFFFFFFF,#Null, #PAGE_READWRITE, 0, SizeOf(Partage),"Mapping") 
     *VueDonnees=MapViewOfFile_(MemoirePartagee, #FILE_MAP_WRITE, 0, 0, 0) 
EndProcedure 

ProcedureDLL DetachProcess(Instance) 
     UnmapViewOfFile_(VueDonnees) 
     CloseHandle_(MemoirePartagee) 
EndProcedure 

ProcedureDLL AttachThread(Instance) 
EndProcedure 

ProcedureDLL DetachThread(Instance) 
EndProcedure 

ProcedureDLL Initialiser_Hook(Handle,hinst) 
     *VueDonnees\hwnd=Handle 
     hook = SetWindowsHookEx_(#WH_GETMESSAGE,@GetMsgProc(),hinst,0) 
     If hook = #False 
          MessageRequester("","Echec du Hook") 
          ProcedureReturn 0 
     EndIf 
     *VueDonnees\hook=hook 
     ProcedureReturn *VueDonnees 
EndProcedure    


ProcedureDLL Fermeture_Hook() 
     SendMessage_(*VueDonnees\Donnee5,#WM_DESTROY,0,0) 
     UnhookWindowsHookEx_(*VueDonnees\hook) 
     ProcedureReturn 1 
EndProcedure
Code modifié en souligné gras italique permettant d'ajouter un élement du menu en lieu et place du menu system

Partie programme

Code : Tout sélectionner

#Librairie=0 
#WM_MONMESSAGE= #WM_USER+1 

Structure Partage2 
     hook.l 
     hwnd.l 
     Donnee1.l 
     Donnee2.l 
     Donnee3.l 
     Donnee4.l 
     Donnee5.l      
EndStructure 

Global *Vue.Partage2,ID 

Procedure ProcedureCallback(WindowID, Message, wParam, lParam) 
     Resultat = #PB_ProcessPureBasicEvents 
         Select Message 
          Case #WM_MONMESSAGE 
               Select *Vue\Donnee1 
                    [u][i][b]Case #WM_COMMAND [/b][/i][/u]
                         Select *Vue\Donnee2 
                              Case 2006 
                                   Debug "2006" 
                         EndSelect 
               EndSelect 
     EndSelect 
     ProcedureReturn Resultat 
EndProcedure 


If OpenWindow(0,0,0,120,0,#PB_Window_SystemMenu|#PB_Window_TitleBar,"Pour quitter") 
      
     SetWindowCallback(@ProcedureCallback()) 
      
     Hmodule = OpenLibrary(#Librairie, "WH_GETMESSAGE.dll") 
     Debug Hmodule 
      
     *Vue=CallFunction(#Librairie, "Initialiser_Hook", WindowID(0),Hmodule) 
      
     If *Vue=0 
          MessageRequester("Info", "Erreur") 
     EndIf 
      
      
     Repeat  
     Until WaitWindowEvent() = #PB_EventCloseWindow 
      
     If CallFunction(#Librairie, "Fermeture_Hook")=0 
          MessageRequester("Info", "Erreur") 
     EndIf 
      
EndIf
nico
Messages : 3702
Inscription : ven. 13/févr./2004 0:57

Message par nico »

Je te reposte les deux codes pour tes changements:

La Dll:

Code : Tout sélectionner

Structure Partage 
     hook.l 
     hwnd.l 
     Donnee1.l 
     Donnee2.l 
     Donnee3.l 
     Donnee4.l 
     Donnee5.l      
EndStructure 

Global MemoirePartagee,*VueDonnees.Partage 

#WM_MONMESSAGE= #WM_USER+1 
#MF_STRING = $0 
#MF_ENABLED = $0 
#IDM_MYMENUITEM = 2006 
#MSGF_MENU = 2 

Procedure NouvelleProc( hwnd, msg,  wParam, lParam) 
     OriginProc.l= GetProp_(hwnd, "OriginProc") 
     *VueDonnees\Donnee1 = msg 
     *VueDonnees\Donnee2 = wParam                
     *VueDonnees\Donnee3 = lParam 
     Select msg 
          Case #WM_COMMAND 
               If wParam = 2006 
                    SendMessage_(*VueDonnees\hwnd, #WM_MONMESSAGE, 0, 0)  
               EndIf 
                
          Case #WM_DESTROY 
               RemoveProp_(*VueDonnees\Donnee5, "OriginProc") 
               SetWindowLong_(*VueDonnees\Donnee5, #GWL_WNDPROC, *VueDonnees\Donnee4) 
               ProcedureReturn 0 
     EndSelect 
      
     ProcedureReturn CallWindowProc_(OriginProc,hwnd,msg,wParam,lParam) 
EndProcedure  
      
      
Procedure GetMsgProc(nCode,wParam,lParam) 
     If nCode < 0 
          ProcedureReturn CallNextHookEx_(hook,nCode,wParam,lParam) 
     Else 
          Select nCode 
               Case #HC_ACTION 
                    *pointeur.MSG=lParam 
                    Texte.s=Space(13) 
                    GetWindowText_(*pointeur\hwnd,@Texte,13) 
                    If Texte="Calculatrice" 
                         If GetProp_(*pointeur\hwnd, "OriginProc")=0 
                              ;hSystemMenu.l = GetSystemMenu_(*pointeur\hwnd, #False) 
                              Hmenu=GetMenu_(*pointeur\hwnd)
                              HsubMenu=GetSubMenu_( Hmenu,0)
                              AppendMenu_(HsubMenu,#MF_STRING+#MF_ENABLED, #IDM_MYMENUITEM, "My Menu ITEM") 
                              OriginProc = SetWindowLong_(*pointeur\hwnd, #GWL_WNDPROC, @NouvelleProc()) 
                              SetProp_(*pointeur\hwnd, "OriginProc", OriginProc) 
                              *VueDonnees\Donnee4=OriginProc 
                              *VueDonnees\Donnee5=*pointeur\hwnd 
                         EndIf 
                    EndIf        
          EndSelect 
          wParam=#PM_NOREMOVE 
     EndIf 
     ProcedureReturn CallNextHookEx_(hook,nCode,wParam,lParam) 
EndProcedure 

      
ProcedureDLL AttachProcess(Instance) 
     MemoirePartagee=CreateFileMapping_($FFFFFFFF,#Null, #PAGE_READWRITE, 0, SizeOf(Partage),"Mapping") 
     *VueDonnees=MapViewOfFile_(MemoirePartagee, #FILE_MAP_WRITE, 0, 0, 0) 
EndProcedure 

ProcedureDLL DetachProcess(Instance) 
     UnmapViewOfFile_(VueDonnees) 
     CloseHandle_(MemoirePartagee) 
EndProcedure 

ProcedureDLL AttachThread(Instance) 
EndProcedure 

ProcedureDLL DetachThread(Instance) 
EndProcedure 

ProcedureDLL Initialiser_Hook(Handle,hinst) 
     *VueDonnees\hwnd=Handle 
     hook = SetWindowsHookEx_(#WH_GETMESSAGE,@GetMsgProc(),hinst,0) 
     If hook = #False 
          MessageRequester("","Echec du Hook") 
          ProcedureReturn 0 
     EndIf 
     *VueDonnees\hook=hook 
     ProcedureReturn *VueDonnees 
EndProcedure    


ProcedureDLL Fermeture_Hook() 
     SendMessage_(*VueDonnees\Donnee5,#WM_DESTROY,0,0) 
     UnhookWindowsHookEx_(*VueDonnees\hook) 
     ProcedureReturn 1 
EndProcedure
La fenêtre principale:

Code : Tout sélectionner

#Librairie=0 
#WM_MONMESSAGE= #WM_USER+1 

Structure Partage2 
     hook.l 
     hwnd.l 
     Donnee1.l 
     Donnee2.l 
     Donnee3.l 
     Donnee4.l 
     Donnee5.l      
EndStructure 

Global *Vue.Partage2,ID 

Procedure ProcedureCallback(WindowID, Message, wParam, lParam) 
     Resultat = #PB_ProcessPureBasicEvents 
     Select Message 
          Case #WM_MONMESSAGE 
               Select *Vue\Donnee1 
                    Case #WM_COMMAND 
                         Select *Vue\Donnee2 
                              Case 2006 
                                   Debug "2006" 
                         EndSelect 
               EndSelect 
     EndSelect 
     ProcedureReturn Resultat 
EndProcedure 


If OpenWindow(0,0,0,120,0,"Pour quitter",#PB_Window_SystemMenu|#PB_Window_TitleBar) 
      
     SetWindowCallback(@ProcedureCallback()) 
      
     Hmodule = OpenLibrary(#Librairie, "WH_GETMESSAGE.dll") 
     Debug Hmodule 
      
     *Vue=CallFunction(#Librairie, "Initialiser_Hook", WindowID(0),Hmodule) 
      
     If *Vue=0 
          MessageRequester("Info", "Erreur") 
     EndIf 
      
      
     Repeat  
     Until WaitWindowEvent() = #PB_Event_CloseWindow 
      
     If CallFunction(#Librairie, "Fermeture_Hook")=0 
          MessageRequester("Info", "Erreur") 
     EndIf 
      
EndIf
Répondre