我如何 运行 两个函数,一个用于键盘,一个用于鼠标,同时使用 Turbo C++?

How can I run two functions, one for keyboard and one for mouse, in parallel using Turbo C++?

我正在尝试使用 Turbo-C++ 同时获取鼠标和键盘输入。

我想使用两个函数。第一个函数是 main 函数,它可以接受键盘输入或从 dos.h 调用 delay 函数来暂时停止 main().

的正常运行

第二个函数处理鼠标输入:

void mouse()
 {
    union REGS in,out;
    in.x.ax=1; // Show mouse pointer
    int86(0x33,&in,&out); //interrupt call
    while(1)
     {
       //print the location whenever it changes (not required)
     }
 }

上下文

如果我对问题的理解正确,您正在编写一个程序,该程序将 运行 在 16 位 MS-D OS 下,在 DosBox 中。该程序应该响应鼠标和键盘输入。它可能还想在等待输入时执行一些计算。

轮询

最简单和最直接的解决方案是使用 轮询,这意味着您坐在一个循环中,询问键盘和鼠标是否有新的输入要响应。在伪代码中:

  while (true) {
    while (keyboard_has_activity()) {
      process_keyboard_input();
    }
    while (mouse_has_activity()) {
      process_mouse_input();
    }
    do_other_computation_for_a_short_time();
  }

keyboard_has_activity怎么写?您在评论中提到了来自 conio.hkbhit;那应该工作。您还可以使用较低级别的中断(尽管我不知道有什么理由不使用 kbhit)。

注意:process_keyboard_input 应该只读取当前可用的尽可能多的字符。如果您的程序涉及等待用户按下 Enter,那么您必须将键入的字符存储在(比方说)一个数组中,直到您真正看到 Enter 键,然后一次处理所有输入。

mouse_has_activity怎么写?据我所知,您必须使用 INT 0x33 例程来查询当前鼠标状态并将其与上次调用时的状态进行比较。

do_other_computation_for_a_short_time怎么写?您必须在算法中设计某种时间限制。例如,如果您正在编写国际象棋引擎,它会在每次(比如说)棋盘评估后检查时钟,并在必要时停止,以便您可以轮询输入。当算法停止时,它必须在数据结构中记住它所在的位置,以便稍后可以从该点恢复。一种常见的策略是维护工作列表:仍然需要完成的所有计算部分的列表。这是 cooperative multitasking.

的一种形式

在任何情况下,您都希望时间限制不超过 10 毫秒,否则您可能会错过鼠标点击(用户可能会在您注意到之前按下并释放按钮)。

这个解决方案很简单,但不一定是最有效的,而且如果时间限制太长,可能会因为前面提到的鼠标点击丢失的问题而变得不可靠。

中断

另一种方法是 hook into the low-level keyboard and mouse interrupts。这样,您安装的代码在输入设备被触摸时仅需 运行s,效率更高。但是,由于各种原因,包括当一段代码被中断时,您几乎无法控制它正在做什么。 更难做到正确。

非答案:线程

在这种环境下,尝试将程序组织为两个线程(鼠标和键盘)同时具有两个功能 运行ning 是不切实际的。 DOS 没有线程功能,而且我不知道有什么方法可以在不重写 OS 的情况下添加它们。相反,您需要从一个控制线程执行所有操作。

您在评论中说您正在为 Windows 编码。 Microsoft 在 MSDN 上有 ReadConsoleInput() function that reads both keyboard and mouse inputs in a console window. See Reading Input Buffer Events

例如:

#include <windows.h>

int main()
{
    HANDLE hStdIn;
    INPUT_RECORD input[128];
    DWORD dwOldMode, dwNumRead;

    hStdIn = GetStdHandle(STD_INPUT_HANDLE);

    GetConsoleMode(hStdIn, &dwOldMode);
    SetConsoleMode(hStdIn, ENABLE_MOUSE_INPUT);

    while (ReadConsoleInput(hStdIn, input, 128, &dwNumRead))
    {
        for (DWORD i = 0; i < dwNumRead; ++i)
        {
            switch (input[i].EventType)
            {
                case KEY_EVENT:
                    // process input[i].Event.KeyEvent data as needed...
                    break;

                case MOUSE_EVENT:
                    // process input[i].Event.MouseEvent data as needed...
                    break;
            }
        } 
    }

    SetConsoleMode(hStdIn, dwOldMode);
    return 0;
}