Passing a keyboard character to MSFS 2020

Hi All!

I have been wanting to create a window that allows me to send a keystroke over to MSFS 2020 Flying Simulator and I think I am close. Any ideas what I am missing?

I want to code this program by hand and am not willing to use templates or any other outside tools.

Thanks for your help!

  PROGRAM

  INCLUDE('KEYCODES')
  INCLUDE('svapi.inc') ,ONCE
  MAP
    INCLUDE('svapifnc.inc') ,ONCE
    INCLUDE('CWUTIL.INC')
  END
!===============================================================================
MSFS               LONG
STATUS             LONG
!===============================================================================
  CODE
  MSFS = WINDOWEXISTS('Microsoft Flight Simulator')
  IF MSFS
    STATUS = SENDMESSAGE(MSFS,WM_SETTEXT,GKEY,WM_NULL) !PASS "G" FOR LANDING GEAR
    STOP(STATUS) !IS ALWAYS RETURNING 0
  END
1 Like

You made my day better.

1 Like

I think you need to PostMessage() using WM_KeyDown WM_KeyUp. Google that. In VB6 was there was SendKeys() that did not always work so well so you can find VB6 examples of replacing that with API calls.

1 Like

Thanks, Carl! I was looking at that also.

As a side note, I also use PureBasic in weird situations like this when you need a different wrench…

I may consider creating a stand-alone exe that I pass the name of the window and keyboard-key too and PureBasic does it that way. It is always better to have Dewalt and Craftsman tools readily available!

If I get easy success with PB I will post the code here too.

Yup, as I expected.

