WinBatch® Technical Support Forum

All Things WinBatch => WinBatch => Topic started by: USMuscle on October 18, 2016, 04:00:50 PM

Title: Continuous Holding Keys Down
Post by: USMuscle on October 18, 2016, 04:00:50 PM
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.
Title: Re: Continuous Holding Keys Down
Post by: td on October 19, 2016, 10:46:51 AM
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 (http://techsupt.winbatch.com/webcgi/webbatch.exe?techsupt/nftechsupt.web+WinBatch/Sending~Keystrokes+Send~Fn~key~on~a~Notebook.txt)
Title: Re: Continuous Holding Keys Down
Post by: 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)
Title: Re: Continuous Holding Keys Down
Post by: td on October 19, 2016, 03:39:34 PM
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.
Title: Re: Continuous Holding Keys Down
Post by: USMuscle on October 20, 2016, 07:58:43 AM
Thank you. I now have stuff to experiment with.  :D
Title: Re: Continuous Holding Keys Down
Post by: USMuscle on October 20, 2016, 10:43:12 AM
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)

Title: Re: Continuous Holding Keys Down
Post by: td on October 20, 2016, 12:59:33 PM
It doesn't matter:  #endfunction or #endsubroutine will work with either #definefunction or #definesubroutine.