Wait for time elapsed in a mouse hook?

Just starting out? Need help? Post your questions and find answers here.
forumuser
User
User
Posts: 98
Joined: Wed Apr 18, 2018 8:24 am

Wait for time elapsed in a mouse hook?

Post by forumuser »

Hi,

I'm using a low-level mouse hook to capture clicks and mouse movement in an external window.

The problem is that when a mouse button is pressed I need to measure the time how long it is pressed
and only do something when a specific amount of time is exceeded. This is a problem because there aren't
any new events firing if the mouse isn't moved during that period of time while the button is pressed.

Any hints on how this should be handled (and moving the mouse during that time isn't an option^^)?
User avatar
Josh
Addict
Addict
Posts: 1183
Joined: Sat Feb 13, 2010 3:45 pm

Re: Wait for time elapsed in a mouse hook?

Post by Josh »

forumuser wrote:low-level
Whitch OS?
sorry for my bad english
forumuser
User
User
Posts: 98
Joined: Wed Apr 18, 2018 8:24 am

Re: Wait for time elapsed in a mouse hook?

Post by forumuser »

Windows only.
JHPJHP
Addict
Addict
Posts: 2129
Joined: Sat Oct 09, 2010 3:47 am
Contact:

Re: Wait for time elapsed in a mouse hook?

Post by JHPJHP »

Hi forumuser,

Windows Services & Other Stuff
- \Other_Stuff\OtherStuff\GlobalMouseHook.pb
-- hold the left button down for 2+ seconds
-- left button down must occur over PB window (by design)
Last edited by JHPJHP on Sat Feb 16, 2019 5:20 pm, edited 1 time in total.
User avatar
Mijikai
Addict
Addict
Posts: 1360
Joined: Sun Sep 11, 2016 2:17 pm

Re: Wait for time elapsed in a mouse hook?

Post by Mijikai »

Heres my try :D

It fires an Event including the delay and mouse position
mapped to the window coordinates.

Code:

Code: Select all

EnableExplicit

DeclareModule MOUSEHOOK
  Declare.i Create(Window.i,EventId.i)
  Declare.i Destroy()
EndDeclareModule

Module MOUSEHOOK

  EnableExplicit
  
  Structure MSLLHOOKSTRUC
    StructureUnion
      pt.POINT
      ptq.q
    EndStructureUnion
    mouseData.l
    flags.l
    time.l
    *dwExtraInfo
  EndStructure
  
  Structure HOOK_STRUCT
    Handle.i
    Atom.i
    Event.i
    Clock.q
    StructureUnion
      pt.POINT
      ptq.q
    EndStructureUnion
  EndStructure
  
  Global Mutex.i = CreateMutex()
  Global Hook.HOOK_STRUCT
  
  Procedure.i Destroy()
    With Hook
      LockMutex(Mutex)
      If \Handle
        UnhookWindowsHookEx_(\Handle)
        \Handle = #Null
      EndIf
      UnlockMutex(Mutex)
    EndWith
  EndProcedure
  
  Procedure.i Hook(nCode.i,*wParam,*lParam.MSLLHOOKSTRUC)
    With Hook
      LockMutex(Mutex)
      If nCode = #HC_ACTION
        Select *wParam
          Case #WM_LBUTTONDOWN
            If WindowFromPoint_(*lParam\ptq) = \Atom
              \Clock = ElapsedMilliseconds()
              \ptq = *lParam\ptq
              MapWindowPoints_(#Null,\Atom,@\pt,1)
            EndIf
          Case #WM_MOUSEMOVE
            If \Clock
              \ptq = *lParam\ptq
            EndIf
          Case #WM_LBUTTONUP
            If \Clock
              \Clock = ElapsedMilliseconds() - \Clock
              PostEvent(\Event,\Clock,\ptq)
              \Clock = #Null
            EndIf
        EndSelect
      EndIf
      UnlockMutex(Mutex) 
      ProcedureReturn CallNextHookEx_(\Handle,nCode,*wParam,*lParam) 
    EndWith
  EndProcedure
  
  Procedure.i Create(WindowHandle.i,EventId.i)
    With Hook
      If Mutex
        LockMutex(Mutex)
        If \Handle
          UnhookWindowsHookEx_(\Handle)
          \Handle = #Null
        EndIf
        If EventId
          \Atom = WindowHandle
          \Event = EventId
          \Handle = SetWindowsHookEx_(#WH_MOUSE_LL,@Hook(),#Null,#Null)
          If \Handle
            UnlockMutex(Mutex)
            ProcedureReturn #True
          EndIf
        EndIf
        UnlockMutex(Mutex)
      EndIf
    EndWith
  EndProcedure
  
EndModule

Structure MOUSEPOS_STRUCT
  StructureUnion
    pt.POINT
    ptq.q
  EndStructureUnion
EndStructure

Global MousePos.MOUSEPOS_STRUCT

If OpenWindow(0,0,0,400,400, "Global Mouse Hook",#PB_Window_SystemMenu|#PB_Window_ScreenCentered)
  If MOUSEHOOK::Create(WindowID(0),#PB_Event_FirstCustomValue)
    Repeat
      Select WaitWindowEvent()
        Case #PB_Event_FirstCustomValue
          Debug "Delay: " + Str(EventWindow()) + " ms"
          MousePos\ptq = EventGadget()
          Debug "Pos: " + Str(MousePos\pt\x) + " x " + Str(MousePos\pt\y)
        Case #PB_Event_CloseWindow
          Break
      EndSelect
    ForEver
    MOUSEHOOK::Destroy()
  EndIf
  CloseWindow(0)  
EndIf

End
Last edited by Mijikai on Sat Feb 16, 2019 12:52 pm, edited 1 time in total.
forumuser
User
User
Posts: 98
Joined: Wed Apr 18, 2018 8:24 am

Re: Wait for time elapsed in a mouse hook?

Post by forumuser »

Thanks a lot for the example codes (and the help ofc), guys!

@JHPJHP
The created thread doesn't need any locks, because it never writes
anything into anything (e.g. variable assigned to a structure), right?


@Mijikai
In the Hook procedure you're using:

Code: Select all

      ProcedureReturn CallNextHookEx_(\Handle,nCode,*wParam,*lParam)
      UnlockMutex(Mutex)
I guess UnlockMutex(Mutex) won't ever be reached, will it?
User avatar
Mijikai
Addict
Addict
Posts: 1360
Joined: Sun Sep 11, 2016 2:17 pm

Re: Wait for time elapsed in a mouse hook?

Post by Mijikai »

@forumuser thx i fixed it.
Post Reply