Author Topic: A rudimentary version of SendKeys.  (Read 3491 times)

hutch--

  • Administrator
  • Member
  • ******
  • Posts: 4808
  • Mnemonic Driven API Grinder
    • The MASM32 SDK
A rudimentary version of SendKeys.
« on: August 29, 2014, 06:20:36 PM »
I regularly use the old NT4 Winfile.exe and while it works well, it suffers one irksome problem, every time something resets the OS file settings, it changes my file view and settings which in turn means I have to make the 10 or so mouse clicks to reset them back to my preference. After the first billion times you get tired of the repetitive task so I have made a rudimentary tool that resets it back to my choice. The application of Winfile will be of no interest to many but the technique for sending keystrokes to an external app seems to work OK if you massage it slightly with some delays to accommodate timing issues with Explorer. This is the code.


; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
    include \masm32\include\masm32rt.inc
; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤


    SetAltKey MACRO
      call AltKeyOn
    ENDM

    ClearAltKey MACRO
      call AltKeyOff
    ENDM

    SendKey MACRO vkkey
      invoke KeySend,vkkey
    ENDM

    KeySend PROTO vkkey:BYTE

    .code

start:
   
; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤

    call main
    exit

; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤

main proc

    LOCAL wfh   :DWORD

  ; -------------------------------
  ; allow for any lag with Explorer
  ; -------------------------------
    invoke SleepEx,256,0

    mov wfh, rv(FindWindow,"WFS_Frame",0)       ; winfile class name
    invoke SetForegroundWindow, wfh

  ; ----------------------------
  ; Indicate Expandable Branches                ; fixed the comment error
  ; ----------------------------
    SetAltKey                       ; do the menu options
    SendKey VK_T
    SendKey VK_DOWN
    SendKey VK_DOWN
    SendKey VK_DOWN
    SendKey VK_DOWN
    SendKey VK_RETURN
    ClearAltKey                     ; turn the Alt key off
  ; ----------------------------
  ; set the View parameters
  ; ----------------------------
    SetAltKey                       ; do the menu options
    SendKey VK_V
    SendKey VK_DOWN
    SendKey VK_DOWN
    SendKey VK_DOWN
    SendKey VK_DOWN
    SendKey VK_DOWN
    SendKey VK_DOWN
    SendKey VK_RETURN
    ClearAltKey                     ; turn the Alt key off

    SendKey VK_SPACE                ; do the dialog options
    SendKey VK_DOWN
    SendKey VK_SPACE
    SendKey VK_RETURN
  ; ----------------------------
  ; by File Type
  ; ----------------------------
    SetAltKey                       ; do the menu options
    SendKey VK_V
    SendKey VK_DOWN
    SendKey VK_DOWN
    SendKey VK_DOWN
    SendKey VK_DOWN
    SendKey VK_DOWN
    SendKey VK_DOWN
    SendKey VK_DOWN
    SendKey VK_DOWN
    SendKey VK_DOWN
    SendKey VK_DOWN
    SendKey VK_DOWN
    SendKey VK_RETURN
    ClearAltKey                     ; turn the Alt key off

    SendKey VK_TAB                  ; do the dialog options
    SendKey VK_SPACE
    SendKey VK_DOWN
    SendKey VK_DOWN
    SendKey VK_DOWN
    SendKey VK_DOWN
    SendKey VK_SPACE
    SendKey VK_TAB
    SendKey VK_RETURN
  ; ----------------------------

    ret

main endp

; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤

AltKeyOn proc

    invoke keybd_event,VK_MENU,1,KEYEVENTF_EXTENDEDKEY or 0,0
    ret

AltKeyOn endp

; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤

AltKeyOff proc

    invoke keybd_event,VK_MENU,1,KEYEVENTF_EXTENDEDKEY or KEYEVENTF_KEYUP,0
    ret

AltKeyOff endp

; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤

KeySend proc vkkey:BYTE

    invoke keybd_event,vkkey,1,KEYEVENTF_EXTENDEDKEY or 0,0
    invoke keybd_event,vkkey,1,KEYEVENTF_EXTENDEDKEY or KEYEVENTF_KEYUP,0
  ; --------------------------------------------------------------------
  ; delay is so the sent keys do not get in front of the keyboard buffer.
  ; --------------------------------------------------------------------
    invoke SleepEx,32,0

    ret

KeySend endp

; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤

end start
« Last Edit: August 30, 2014, 01:25:53 AM by hutch-- »
hutch at movsd dot com
http://www.masm32.com    :biggrin:  :biggrin:

Gunther

  • Member
  • *****
  • Posts: 3515
  • Forgive your enemies, but never forget their names
Re: A rudimentary version of SendKeys.
« Reply #1 on: August 29, 2014, 06:57:30 PM »
Steve,

I regularly use the old NT4 Winfile.exe and while it works well, it suffers one irksome problem, every time something resets the OS file settings, it changes my file view and settings which in turn means I have to make the 10 or so mouse clicks to reset them back to my preference. After the first billion times you get tired of the repetitive task so I have made a rudimentary tool that resets it back to my choice. The application of Winfile will be of no interest to many but the technique for sending keystrokes to an external app seems to work OK if you massage it slightly with some delays to accommodate timing issues with Explorer. This is the code.

cool. :t Well done.

Gunther
Get your facts first, and then you can distort them.

jj2007

  • Member
  • *****
  • Posts: 7542
  • Assembler is fun ;-)
    • MasmBasic
Re: A rudimentary version of SendKeys.
« Reply #2 on: August 29, 2014, 10:31:22 PM »
Hutch,

The source doesn't assemble, there is a serious bug in line 36. Maybe somebody can find out how to fix it ::)

Would be nice to add SendKeys to Masm32. I had something using a lot of Win32 stuff (GetWindowThreadProcessId, GetCurrentThreadId, AttachThreadInput, SetKeyboardState, SendMessage(WM_KEYDOWN, WM_KEYUP), SetKeyboardState, AttachThreadInput, ...) but I can't get it to work any more :(

Gunther

  • Member
  • *****
  • Posts: 3515
  • Forgive your enemies, but never forget their names
Re: A rudimentary version of SendKeys.
« Reply #3 on: August 30, 2014, 12:12:30 AM »
Jochen,

Hutch,

The source doesn't assemble, there is a serious bug in line 36. Maybe somebody can find out how to fix it ::)

no, assembles fine here. But you have to change the BASIC comments (') in lines 35 - 37 into valid assembly language comments [;]. No big deal.

Gunther
Get your facts first, and then you can distort them.

jj2007

  • Member
  • *****
  • Posts: 7542
  • Assembler is fun ;-)
    • MasmBasic
