Question

Following along with (http://win32com.goermezer.de/content/view/136/254/) I was able to load up a program, gain focus on the program, however I'm not able to send actual keys into the emulation, it's like it's sending to the window and not inside the emulation.

The bit of code that I am using goes like:

import win32com.client
shell = win32com.client.Dispatch("WScript.Shell")
shell.Run("Silver.gbc")
shell.AppActivate("VisualBoyAdvance")
shell.SendKeys("{DOWN}")

Which all works until I try and send {DOWN}, I have also tried "z" and it won't send inside of the window, even though it sends fine to any other application. Any ideas? Thanks in advance.

Was it helpful?

Solution

Problem was that SendKey isn't compatible with Direct Input, to get past this I used win32api's keybd_event for direct input

VK_CODE = {
    'backspace':0x08
}

def press(*args):
    '''
    press, release
    eg press('x', 'y', 'z')
    '''
    for i in args:
        win32api.keybd_event(VK_CODE[i], 0, 0, 0)
        time.sleep(0.2)
        win32api.keybd_event(VK_CODE[i],0 ,win32con.KEYEVENTF_KEYUP ,0)

press('backspace')

OTHER TIPS

For some odd reason, Visual Boy Advance seems to neither respond to SendMessage nor keybd_event when used on their own. But if you use them together, it starts working. So using WinAPI in C++ (you can translate into Python if needed; I'm not familiar with Python enough), this sendKeys(window,key) method works with Visual Boy Advance:

    /* Just a struct to make keypress messages more organized and easier to set up */
struct extraKeyInfo {
    unsigned short repeatCount;
    unsigned char scanCode;
    bool extendedKey, prevKeyState, transitionState;

    /* Convert this struct's data into the properly-encoded unsigned int on casting */
    operator unsigned int()
    {
         return repeatCount | (scanCode << 16) | (extendedKey << 24) |
               (prevKeyState << 30) | (transitionState << 31);
    }
};

/* The main method */
void sendKey(HWND hCurrentWindow, BYTE keyval) {
  extraKeyInfo lParam = {};
  BYTE vkCode=keyval;
  lParam.scanCode = MapVirtualKey(vkCode, 0);
  keybd_event(vkCode, lParam.scanCode, 0x0, 0x0);
  SendMessage(hCurrentWindow, WM_KEYDOWN, vkCode, lParam);

  lParam.repeatCount = 1;
  lParam.prevKeyState = true;
  lParam.transitionState = true;
  keybd_event(vkCode, lParam.scanCode, 0x2, 0x0);
  SendMessage(hCurrentWindow, WM_KEYUP, vkCode, lParam);

}

Note that I've only tested this with VBA in the foreground, so if it's in the background it may not work, but it works 100% of the time in my foreground tests.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top