C++ 如何将键盘输入发送到Windows98窗口模式下运行的dos应用程序
我的问题是关于非常古老的技术。我有一项任务是在Windows 98中自动运行在Windows模式下的旧DOS软件(光谱仪)。我提出了两种不同的解决方案,但这两种解决方案在DOS应用程序中都不起作用:C++ 如何将键盘输入发送到Windows98窗口模式下运行的dos应用程序,c++,dos,keyboard-input,windows-98,C++,Dos,Keyboard Input,Windows 98,我的问题是关于非常古老的技术。我有一项任务是在Windows 98中自动运行在Windows模式下的旧DOS软件(光谱仪)。我提出了两种不同的解决方案,但这两种解决方案在DOS应用程序中都不起作用: 第一种解决方案 使DOS应用程序处于活动状态 通过SendInput函数发送输入,如下所示: void MossbauerLab::Sm2201::SaveManager::AutoSaveManager::sendKeysViaInput(const std::vector&keys,int
- 使DOS应用程序处于活动状态
- 通过SendInput函数发送输入,如下所示:
void MossbauerLab::Sm2201::SaveManager::AutoSaveManager::sendKeysViaInput(const std::vector&keys,int keyPause)
{
std::vector::const_迭代器it;
输入键盘输入;
keyBoardInput.type=输入\键盘;
keyBoardInput.ki.wScan=0;
keyBoardInput.ki.time=0;
keyBoardInput.ki.dwExtraInfo=0;
for(it=keys.begin();it!=keys.end();it++)
{
keyBoardInput.ki.wVk=(*it);
keyBoardInput.ki.dwFlags=0;//按下键
SendInput(1,&键盘输入,sizeof(输入));
睡眠(按键暂停);
keyBoardInput.ki.dwFlags=2;//向上键
SendInput(1,&键盘输入,sizeof(输入));
睡眠(按键暂停);
}
}
void MossbauerLab::Sm2201::SaveManager::AutoSaveManager::SendKeyViaKeyboardController(const std::vector&scanCodes,int keyPause)
{
std::vector::const_迭代器it;
for(it=scanCodes.begin();it!=scanCodes.end();it++)
{
//等待直到缓冲区为空
int status=0;
int结果=0;
做
{
状态=_inp(0x64);
//Windows 98中的MS-DOS应用程序运行在虚-实模式,而不是保护模式,这就是为什么无法使用保护模式驱动程序或系统调用与它们通信。您需要使用BIOS/DOS中断与键盘接口,Windows驱动程序将无法为您执行此操作
因此,实现这一点的唯一方法是使用另一个DOS应用程序模拟按键,但我不确定BIOS键盘缓冲区是否虚拟化,但如果不是,那么您应该能够通过从应用程序启动虚拟实模式进程来实现(必须是一个单独的exe,但您应该能够在无窗口运行它)并将按键作为命令行参数传递给BIOS
这是一个非常有趣的问题,希望这能帮助你解决它。首先我要感谢所有对这篇文章感兴趣的人,你们都给了我一些有用的信息,我终于得到了我想要的
关于它是如何实现的:我已经创建了VXD驱动程序(它是我的专有驱动程序,我不能在这里发布它的代码,因为我计划在商业项目中使用它)。但此评论的主要目的是-是的,可以模拟Windows 98中运行的DOS应用程序在窗口模式下的键盘输入。。我可以发布的部分解决方案在github上:
这里我使用的是vXd访问器类:()
主要思想-使用W32_DEVICEIOCONTROL驱动程序消息处理程序和DEVICEIOCONTROL函数与驱动程序交互,并使用CTL(在我的驱动程序中定义)代码传递具有1字节对齐的结构:我没有使用CTL_代码宏。此Github项目几乎准备就绪~95%(目前,我只需手动选择要发送的窗口,方法是用鼠标点击激活窗口并检查是否有适当的内存可用)。16年前我也遇到过同样的问题,我的(不太优雅但可能更容易实现)解决方案是将我想插入的文本放入剪贴板,获取前景窗口hWnd,然后使用SendMessage()将0xE001作为数据发送给它的WM_SYSCOMMAND.IIRC触发了窗口上下文菜单中的粘贴命令(我使用Spy++)
我希望有人会觉得这很有用。您尝试的操作不会起作用,因为MS-DOS应用程序运行在与Windows运行的主虚拟机不同的虚拟机中。这两个虚拟机有两个不同的虚拟键盘控制器。除了编写VxD(32位驱动程序)之外我不确定是否有办法满足您的要求。也许有办法写信给MS-DOS Vx键盘驱动程序?罗斯,谢谢您的评论,我以前从未听说过VxD,我搜索了有关虚拟键盘驱动程序的内容,找到了有趣的链接:可能它可以帮我找到解决方案,这与您需要的解决方案类似。您已经找到了编写自己的来编写自己的VxD,就像您链接的“VSAMPLED”示例一样,但它不是键盘驱动程序。它将只使用Windows虚拟键盘驱动程序(VKD)公开的API,就像示例代码如何使用VKD_Force_键一样。
void MossbauerLab::Sm2201::SaveManager::AutoSaveManager::sendKeysViaInput(const std::vector<DWORD>& keys, int keyPause)
{
std::vector<DWORD>::const_iterator it;
INPUT keyBoardInput;
keyBoardInput.type = INPUT_KEYBOARD;
keyBoardInput.ki.wScan = 0;
keyBoardInput.ki.time = 0;
keyBoardInput.ki.dwExtraInfo = 0;
for(it = keys.begin(); it != keys.end(); it++)
{
keyBoardInput.ki.wVk = (*it);
keyBoardInput.ki.dwFlags = 0; // key down
SendInput(1, &keyBoardInput, sizeof(INPUT));
Sleep(keyPause);
keyBoardInput.ki.dwFlags = 2; // key up
SendInput(1, &keyBoardInput, sizeof(INPUT));
Sleep(keyPause);
}
}
void MossbauerLab::Sm2201::SaveManager::AutoSaveManager::sendKeysViaKeyboardController(const std::vector<BYTE>& scanCodes, int keyPause)
{
std::vector<BYTE>::const_iterator it;
for(it = scanCodes.begin(); it != scanCodes.end(); it++)
{
// wait untill buffer is empty
int status = 0;
int result = 0;
do
{
status = _inp(0x64);
// std::cout <<"Keyboard status: "<< status << std::endl;
Sleep(10);
}
while (status & 1);
// send scan code for key down
_outp(KEYBOARD_CMD_REG, 0xD2);
_outp(KEYBOARD_DATA_REG, (*it));
result = _inp(KEYBOARD_DATA_REG);
std::cout <<"Keyboard command result for KEY DOWN: "<< result << std::endl;
// send scan code for key up
BYTE keyUpCode = (*it) | 128;
Sleep(keyPause);
_outp(KEYBOARD_CMD_REG, 0xD2);
_outp(KEYBOARD_DATA_REG, keyUpCode);
result = _inp(KEYBOARD_DATA_REG);
std::cout <<"Keyboard command result for KEY UP: "<< result << std::endl;
}
}