从C#向DOSBOX发送键盘命令

3
我希望能够向DOSBOX发送一个单一的键盘命令(下箭头),然后在C#中执行一些处理代码,最后循环执行。我的目的是自动化运行DOS程序。
我已经编写了一段代码,在记事本和Windows资源管理器上成功运行,但无法在DOSBOX上运行。
以下是我简化后的代码:
[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));
}

我使用WinSpy++获取了窗口的句柄,DOSBOX只有一个窗口且没有子窗口,这个过程对于记事本和资源管理器运行良好。我将发送给SendMessage方法的其他参数是键盘通知按下键向下箭头键的代码。
所以我的问题是,我该如何修改我的代码以发送按键到DOSBOX,或者是否有其他方法可以实现这一点?
2个回答

3

我设法自己使其工作,以下是我的发现。

DOSBOX是一个SDL应用程序,因此运行在OpenGL中。向OpenGL应用程序发送消息已经讨论过了,并且使用SendInput()方法来完成。显然,这就是SendKeys在幕后调用的内容,所以我不确定为什么它对我不起作用,但看起来我不是唯一一个遇到这个问题的人。

这个未维护的库似乎可以正常工作,或者可以像这样自定义实现。

如上所述,另一种选择是编写一个C或C++库,并通过C#应用程序调用它。这就是我最终采取的方法,以下是代码。

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));
}

2

微软曾经在很久以前发布了一篇关于这个主题的文章,并提供了完整的实现。

编辑:根据评论中的对话 - 这是代码。

控制台应用程序:

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

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

Winforms应用程序:

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

您可以在控制台应用程序上查看输出 - 这意味着它正在接收命令。

这似乎更多是关于在控制台应用程序中接收消息,我所希望做的只是向一个我无法修改的应用程序发送一条信息。 - Adam
嗯,我明白了。我没意识到你无法控制控制台应用程序?所以你想要的只是从你的C# Windows应用程序发送按键到控制台应用程序?为什么不直接使用System.Windows.Forms.SendKeys.SendWait()呢? - AngryHacker
我刚刚用记事本试了一下,它可以正常工作,但在DOSBOX中无法工作。你有在DOSBOX中尝试过吗? - Adam
@Adam,我刚刚下载了DOSBox 0.74,并且我的代码仍然可以运行。 我希望我们说的是同一个[DOSBox](http://imgur.com/ntuer70)。 - AngryHacker
@Adam 我不确定。我只是下载、安装并双击它。它进入了DOS提示符,然后我让我的WinForms应用程序运行。我能想到的唯一其他事情就是你应该让你的DOSBox成为活动应用程序。 - AngryHacker
显示剩余3条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接