我如何 运行 两个函数,一个用于键盘,一个用于鼠标,同时使用 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.h
的 kbhit
;那应该工作。您还可以使用较低级别的中断(尽管我不知道有什么理由不使用 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;
}
我正在尝试使用 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.h
的 kbhit
;那应该工作。您还可以使用较低级别的中断(尽管我不知道有什么理由不使用 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;
}