PB is a little easier to use when it comes to doing resident WinAPI calls. I still may consider re-writing this into my Clarion exe, but as you can see below it will be very easy to pass two command line parameters ("sendkeys.exe “Microsoft Flight Simulator” “{SHIFTDOWN}G{SHIFTUP}”) into a PB SendKeys.exe and it does the rest of the work.

PB Code:

Procedure SendKeys(handle,window$,keys$)
    If window$<>"" : handle=FindWindow_(0,window$) : EndIf                                            ; Use window$ instead of handle.
    If IsWindow_(handle)=0                                                                            ; Does the target window actually exist?
        ProcedureReturn #False                                                                             ; Nope, so report 0 for failure to type.
    Else
        ; This block gives the target window the focus before typing.
        thread1=GetWindowThreadProcessId_(GetForegroundWindow_(),0)
        thread2=GetWindowThreadProcessId_(handle,0)
        If thread1<>thread2 : AttachThreadInput_(thread1,thread2,#True) : EndIf
        SetForegroundWindow_(handle)                                                                  ; Target window now has the focus for typing.
        Delay(125)                                                                                    ; 1/8 second pause before typing, to prevent fast CPU problems.
        
        ; Now the actual typing starts.
        For r=1 To Len(keys$)
          vk$=Mid(keys$,r,1)
          If vk$="{"                                                                                  ; Special key found.
            s=FindString(keys$,"}",r+1)-(r+1)                                                         ; Get length of special key.
            s$=Mid(keys$,r+1,s)                                                                       ; Get special key name.
            notakey=#False
            Select s$                                                                                 ; Get virtual key code of special key.
              Case "ALTDOWN"      : alted = 1 :   keybd_event_(#VK_MENU,0,0,0)                        ; Hold ALT down.
              Case "ALTUP"        : alted = 0 :   keybd_event_(#VK_MENU,0,#KEYEVENTF_KEYUP,0)         ; Release ALT.
              Case "BACKSPACE"    : vk=#VK_BACK
              Case "CONTROLDOWN"  : ctrled = 1 :  keybd_event_(#VK_CONTROL,0,0,0)                     ; Hold CONTROL down.
              Case "CONTROLUP"    : ctrled = 0 :  keybd_event_(#VK_CONTROL,0,#KEYEVENTF_KEYUP,0)      ; Release CONTROL.
              Case "DELETE"       : vk=#VK_DELETE
              Case "DOWN"         : vk=#VK_DOWN
              Case "END"          : vk=#VK_END
              Case "ENTER"        : vk=#VK_RETURN
              Case "F1"           : vk=#VK_F1
              Case "F2"           : vk=#VK_F2
              Case "F3"           : vk=#VK_F3
              Case "F4"           : vk=#VK_F4
              Case "F5"           : vk=#VK_F5
              Case "F6"           : vk=#VK_F6
              Case "F7"           : vk=#VK_F7
              Case "F8"           : vk=#VK_F8
              Case "F9"           : vk=#VK_F9
              Case "F10"          : vk=#VK_F10
              Case "F11"          : vk=#VK_F11
              Case "F12"          : vk=#VK_F12
              Case "ESCAPE"       : vk=#VK_ESCAPE
              Case "HOME"         : vk=#VK_HOME
              Case "INSERT"       : vk=#VK_INSERT
              Case "LEFT"         : vk=#VK_LEFT
              Case "PAGEDOWN"     : vk=#VK_NEXT
              Case "PAGEUP"       : vk=#VK_PRIOR
              Case "PRINTSCREEN"  : vk=#VK_SNAPSHOT
              Case "RETURN"       : vk=#VK_RETURN
              Case "RIGHT"        : vk=#VK_RIGHT
              Case "SHIFTDOWN"    : shifted=1 :    keybd_event_(#VK_SHIFT,0,0,0)                      ; Hold SHIFT down.
              Case "SHIFTUP"      : shifted=0 :    keybd_event_(#VK_SHIFT,0,#KEYEVENTF_KEYUP,0)       ; Release SHIFT.
              Case "TAB"          : vk=#VK_TAB
              Case "UP"           : vk=#VK_UP
              Default
                notakey = #True
            EndSelect
            If notakey=#False
              If Left(s$,3)<>"ALT" And Left(s$,7)<>"CONTROL" And Left(s$,5)<>"SHIFT"
                keybd_event_(vk,0,0,0) : keybd_event_(vk,0,#KEYEVENTF_KEYUP,0)                        ; Press the special key.
              EndIf
              r=r+s+1                                                                                 ; Continue getting the keystrokes that follow the special key.
            Else
              vk=VkKeyScanEx_(Asc(vk$),GetKeyboardLayout_(0))                                         ; Normal key found
              keybd_event_(vk,0,0,0) : keybd_event_(vk,0,#KEYEVENTF_KEYUP,0)                          ; Press the normal key.
            EndIf
          Else
            
            ;LoadKeyboardLayout_("000040c",#KLF_ACTIVATE|#KLF_REORDER)
            vk=VkKeyScanEx_(Asc(vk$),GetKeyboardLayout_(0))                                           ; Normal key found
            If (vk&$0100)<>0 And shifted = 0 : keybd_event_(#VK_SHIFT,0,0,0) : EndIf                  ; Due to shifted character.
            If (vk&$0200)<>0 And ctrled = 0 :  keybd_event_(#VK_CONTROL,0,0,0) : EndIf
            If (vk&$0400)<>0 And alted = 0 :   keybd_event_(#VK_MENU,0,0,0) : EndIf
            
            keybd_event_(vk,0,0,0) : keybd_event_(vk,0,#KEYEVENTF_KEYUP,0)                            ; Press the normal key.
            
            If (vk&$0100)<>0 And shifted = 0 : keybd_event_(#VK_SHIFT,0,#KEYEVENTF_KEYUP,0) : EndIf   ; Due to shifted character.
            If (vk&$0200)<>0 And ctrled = 0  : keybd_event_(#VK_CONTROL,0,#KEYEVENTF_KEYUP,0) : EndIf
            If (vk&$0400)<>0 And alted = 0   : keybd_event_(#VK_MENU,0,#KEYEVENTF_KEYUP,0) : EndIf
          EndIf
        Next

        If thread1<>thread2 : AttachThreadInput_(thread1,thread2,#False) : EndIf                      ; Finished typing to target window!
        keybd_event_(#VK_MENU,0,#KEYEVENTF_KEYUP,0)                                                   ; Release ALT key if user forgot.
        keybd_event_(#VK_CONTROL,0,#KEYEVENTF_KEYUP,0)                                                ; Release CONTROL key if user forgot.
        keybd_event_(#VK_SHIFT,0,#KEYEVENTF_KEYUP,0)                                                  ; Release SHIFT key if user forgot.
        ProcedureReturn #True                                                                         ; Report successful typing! :)
    EndIf
  EndProcedure
  
;Test using an open NotePad.exe  
w$="Untitled - Notepad"                                                                               ; Specifies target window name.

SendKeys(0,w$,"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ\\\///___----[[[")                 ; Type some dummy text.
SendKeys(0,w$,"{CONTROLDOWN}a{CONTROLUP}") ; Select it all.
SendKeys(0,w$,"{DELETE}")                                                                             ; Delete it.