C++ 如何识别C+中的键盘输入+;在控制台应用程序中使用GetMessage()的Windows API?

C++ 如何识别C+中的键盘输入+;在控制台应用程序中使用GetMessage()的Windows API?,c++,windows,winapi,console,C++,Windows,Winapi,Console,首先是全局:我正在尝试通过Windows7(64位)上的控制台程序同步两个外部设备。也就是说,设备1应该触发设备2。(出于好奇,设备1是NI USB-6525,我正在使用它的变化检测功能。) 我在while循环中使用GetMessage()来等待由设备1触发的消息。(因为我没有为那个硬件编写软件,所以我不能改变我必须阅读这条消息的事实。)一旦阅读了这条消息,它就是。此分派导致回调函数,该函数使用设备2执行测量,并将measurementComplete设置为true。回调返回后,循环结束。然后执

首先是全局:我正在尝试通过Windows7(64位)上的控制台程序同步两个外部设备。也就是说,设备1应该触发设备2。(出于好奇,设备1是NI USB-6525,我正在使用它的变化检测功能。)

我在while循环中使用GetMessage()来等待由设备1触发的消息。(因为我没有为那个硬件编写软件,所以我不能改变我必须阅读这条消息的事实。)一旦阅读了这条消息,它就是。此分派导致回调函数,该函数使用设备2执行测量,并将measurementComplete设置为
true
。回调返回后,循环结束。然后执行清理,应用程序退出

问题是,用户在等待消息时也应该能够中止,例如按下一个键。我尝试执行一项检查,查看收到的消息是来自另一个线程还是来自键盘,但它无法识别键盘输入:

#include <cstdio>
#include <windows.h>

using namespace std;

bool measurementComplete = false;
BOOL bRet = 0;
MSG threadMessage;

signed long __cdecl callbackFunction(type1 param1, type2 param2) // (pseudo args)
{
    measurementComplete = 1;
    performMeasurement();
    return 0;
}

int main (int argc, char* argv[])
{
    /* Load libraries, set up hardware,
       call NI function that looks for signal from Device 1 in separate thread
       and sends a Windows message upon signal detection */

    while (!measurementComplete) { // measurement has not yet been performed
        // wait for message
        puts("Waiting for message.");
        if ((bRet = GetMessage(&threadMessage, NULL, 0, 0)) != 0) { // if message available
            if (bRet == -1) {
                puts("Error: GetMessage() returned -1. The program will now exit.");
                break;
            } else {
                DispatchMessage(&threadMessage);
                if ((TranslateMessage(&threadMessage)) != 0) // if character message (indicates key press)
                    break;
            }
        }
        puts("Message handled.");
    }

/* perform cleanup */
return 0;
}
#包括
#包括
使用名称空间std;
bool measurementComplete=假;
BOOL-bRet=0;
MSG线程消息;
有符号长cdecl调用函数(类型1参数1,类型2参数2)/(伪参数)
{
测量完成=1;
性能测量();
返回0;
}
int main(int argc,char*argv[])
{
/*加载库,设置硬件,
调用NI函数,在单独的线程中查找来自设备1的信号
并在检测到信号时发送Windows消息*/
而(!measurementComplete){//尚未执行测量
//等待消息
放置(“等待消息”);
if((bRet=GetMessage(&threadMessage,NULL,0,0))!=0){//如果消息可用
如果(bRet==-1){
puts(“错误:GetMessage()返回-1。程序现在将退出。”);
打破
}否则{
DispatchMessage(&threadMessage);
if((TranslateMessage(&threadMessage))!=0)//if字符消息(表示按键)
打破
}
}
puts(“消息已处理”);
}
/*进行清理*/
返回0;
}
我不熟悉Windows API,所以对它不太熟悉。我在Code::Blocks 13.12 IDE中编程,并使用GCC。我没有微软的MFC或任何付费产品,所以我不能使用MFC函数或类。不幸的是,我发现许多类似问题的答案都包含MFC函数

从我对这个问题的研究来看,键盘上的信息似乎没有一个窗口可以打开。我试图创建一个只显示消息的窗口,如所述,但在调用CreateWindowEx()时总是出现
错误18:没有更多文件。如果需要,我可以提供代码,但我甚至不确定是否真的需要创建一个窗口。当我运行FindWindowEx时(HWND_消息,NULL,NULL,NULL),我可以看到这样的窗口已经存在。我不知道该函数找到的窗口是由二进制文件自动创建的窗口,还是由计算机上运行的另一个程序创建的仅包含消息的窗口。另外,我不是已经有一个窗口(控制台窗口)了吗


有人知道如何在我的控制台应用程序中将键盘输入定向到消息传递系统吗?任何帮助都将不胜感激。

事实上,“控制台应用程序”没有“窗口”,因此他们无法接收任何消息(以一种简单的方式)

如果我没记错的话,您实际上可以编写代码,用消息泵创建一个不可见的窗口,这样所有的“消息”都将被发送。*)

但是,还有大量与窗口相关的代码需要研究、编写和维护。从“windows应用程序”开始并在启动时隐藏其窗口要容易得多。您将从项目代码模板免费获得所有messagepump代码。如果您喜欢这种UI风格,您还可以从窗口应用程序中分配并打开控制台窗口

*)您可以启动一个新的带窗口的应用程序项目,并查看其中的窗口是如何通过处理消息的“wndproc”例程注册的。在main()代码的某些地方,您将需要执行与空的“窗口化”项目相同的操作。另外,请记住,您将需要实际进入调度循环,并且该将阻塞您的线程,直到调度循环关闭(使用PostQuitMessage等)-通常是在应用程序关闭“信号”时(注意,通常是您的代码必须侦听并对“信号”作出反应),当您决定退出时,必须调用
PostQuitMessage

你逃不了,这里没有魔法!必须有人倾听信息。如果希望传递消息并进行一些并行工作,则需要:

  • 两个线程,一个用于消息泵,一个用于作业,具有所有同步功能,以便在它们之间安全通信
  • 或者,只需一个线程运行消息泵,然后通过消息将作业重写为异步通知,因此任何通知/回调也由messageloop处理
选择您最不喜欢的内容:)

以下是从MSDN站点获取的普通消息循环:

忽略一个可怕的事实,
BOOL
在这里的值不是true和false,请注意,
GetMessage()
的返回是消息循环何时退出的最外部控制。这对于Win32来说是很自然的。在它周围放置其他东西(比如测试是否进行了一些测量)会破坏这个简单的模式

注意:正如前面所讨论的,让您的
DispatchMessage()
实现引发一条将kic的消息是完全可以接受的(也是预期的)
while( (bRet = GetMessage( &msg, NULL, 0, 0 )) != 0)
{ 
    if (bRet == -1)
    {
        // handle the error and possibly exit
    }
    else
    {
        TranslateMessage(&msg); 
        DispatchMessage(&msg); 
    }
}