Page 1 sur 1

[Résolu] Hook de la roulette de souris...

Publié : sam. 30/nov./2013 18:43
par Fig
Quelqu'un sait il faire un hook de la roulette (Wheelmouse) de la souris ?

Je souhaite intercepter cette information sans que le programme qui a le focus ne la reçoive...
J'ai vu un exemple sur le forum anglais pour une touche clavier [space] mais je ne sais pas comment l'adapter.

Re: Hook de la roulette de souris...

Publié : sam. 30/nov./2013 19:15
par falsam
Le focus sur la fenêtre n'est pas nécessaire.

Code : Tout sélectionner

Procedure.w MouseWheelDelta()
  wz.w = ((EventwParam()>>16)&$FFFF)
  ProcedureReturn -(wz/100)
EndProcedure

Procedure MouseKeyHook(nCode, wParam, lParam) 
  Select wParam
    Case #WM_MOUSEWHEEL
      Debug MouseWheelDelta()
      
  EndSelect

  ProcedureReturn CallNextHookEx_(0, nCode, wParam, lParam) 
 
EndProcedure 

OpenWindow(0, 0, 0, 240, 140, "Mouse Wheel", #WS_CAPTION|#WS_SYSMENU|1) 
StickyWindow(0,1) 

hhkLLMouse = SetWindowsHookEx_(#WH_MOUSE_LL, @MouseKeyHook(), GetModuleHandle_(0), 0) 
hhkLLKey = SetWindowsHookEx_(#WH_KEYBOARD_LL, @MouseKeyHook(), GetModuleHandle_(0), 0) 

Repeat 
 Event = WaitWindowEvent() 
Until Event = #PB_Event_CloseWindow

UnhookWindowsHookEx_(hhkLLMouse)
UnhookWindowsHookEx_(hhkLLKey)

Re: Hook de la roulette de souris...

Publié : lun. 02/déc./2013 10:48
par Kwai chang caine
Le focus sur la fenêtre n'est pas nécessaire.
Sur W7, ça capte bien l'evenement mais ça retourne zero si y'a pas le focus...enfin c'est juste pour l'info :wink:
Et comme dirait dupont et dupont..."Je dirais même plus" en ayant le focus ça retourne une fois zero si on ne survole pas la fenetre
En tout cas merci FALSAM 8)

Re: Hook de la roulette de souris...

Publié : mar. 03/déc./2013 9:59
par Fig
Tu as raison, Falsam, ton code retourne 0 quand il n'a pas le focus... Néanmoins il retourne une valeur, ce qui montre qu'il est conscient que la roulette est actionnée.... Que faire ? :(

Re: Hook de la roulette de souris...

Publié : mar. 03/déc./2013 12:37
par nico

Code : Tout sélectionner

Global hhkLLMouse.i

Structure MSLLHOOKSTRUCT
  pt.POINT
  DmouseData.l
  flags.l
  time.l
  CompilerIf #PB_Compiler_Processor = #PB_Processor_x64
    PB_Alignment.b[4]
  CompilerEndIf
  dwExtraInfo.i
EndStructure


Procedure MouseKeyHook(nCode.l, wParam.i, lParam.i)
  Protected *pointer.MSLLHOOKSTRUCT = lparam
  
  If ncode = #HC_ACTION
    Select wParam
      Case #WM_MOUSEWHEEL
        Debug *pointer\DmouseData >>16
        
    EndSelect
  EndIf 
  ProcedureReturn CallNextHookEx_(hhkLLMouse, nCode, wParam, lParam) 
  
EndProcedure 

OpenWindow(0, 0, 0, 240, 140, "Mouse Wheel", #WS_CAPTION|#WS_SYSMENU|1) 
StickyWindow(0,1) 

hhkLLMouse = SetWindowsHookEx_(#WH_MOUSE_LL, @MouseKeyHook(), GetModuleHandle_(0), 0) 

Repeat 
  Event = WaitWindowEvent() 
Until Event = #PB_Event_CloseWindow

UnhookWindowsHookEx_(hhkLLMouse)

Re: Hook de la roulette de souris...

Publié : mar. 03/déc./2013 13:19
par falsam
pas mal ton code Nico :)
Fig a écrit :Tu as raison, Falsam, ton code retourne 0 quand il n'a pas le focus... Néanmoins il retourne une valeur, ce qui montre qu'il est conscient que la roulette est actionnée.... Que faire ? :(
Effectivement la roulette de la souris est bien détectée mais le delta ne se calcule plus !!!

Un autre code (MouseHook.pb) de http://www.purearea.net que j'ai modifié qui te permet de savoir si la molette est activée.

Code : Tout sélectionner

Global EventId, hhook

Procedure MouseProc(nCode, wParam, lParam)
  Protected *ms.MOUSEHOOKSTRUCT = lParam
   
  If wParam = #WM_MOUSEWHEEL
    Debug *ms\hwnd 
  EndIf
  
EndProcedure

If OpenWindow(0, 0, 0, 300, 200, "Mouse hook example", #PB_Window_SystemMenu)
  
  hhook = SetWindowsHookEx_(#WH_MOUSE_LL, @MouseProc(), GetModuleHandle_(0), 0)
  Repeat
    EventID = WaitWindowEvent()
    
  Until EventID = #PB_Event_CloseWindow
EndIf
UnhookWindowsHookEx_(hhook)
End
Le debug renvoyant une valeur négative ou positive il est facile tout comme dans le code de nico, de calculer la valeur de déplacement.

Code : Tout sélectionner

Global EventId, hhook, Wheel

Procedure MouseProc(nCode, wParam, lParam)
  Protected *ms.MOUSEHOOKSTRUCT = lParam
  
  If wParam = #WM_MOUSEWHEEL
    If *ms\hwnd > 0
      Wheel + 1
    Else
      Wheel -1
    EndIf
    
    Debug Wheel
  Else
    
  EndIf  
EndProcedure

If OpenWindow(0, 0, 0, 300, 200, "Mouse hook example", #PB_Window_SystemMenu)
  
  hhook = SetWindowsHookEx_(#WH_MOUSE_LL, @MouseProc(), GetModuleHandle_(0), 0)
  Repeat
    EventID = WaitWindowEvent()
    
  Until EventID = #PB_Event_CloseWindow
EndIf
UnhookWindowsHookEx_(hhook)
End

Re: Hook de la roulette de souris...

Publié : mar. 03/déc./2013 16:14
par Fig
Je prend le code de Nico ... Merci à vous tous! Image

Re: Hook de la roulette de souris...

Publié : mar. 03/déc./2013 16:21
par Fig
Par contre, Nico, ton code ne bloque pas la roulette pour les autres applications... :?

(Oui, je sais je suis pénible...)

Re: Hook de la roulette de souris...

Publié : mar. 03/déc./2013 23:04
par nico
Il faut renvoyer 1 dans le hook lorsque tu ne souhaites pas que le message soit envoyé à la fenêtre de destination; ici si la fenêtre qui a le focus n'est pas notre application, le message n'est pas envoyé.

@Falsam: attention MOUSEHOOKSTRUCT est une structure à utiliser avec un hook WH_MOUSE et non WH_MOUSE_LL, de plus il est nécessaire de tester nCode tel que recommandé dans la doc MSDN.

Code : Tout sélectionner

Global hhkLLMouse.i

Structure MSLLHOOKSTRUCT
  pt.POINT
  DmouseData.l
  flags.l
  time.l
  CompilerIf #PB_Compiler_Processor = #PB_Processor_x64
    PB_Alignment.b[4]
  CompilerEndIf
  dwExtraInfo.i
EndStructure


Procedure MouseKeyHook(nCode.l, wParam.i, lParam.i)
  Protected *pointer.MSLLHOOKSTRUCT = lparam
  
  If ncode = #HC_ACTION
    Select wParam
      Case #WM_MOUSEWHEEL
        Debug *pointer\DmouseData >>16
        If GetForegroundWindow_() <> WindowID(0)
          ProcedureReturn 1
        EndIf
        
    EndSelect
  EndIf 
  ProcedureReturn CallNextHookEx_(hhkLLMouse, nCode, wParam, lParam) 
  
EndProcedure 

OpenWindow(0, 0, 0, 240, 140, "Mouse Wheel", #WS_CAPTION|#WS_SYSMENU|1) 
StickyWindow(0,1) 

hhkLLMouse = SetWindowsHookEx_(#WH_MOUSE_LL, @MouseKeyHook(), GetModuleHandle_(0), 0) 

Repeat 
  Event = WaitWindowEvent() 
Until Event = #PB_Event_CloseWindow

UnhookWindowsHookEx_(hhkLLMouse)

Re: Hook de la roulette de souris...

Publié : mar. 03/déc./2013 23:50
par falsam
J'avoue que je me suis aventuré avec MOUSEHOOKSTRUCT. j'ai vu cette structure dans le lien que je cite plus haut et j'ai testé pour voir sans trop approfondir le sujet. Merci pour cette précision Nico. :)

Le décalage de bits (>>) est il utile ? Que l'on teste 7864320 ou -7864320 sans le décalage ou bien 120 ou - 120 avec le décalage ne change rien pour le calcul du déplacement de la molette.

Ceci dit, je vais adopter ta procédure moi aussi :)

Re: Hook de la roulette de souris...

Publié : mer. 04/déc./2013 0:05
par nico
Ben oui, il faut faire le décalage car les 16 bits de poids faible sont réservés (donc d'aucune utilité) et cette valeur pourrait changer au fil des versions et la valeur plus ou mois 120 est la valeur attendue qui correspond à la constante #WHEEL_DELTA mais en réalité la valeur peut être un multiple ou une division de 120, ainsi j'obtiens plus ou moins 240 en tournant rapidement la molette de la souris. La valeur 120 aurait été choisie apparemment pour faciliter les calculs, on peut la diviser facilement par 2,3,4, 5 ou 6.

Re: Hook de la roulette de souris...

Publié : mer. 04/déc./2013 0:22
par falsam
nico a écrit :j'obtiens plus ou moins 240 en tournant rapidement la molette de la souris.
ok je comprend mieux l'utilité de ce décalage. Il faut effectivement faire tourner rapidement la molette pour obtenir cette valeur de 240 ..... trop fatiguant :mrgreen:

Je vais en tenir compte pour calculer la valeur de déplacement de la molette.

Code : Tout sélectionner

Global hhkLLMouse.i, WheelDelta.i

Structure MSLLHOOKSTRUCT
  pt.POINT
  DmouseData.l
  flags.l
  time.l
  CompilerIf #PB_Compiler_Processor = #PB_Processor_x64
    PB_Alignment.b[4]
  CompilerEndIf
  dwExtraInfo.i
EndStructure


Procedure MouseKeyHook(nCode.l, wParam.i, lParam.i)
  Protected *pointer.MSLLHOOKSTRUCT = lparam
  
  If ncode = #HC_ACTION
    Select wParam
      Case #WM_MOUSEWHEEL
        If *pointer\DmouseData >> 16 >0
          WheelDelta + 1
        Else
          WheelDelta - 1
        EndIf
        
        Debug WheelDelta
        
        If GetForegroundWindow_() <> WindowID(0)
          ProcedureReturn 1
        EndIf
        
    EndSelect
  EndIf 
  ProcedureReturn CallNextHookEx_(hhkLLMouse, nCode, wParam, lParam) 
  
EndProcedure 

OpenWindow(0, 0, 0, 240, 140, "Mouse Wheel", #WS_CAPTION|#WS_SYSMENU|1) 
StickyWindow(0,1) 

hhkLLMouse = SetWindowsHookEx_(#WH_MOUSE_LL, @MouseKeyHook(), GetModuleHandle_(0), 0) 

Repeat 
  Event = WaitWindowEvent() 
Until Event = #PB_Event_CloseWindow

UnhookWindowsHookEx_(hhkLLMouse)
Pratique pour un calcul de zoom :)

Re: Hook de la roulette de souris...

Publié : mer. 04/déc./2013 10:29
par Fig
Merci pour ces explications très intéressantes concernant la manière d'utiliser proprement les apis. :idea: