Continuous Holding Keys Down

Started by USMuscle, October 18, 2016, 04:00:50 PM

Previous topic - Next topic

USMuscle

I know how the SendKeys functions work in the traditional sense of hotkey applications, but is there a way to hold keys down for specified amount of time? For example, I want to hold some keys down while an executable is being run. Any ideas?

Thanks in advance.

td

The article pointed to by the link below along with a bit of research, critical thinking and scripting could provide a solution:

http://techsupt.winbatch.com/webcgi/webbatch.exe?techsupt/nftechsupt.web+WinBatch/Sending~Keystrokes+Send~Fn~key~on~a~Notebook.txt
"No one who sees a peregrine falcon fly can ever forget the beauty and thrill of that flight."
  - Dr. Tom Cade

td

A limited and rough example:

Code (winbatch) Select
#DefineFunction GetVirualKeyScanCode( nVirtualKey )
   nScanCode = DllCall("user32.dll", long:"MapVirtualKeyA", long:nVirtualKey, long:0)
   Return nScanCode
#EndSubRoutine

#DefineFunction SendKeyInput( strKey, strState )
   
   ; Flag member values
   INPUT_KEYBOARD        = 1
   KEYEVENTF_EXTENDEDKEY = 1  ; Causes a 0xE0 to be sent ahead of the key                             
   KEYEVENTF_KEYUP       = 2
   KEYEVENTF_SCANCODE    = 8

   ; INPUT structure descriptor.
   strInput = $"DWORD::type
WORD::wVk
WORD::wScan
DWORD::dwFlags
DWORD::time
LONG_PTR::dwExtraInfo
DWORD::Padding1
DWORD::Padding2$" ; 8 byte padding necessary because structure contains a union.

   hInput = DllStructAlloc(strInput)
   DllStructPoke(hInput, 'type', INPUT_KEYBOARD)
   
   ; Assume are ANSI key with same virtual key code.
   nVk = Char2Num(StrUpper(strKey))
   DllStructPoke(hInput, 'wVk', nVk)
   DllStructPoke(hInput, 'wScan', 0) ;GetVirualKeyScanCode(nVk))
   if StriCmp(strState, 'UP')
      DllStructPoke(hInput, 'dwFlags', KEYEVENTF_KEYUP) ;|KEYEVENTF_SCANCODE
   else
      DllStructPoke(hInput, 'dwFlags', 0) ;KEYEVENTF_SCANCODE)
   endif
   DllStructPoke(hInput, 'time', 0)
   DllStructPoke(hInput, 'dwExtraInfo', 0)
   

   ; Do the deed.
   dwSize = IntControl(98, hInput, 1, 0, 0)
   nResult = DllCall("user32.dll", long:"SendInput", long:1, lpstruct:hInput, long:dwSize)

   ; Clean up
   DllStructFree(hInput)

   Return nResult ; 0 on failure otherwise number of inputs.
#EndFunction

; Key down for one second
nResult1 = SendKeyInput('H', 'down')
TimeDelay(1)
nResult2 = SendKeyInput('H', 'up')

If nResult1 && nResult2
   sText = "Success"
Else
   sText = "Failure"
EndIf
Message("SendKey Test", sText)
"No one who sees a peregrine falcon fly can ever forget the beauty and thrill of that flight."
  - Dr. Tom Cade

td

Neglected to mention that most systems are set to begin repeating a key down and up press after a key has been physically held down for a predetermined time.  If that is the end goal then the SendKey function's repeat key feature can be used instead of using DllCall on the Win32 'SendInput' function.
"No one who sees a peregrine falcon fly can ever forget the beauty and thrill of that flight."
  - Dr. Tom Cade

USMuscle

Thank you. I now have stuff to experiment with.  :D

USMuscle

I noticed in the code you supplied below that the first DefineFunction is closed with an EndSubRoutine. Forgive my ignorance, but I thought a DefineFunction is supposed to be closed with an EndFunction, and a DefineSubroutine is supposed to be closed by an EndSubRoutine. Am I wrong?
Quote from: td on October 19, 2016, 03:11:28 PM
A limited and rough example:

Code (winbatch) Select
#DefineFunction GetVirualKeyScanCode( nVirtualKey )
   nScanCode = DllCall("user32.dll", long:"MapVirtualKeyA", long:nVirtualKey, long:0)
   Return nScanCode
#EndSubRoutine

#DefineFunction SendKeyInput( strKey, strState )
   
   ; Flag member values
   INPUT_KEYBOARD        = 1
   KEYEVENTF_EXTENDEDKEY = 1  ; Causes a 0xE0 to be sent ahead of the key                             
   KEYEVENTF_KEYUP       = 2
   KEYEVENTF_SCANCODE    = 8

   ; INPUT structure descriptor.
   strInput = $"DWORD::type
WORD::wVk
WORD::wScan
DWORD::dwFlags
DWORD::time
LONG_PTR::dwExtraInfo
DWORD::Padding1
DWORD::Padding2$" ; 8 byte padding necessary because structure contains a union.

   hInput = DllStructAlloc(strInput)
   DllStructPoke(hInput, 'type', INPUT_KEYBOARD)
   
   ; Assume are ANSI key with same virtual key code.
   nVk = Char2Num(StrUpper(strKey))
   DllStructPoke(hInput, 'wVk', nVk)
   DllStructPoke(hInput, 'wScan', 0) ;GetVirualKeyScanCode(nVk))
   if StriCmp(strState, 'UP')
      DllStructPoke(hInput, 'dwFlags', KEYEVENTF_KEYUP) ;|KEYEVENTF_SCANCODE
   else
      DllStructPoke(hInput, 'dwFlags', 0) ;KEYEVENTF_SCANCODE)
   endif
   DllStructPoke(hInput, 'time', 0)
   DllStructPoke(hInput, 'dwExtraInfo', 0)
   

   ; Do the deed.
   dwSize = IntControl(98, hInput, 1, 0, 0)
   nResult = DllCall("user32.dll", long:"SendInput", long:1, lpstruct:hInput, long:dwSize)

   ; Clean up
   DllStructFree(hInput)

   Return nResult ; 0 on failure otherwise number of inputs.
#EndFunction

; Key down for one second
nResult1 = SendKeyInput('H', 'down')
TimeDelay(1)
nResult2 = SendKeyInput('H', 'up')

If nResult1 && nResult2
   sText = "Success"
Else
   sText = "Failure"
EndIf
Message("SendKey Test", sText)


td

It doesn't matter:  #endfunction or #endsubroutine will work with either #definefunction or #definesubroutine.   
"No one who sees a peregrine falcon fly can ever forget the beauty and thrill of that flight."
  - Dr. Tom Cade