简体   繁体   English

从C#向DOSBOX发送键盘命令

[英]Sending keyboard commands to DOSBOX from C#

I want to send a single keyboard command (down arrow) to DOSBOX, followed by executing some processing code in C#, then looping. 我想向DOSBOX发送一个键盘命令(向下箭头),然后在C#中执行一些处理代码,然后循环。 My aim is to automate the running of a DOS program. 我的目标是自动运行DOS程序。

The code I have works successfully on Notepad and Windows Explorer however will not work on DOSBOX. 我在记事本和Windows资源管理器上成功运行的代码但不适用于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. 我使用WinSpy ++获取窗口的句柄,DOSBOX只有一个窗口,没有子窗口,这个过程适用于记事本和资源管理器。 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 . 我发送给SendMessage方法的其他参数是键盘通知keydown的代码和向下箭头键的代码。

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? 所以我的问题是,如何修改我的代码以将按键发送到DOSBOX,或者我可以采用不同的方式实现这一目标?

So I managed to get it working myself, here's what I found. 所以我设法让它自己工作,这就是我发现的。

DOSBOX is an SDL application and so runs in OpenGL. DOSBOX是一个SDL应用程序 ,因此在OpenGL中运行。 Sending messages to OpenGL applications has been discussed before and is done using the SendInput() method . 之前已经讨论过向OpenGL应用程序发送消息,并使用SendInput()方法完成 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. 这显然是SendKeys在引擎盖下调用的,所以我不确定为什么这对我不起作用,但看起来我不是唯一一个。

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. 上面的堆栈溢出链接中讨论的另一个选项是编写C或C ++库并通过C#应用程序调用它。 This is what I ended up doing, here's the code. 这就是我最终做的,这是代码。

Down.h Down.h

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

Down.cpp 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));
}

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: 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. 您可以在控制台应用程序上看到输出 - 这意味着它正在接收命令。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM