Question

I want to send a single keyboard command (down arrow) to DOSBOX, followed by executing some processing code in C#, then looping. My aim is to automate the running of a DOS program.

The code I have works successfully on Notepad and Windows Explorer however will not work on DOSBOX.

This is my (simplified) code:

[DllImport("user32.dll")]
public static extern int SendMessage(IntPtr hWnd, int wMsg, IntPtr wParam, IntPtr lParam);

static void Main(string[] args)
{
    Console.ReadKey();
    System.Threading.Thread.Sleep(2000); //to give me time to set focus to the other window
    SendMessage(new IntPtr(0x001301CE), 0x0100, new IntPtr(0x28), new IntPtr(0));
}

I obtained the handle for the window using WinSpy++, DOSBOX only has one window and no child windows and this process works fine for notepad and explorer. The other perameters I'm sending to the SendMessage method are the code for the keyboard notification keydown and the code for the down arrow key.

So my question is, how can I modify my code to send keypresses to DOSBOX, or is there a different way that I can achieve this?

Was it helpful?

Solution

So I managed to get it working myself, here's what I found.

DOSBOX is an SDL application and so runs in OpenGL. Sending messages to OpenGL applications has been discussed before and is done using the SendInput() method. This is apparantly what SendKeys calls under the hood so I'm not sure why that wasn't working for me but it looks like I'm not the only one.

This unmaintained library seems to work fine, or a custom implementation can be done like this.

The other option as discussed in the stack overflow link above is to write a C or C++ library and call it through the C# application. This is what I ended up doing, here's the code.

Down.h

extern "C" __declspec(dllexport) void PressDownKey();

Down.cpp

#include <Windows.h>
#include "Down.h"
extern "C" __declspec(dllexport) void PressDownKey()
{
    KEYBDINPUT KeybdInput;
    ZeroMemory(&KeybdInput, sizeof(KeybdInput));
    KeybdInput.wVk = VK_DOWN;
    KeybdInput.dwExtraInfo = GetMessageExtraInfo();
    INPUT InputStruct;
    ZeroMemory(&InputStruct, sizeof(InputStruct));
    InputStruct.ki = KeybdInput;
    InputStruct.type = 1;
    int A = SendInput(1,&InputStruct,sizeof(INPUT));
    Sleep(10);
    ZeroMemory(&KeybdInput, sizeof(KeybdInput));
    KeybdInput.wVk = VK_DOWN;
    KeybdInput.dwFlags = KEYEVENTF_KEYUP;
    KeybdInput.dwExtraInfo = GetMessageExtraInfo();
    ZeroMemory(&InputStruct, sizeof(InputStruct));
    InputStruct.ki = KeybdInput;
    InputStruct.type = 1;
    A = SendInput(1,&InputStruct,sizeof(INPUT));
}

OTHER TIPS

Microsoft has an article on this very topic from way back, along with a full implementation.

EDIT: per conversation in the comments - here is the code.

Console app:

class Program
{
    static void Main(string[] args)
    {

        ConsoleKeyInfo ki = Console.ReadKey();
        while (ki.KeyChar != 'Z')
        {
            Console.WriteLine(ki.KeyChar);
            ki = Console.ReadKey();
        }
    }
}

Winforms App:

SendKeys.SendWait("A");
Thread.Sleep(2000);
SendKeys.SendWait("Z");

You can see the output on the console app - which means it is receiving commands.

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