C++中的键盘/鼠标输入

10

我想知道如何在C++中接受键盘和鼠标输入,使用Visual Studio 2010,适用于Windows 7 32位。

--编辑:我忘记提到我需要在不中断程序流程的情况下获取键盘/鼠标输入。类似于监听器。我不想暂停程序并请求输入,然后让用户输入并按回车键。我想要的是:

如果用户按下W,S,A,D -> 发生某事。

或:如果用户在左键单击->某些事情发生。

我必须提到我仍然是编程的新手。我了解基本的面向对象编程但就此而言就到这了。我肯定这将涉及到我还不知道的东西,我不介意,我只是要求您仔细地解释,并可能给出一个示例,以便我知道如何使用它。

谢谢。


1
如果你正在编写一个C++控制台应用程序,那会比你想象的要困难得多。你必须监听Windows消息泵以获取各种消息,并对其进行解释。这将引发一系列问题。 - Mooing Duck
4个回答

17

不中断流程的键盘/鼠标输入

#include <windows.h>
#include <iostream>
using namespace std;

int main()
{
    HANDLE hIn;
    HANDLE hOut;
    COORD KeyWhere;
    COORD MouseWhere;
    COORD EndWhere;
    bool Continue = TRUE;
    int KeyEvents = 0;
    int MouseEvents = 0;
    INPUT_RECORD InRec;
    DWORD NumRead;

    hIn = GetStdHandle(STD_INPUT_HANDLE);
    hOut = GetStdHandle(STD_OUTPUT_HANDLE);

    cout << "Key Events   : " << endl;
    cout << "Mouse Events : " << flush;

    KeyWhere.X = 15;
    KeyWhere.Y = 0;
    MouseWhere.X = 15;
    MouseWhere.Y = 1;
    EndWhere.X = 0;
    EndWhere.Y = 3;

    while (Continue)
    {
        ReadConsoleInput(hIn,
                         &InRec,
                         1,
                         &NumRead);

        switch (InRec.EventType)
        {
        case KEY_EVENT:
            ++KeyEvents;
            SetConsoleCursorPosition(hOut,
                                     KeyWhere);
            cout << KeyEvents << flush;
            if (InRec.Event.KeyEvent.uChar.AsciiChar == 'x')
            {
                SetConsoleCursorPosition(hOut,
                                         EndWhere);
                cout << "Exiting..." << endl;
                Continue = FALSE;
            }
            break;

        case MOUSE_EVENT:
            ++MouseEvents;
            SetConsoleCursorPosition(hOut,
                                     MouseWhere);
            cout << MouseEvents << flush;
            break;
        }
    }

    return 0;
}

我想知道您是否能向我展示如何单独检查按键的按下/释放,而不是整个按键事件? - Rohit

15
这背后有很多相关的概念。
在非常低的层面上,键盘和鼠标是硬件设备,它们通过产生一些"中断"(以电信号形式)发送到CPU。操作系统提供了一些驱动程序来处理这些中断,通过解码设备通讯特定协议,并在操作系统层面上"标准化"(以事件形式)这些信号。
对于"控制台应用程序",操作系统通过填充一个输入缓冲区(本质上是char[])来处理这些事件(特别是键盘),该缓冲区可以作为名为"CON"的"无限字符序列"(早期计算机的复杂名称)进行访问,从而模拟早期计算机的"无限电传打字机模型"。在C++程序中,标准库在程序启动时将std::cinstd::cout对象关联到该"文件",因此您可以使用std::istream函数和运算符读取输入字符序列。
对于"图形应用程序",不幸的是,没有"早期模型"可模仿,而"事件"则作为操作系统本地结构留下。不同的操作系统在表示和处理这些事件的方式上有所不同,但是可以看到某些相似之处。对于Windows(因为您的问题是关于它的),典型的程序通过使用"消息循环"以特定的OS API顺序检索这些事件。在该循环中,典型的程序还会调用另一个OS API将这些事件分派给先前创建的"窗口"上关联的适当"回调"过程。该回调程序必须检测事件代码,根据需要转换参数并管理它们以执行所需的操作。
WIN32编程教程(例如http://www.winprog.org/tutorial/)可以查看更精确的细节。大部分代码实际上是C,因为C是API规范化的语言。对于C++,已编写了许多库来以C++类的形式表示操作系统对象,并将OS API映射到这些类成员。这些库可以是特定于操作系统的(如MFC、WTL...),也可以是“跨平台”的(它们存在不同的版本,将各种操作系统的API映射到相同的C++接口中),例如WxWidget、Qt、Gtk、Fltk等。

希望这能给您更多思考的线索。


非常感谢^^。这对于理解背后的理论真的很有帮助。 - Rohit
对OP来说很有用,而且我认为很必要。++ - Captain Giraffe

0

Windows 还是控制台?

如果选择控制台,请使用:

std::cin >> myVar;

抱歉,我忘了提到我正在尝试在不中断程序的情况下接受输入。我已经编辑了我的原始问题以反映这一点。感谢您抽出时间来回答。 - Rohit

0

如果你正在编写控制台应用程序,你可以使用scanf或cin来获取键盘输入。控制台应用程序不支持鼠标。

如果你正在编写GUI应用程序,你将使用标准的Windows控件构建应用程序,这些控件具有内置的鼠标和键盘输入行为。你可以直接使用这些可重用的控件,或者你可以增强它们的功能,使它们完全按照你的应用程序所需的方式进行操作。

例如,在GUI应用程序中,有一个标准的编辑控件,用户可以在其中输入文本。当用户输入文本时,你的程序会收到消息,并根据这些消息或其他事件检索文本,并根据你的程序要求执行相应的操作。


抱歉,我忘记提到我尝试在不中断程序的情况下接受输入。我已经编辑了我的原始问题以反映这一点。感谢您抽出时间来回答。 - Rohit

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接