Page 1 of 1

Sense last key entry on computer, without program being active.

Posted: Sat Feb 17, 2024 11:18 pm
by matalog
I have a program that senses mouse movements via

Code: Select all

  XM=DesktopMouseX()
  YM=DesktopMouseY()
That will sense and mouse movement in any program run on my computer wether the PB program is active, selected or not.

Is there a similar command for a keyboard last key press in any program, you know, the last key that was pressed while the PB program is running but not necessarily the active window?

Re: Sense last key entry on computer, without program being active.

Posted: Sun Feb 18, 2024 12:35 am
by idle
windows

Code: Select all

;-Keyboardhook 
  Structure akey
    ks.a[256]
  EndStructure   
   
  Procedure ProcessKeys(key.s,back=0)  
    
    Debug key 
      
  EndProcedure   
    
  Procedure.i KeyProc(nCode.l,wParam.l,lParam.l)
    
    Protected *keyInput.KBDLLHOOKSTRUCT 
    Static keys.akey 
    Static pos,len  
        
    Protected ret.i, hwnd.i,thwnd.i 
    Protected rs.s=Space(2) 
    Protected doc 
    
    ret = CallNextHookEx_(myKeyhook, nCode, wParam, lParam) 
    
    *keyInput = lParam 
    
    If nCode = #HC_ACTION 
      
      hwnd = GetForegroundWindow_()
          
        Select wParam  
            
          Case #WM_KEYUP
                                 
            keys\ks[*keyInput\vkCode]= $fe
            
            If (GetAsyncKeyState_(#VK_SHIFT) & $8000)  
              keys\ks[#VK_SHIFT]=$fe
            EndIf 
            
            If (GetAsyncKeyState_(#VK_CONTROL) & $8000)  
              keys\ks[#VK_CONTROL]=$fe
            EndIf 
            
            If (GetAsyncKeyState_(#VK_LMENU) & $8000)  
              keys\ks[#VK_LMENU]=$fe
            EndIf 
            
            If (GetAsyncKeyState_(#VK_RMENU) & $8000)  
              keys\ks[#VK_RMENU]=$fe
            EndIf 
            
            If (keys\ks[#VK_ESCAPE] = 0 And keys\ks[#VK_LBUTTON] = 0)
            
              If ToUnicode_(*keyInput\vkCode,*keyInput\scanCode,@keys,@rs,1,2) 
                 ProcessKeys(rs,keys\ks[#VK_BACK])              
              EndIf   
            
            EndIf 
            
            keys\ks[*keyInput\vkCode]=0
            keys\ks[#VK_SHIFT]=0
            keys\ks[#VK_CONTROL]=0
            keys\ks[#VK_LMENU]=0
            keys\ks[#VK_RMENU]=0
            
        EndSelect
       
    EndIf    
    
    ProcedureReturn ret
    
  EndProcedure 
  
  Procedure SetHooks(hInstance=0)
    If hInstance = 0 
      hInstance = GetModuleHandle_(0)
    EndIf 
    If hInstance 
      myKeyhook = SetWindowsHookEx_(#WH_KEYBOARD_LL, @KeyProc(),hInstance,0) 
    Else 
      MessageRequester("hook", "can't get module handle")
    EndIf       
    
  EndProcedure 
  
  Procedure KillHooks()
    UnhookWindowsHookEx_(myKeyhook)
    myKeyHook = 0  
  EndProcedure 
  
  OpenWindow(0,0,0,100,60,"Hook") 
  SetHooks() 
  Repeat 
  Until WaitWindowEvent() = #PB_Event_CloseWindow 
  KillHooks() 

Re: Sense last key entry on computer, without program being active.

Posted: Sun Feb 18, 2024 1:59 am
by matalog
Thanks for that, I'll examine it and see what it uses.

To be clear, I really just want to see if any key has been pressed, that is, if the user is using the keyboard. Does that make it easier?

Re: Sense last key entry on computer, without program being active.

Posted: Sun Feb 18, 2024 2:28 pm
by Rinzwind
Mind you, that method does not handle (and kills) 'dead keys (ie US-International keyboard layout)'. Press ' and e to produce é or " and e to get ë.

Re: Sense last key entry on computer, without program being active.

Posted: Sun Feb 18, 2024 4:12 pm
by infratec
Use my GetIdleTime() procedure :wink:

https://www.purebasic.fr/english/viewtopic.php?p=615663

It tells you when the last input was done. Mouse or keyboard.

Re: Sense last key entry on computer, without program being active.

Posted: Sun Feb 18, 2024 7:48 pm
by matalog
Thanks everyone. Infratec GetIdelTime() is perfect.