Re: A rudimentary version of SendKeys.
« Reply #4 on: August 30, 2014, 12:20:31 AM »
no, assembles fine here. But you have to change the BASIC comments (') in lines 35 - 37 into valid assembly language comments [;]. No big deal.

Gunther,

Strange, in the BASIC dialect that I use all the time, ";" is the comment character :P

So, did you do some tests with SendKeys already?

hutch--

  • Administrator
  • Member
  • ******
  • Posts: 4808
  • Mnemonic Driven API Grinder
    • The MASM32 SDK
Re: A rudimentary version of SendKeys.
« Reply #5 on: August 30, 2014, 01:24:48 AM »
Sorry about the error, I prototyped it in PowerBASIC then converted it to MASM. I had it working but added the comments after getting it going. I only tested it on menus and it was fussy about how you sent the VK_MENU, if you did not turn it off with a corresponding call, it messed up the OS keyboard on my Win7 64 and I had to reboot the box to fix it.

The technique appears to be highly sensitive to asynchronous timing so I went the path of adding delay between each call to keybd_event to try and get it to be consistent.

LATER :

This seems to work on my Win7 64. The original test piece was to tweak the menu on Winfile, putting plain text into Notepad is a simpler task.


    mov wfh, rv(FindWindow,"Notepad",0)       ; notepad class name
    invoke SetForegroundWindow, wfh

    invoke keybd_event,VK_T,1,0,0
    invoke keybd_event,VK_H,1,0,0
    invoke keybd_event,VK_I,1,0,0
    invoke keybd_event,VK_S,1,0,0
hutch at movsd dot com
http://www.masm32.com    :biggrin:  :biggrin:

hutch--

  • Administrator
  • Member
  • ******
  • Posts: 4808
  • Mnemonic Driven API Grinder
    • The MASM32 SDK
Re: A rudimentary version of SendKeys.
« Reply #6 on: August 30, 2014, 03:41:32 AM »
Give this a blast if you have the time. The macros seem to be more consistent than the procs I used in the first test piece.


; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
    include \masm32\include\masm32rt.inc
; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤

  ; ------
  ; macros
  ; ------
    ExtKeyDown MACRO vkkey
      invoke keybd_event,vkkey,1,KEYEVENTF_EXTENDEDKEY or 0,0
    ENDM

    ExtKeyUp MACRO vkkey
      invoke keybd_event,vkkey,1,KEYEVENTF_EXTENDEDKEY or KEYEVENTF_KEYUP,0
    ENDM

    SendKeyDn MACRO vkkey
      invoke keybd_event,vkkey,1,0,0
    ENDM

    SendKeyUp MACRO vkkey
      invoke keybd_event,vkkey,1,KEYEVENTF_KEYUP or 0,0
    ENDM

    delay MACRO duration
      invoke SleepEx,duration,0
    ENDM

    .code

start:
   
; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤

    call main
    exit

; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤

main proc

    LOCAL hApp   :DWORD

  ; -------------------------------
  ; allow for any lag with Explorer
  ; -------------------------------
    delay 256

    mov hApp, rv(FindWindow,"Notepad",0)       ; notepad class name
    .if hApp == 0
      fn WinExec,"notepad.exe",1
      mov hApp, rv(FindWindow,"Notepad",0)     ; notepad class name
    .endif

    invoke SetForegroundWindow, hApp

    SendKeyDn VK_SHIFT
    SendKeyDn VK_T
    SendKeyUp VK_SHIFT

    SendKeyDn VK_H
    SendKeyDn VK_I
    SendKeyDn VK_S
    SendKeyDn VK_SPACE
    SendKeyDn VK_I
    SendKeyDn VK_S
    SendKeyDn VK_SPACE
    SendKeyDn VK_A
    SendKeyDn VK_SPACE
    SendKeyDn VK_T
    SendKeyDn VK_E
    SendKeyDn VK_S
    SendKeyDn VK_T
    SendKeyDn VK_DECIMAL

    ExtKeyDown VK_MENU      ; if you use this key
    SendKeyDn VK_F          ; File Menu
    ExtKeyUp VK_MENU        ; make sure you reverse it later
    SendKeyDn VK_A          ; hot key "A"

    ret

main endp

; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤

end start
hutch at movsd dot com
http://www.masm32.com    :biggrin:  :biggrin:

jj2007

  • Member
  • *****
  • Posts: 7542
  • Assembler is fun ;-)
    • MasmBasic
Re: A rudimentary version of SendKeys.
« Reply #7 on: August 30, 2014, 04:18:49 AM »
This is a test.a

My version of Notepad is Italian, but Alt F Alt A does normally open something useful (File/Apri).

Gunther

  • Member
  • *****
  • Posts: 3515
  • Forgive your enemies, but never forget their names
Re: A rudimentary version of SendKeys.
« Reply #8 on: August 30, 2014, 04:23:18 AM »
Jochen,

Strange, in the BASIC dialect that I use all the time, ";" is the comment character :P

that won't work.  :lol:

So, did you do some tests with SendKeys already?

I'll give the macro version a try. It seems to work in the right way.

Gunther
Get your facts first, and then you can distort them.

