如何在Windows上使用c++访问底层硬件I/O函数

How can I access a low-level hardware I/O functions in C++ on Windows?

本文关键字:硬件 函数 访问 c++ Windows      更新时间:2023-10-16

我正在用c++编写一个游戏,我需要检测用户何时按下一个键。通常,我会使用std::cin,但我有一个图形窗口,使用graphics.h,一个头文件,最初是由古老的Borland Turbo c++编译器提供的,但等效的在线可用。因此,我将使用函数inportb();,函数定义如下:

inline unsigned char inportb(unsigned int port) {
    unsigned char ret;
    asm volatile ("inb %%dx,%%al":"=a"(ret):"d"(port));
    return ret;
}

来源:inportb。

但是在Windows中,像这样的直接低级硬件I/O是受保护的,如果尝试这样做,程序将被杀死。因此,我需要通过高级函数或API访问该函数。

我的问题是:我该怎么做?

如果你试图在游戏循环中检测特定键的状态,GetAsyncKeyState将在那一刻确定特定状态。

if (GetAsyncKeyState(VK_LEFT) & 0x8000) != 0u)
{
    // ...
}

该函数接受一个虚拟键代码(在本例中为左箭头键),获取状态,并在按位and操作后确定键是否按下,然后离开。

这些虚拟键代码可以在WinUser.h中找到。GetAsyncKeyState与GetKeyState的不同之处在于,GetKeyState不反映与硬件相关的中断级状态(这就是我在上面使用GetAsyncKeyState的原因)。如果您需要给定实例中的所有键状态(这种情况很少见),请考虑GetKeybardState。

然而,如果你正在等待一个键事件(WM_KEYDOWN, WM_CHAR, WM_KEYUP)发生,你必须在窗口过程中提供一个case来处理该事件。

LRESULT WindowProc(UINT const message, WPARAM const wparam, LPARAM const lparam)
{
    switch(message)
    {
    // [ cases like WM_CREATE / WM_PAINT / WM_CLOSE / WM_DESTROY ]
    case WM_KEYDOWN:
        // handle event here
        break;
    case WM_CHAR:
        // handle event here
        break;
    case WM_KEYUP:
        // handle event here
        break;
    }
}

在Windows中有4种不同的方法来检测输入

  1. GetInputState()(及其周围的API)(假设您不需要支持Windows XP或以下版本)
  2. 您可以使用GetKeyState()(及其周围的API)进行轮询,但是您必须为想要检查的每个键执行此操作。您可以使用GetInputState()来检查是否有值得检查的东西,如果有太多的键要轮询。
  3. GetRawInputData()(及其周边API)。这将在XP中工作,但它是一个更丑陋的界面。而且,它只会得到连接到机器上的实际硬件的输入。因此,如果您远程会话到一台windows机器,它可能无法工作。您还需要弄清楚哪些原始设备连接到系统,弄清楚它们何时连接,何时分离。这个(RawInput) API支持所有这些,所以你可能会在编写游戏时使用它。
  4. 钩子函数,它允许你注册回调,当输入事件发生时调用。钩子是通过SetWindowsHookEx()(和周围的API)注册的。这是检测按键最有效,但最不可靠的方法。一些程序可以为相同的事件设置钩子,API希望每个回调都能足够快地返回,以便其他注册者也能及时得到通知。如果你没有足够快地返回,即使只有一次,你也不会被告知,但是你的钩子函数将不再被调用…即使你注销回调并重新注册它们也不会。让这些工作,并在没有用户干预的情况下继续工作,是优秀键盘记录程序的真正艺术所在。

几十年前我在Turbo c++上玩得很开心:-)但如果我是你,我会尝试使用除了C编译器之外的游戏引擎或库,比如这个SDL或Ogre(见https://en.wikipedia.org/wiki/List_of_game_engines有一个很长的列表)。

它们提供了一个带有键盘事件的事件循环。

或者至少你可能想使用Windows或跨平台框架,如微软提供的MSVC(它在某些用途上是免费的)或Qt(它甚至更免费,现在附带了一个方便的IDE)。

让你的游戏充满乐趣!