hutch--

  • Administrator
  • Member
  • ******
  • Posts: 4808
  • Mnemonic Driven API Grinder
    • The MASM32 SDK
Re: A rudimentary version of SendKeys.
« Reply #9 on: August 31, 2014, 02:04:20 AM »
I have just fiddled the macros to add an optional millisecond delay for each item, it seems to be useful due to the asynchronous nature of calling an external app. The test piece is a simple console stuffing a few command line commands into the console and running them but it does demonstrate how the system works. NOTE that the example is for a US English keyboard and a couple of the OEM keys may not work on a non-US English keyboard but this would normally be the case with language and keyboard differences. Each language and keyboard would require its own set of virtual keys for the non common keys or characters.


; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
                                include \masm32\include\masm32rt.inc
; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤

  ; ------
  ; macros
  ; ------
    ExtKeyDown MACRO vkkey:REQ,timing:=<0>
      invoke keybd_event,vkkey,1,KEYEVENTF_EXTENDEDKEY or 0,0
      IF timing ne 0
        invoke SleepEx,timing,0
      ENDIF

    ENDM

    ExtKeyUp MACRO vkkey:REQ,timing:=<0>
      invoke keybd_event,vkkey,1,KEYEVENTF_EXTENDEDKEY or KEYEVENTF_KEYUP,0
      IF timing ne 0
        invoke SleepEx,timing,0
      ENDIF
    ENDM

    SendKeyDn MACRO vkkey:REQ,timing:=<0>
      invoke keybd_event,vkkey,1,0,0
      IF timing ne 0
        invoke SleepEx,timing,0
      ENDIF
    ENDM

    SendKeyUp MACRO vkkey:REQ,timing:=<0>
      invoke keybd_event,vkkey,1,KEYEVENTF_KEYUP or 0,0
      IF timing ne 0
        invoke SleepEx,timing,0
      ENDIF
    ENDM

    delay MACRO duration
      invoke SleepEx,duration,0
    ENDM

    .code

start:
   
; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤

    call main
    exit

; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤

main proc

    fn WinExec,"cmd.exe",SW_SHOW

  ; -------------------------------
  ; allow for any lag with Explorer
  ; -------------------------------
    delay 256

    invoke SetForegroundWindow, rv(FindWindow,"ConsoleWindowClass",0)

  ; ***********************************************************
  ; The keys used are valid for a US English keyboard,
  ; they may not be for keyboards laid out for other languages.
  ; ***********************************************************

  ; ------------------------
  ; change drive to drive c:
  ; ------------------------
    SendKeyDn VK_C
    SendKeyDn VK_SHIFT
    SendKeyDn VK_OEM_1          ; OEM key ":"
    SendKeyUp VK_SHIFT
    SendKeyDn VK_RETURN, 1000

  ; ----------------------------
  ; change to the root directory
  ; ----------------------------
    SendKeyDn VK_C
    SendKeyDn VK_D
    SendKeyDn VK_SPACE
    SendKeyDn VK_OEM_102        ; OEM key "\"
    SendKeyDn VK_RETURN, 1000

    SendKeyDn VK_C
    SendKeyDn VK_L
    SendKeyDn VK_S
    SendKeyDn VK_RETURN, 1000

  ; ------------------------
  ; run the command "dir /w"
  ; ------------------------
    SendKeyDn VK_D
    SendKeyDn VK_I
    SendKeyDn VK_R
    SendKeyDn VK_SPACE
    SendKeyDn VK_DIVIDE         ; forward slash "/"
    SendKeyDn VK_W
    SendKeyDn VK_RETURN, 1000

    ret

main endp

; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤

end start
hutch at movsd dot com
http://www.masm32.com    :biggrin:  :biggrin:

rrr314159

  • Member
  • *****
  • Posts: 1381
Re: A rudimentary version of SendKeys.
« Reply #10 on: February 23, 2015, 09:24:46 AM »
Cool! :t
I am NaN ;)