首页 > 解决方案 > 是否可以在不使用 C++ 创建窗口的情况下创建消息循环

问题描述

我正在使用一些蓝牙库和一些蓝牙回调,有必要使用 Windows 消息循环。但根据我的要求,我需要创建一个没有任何 GUI 的普通 C++ 程序。是否可以在没有窗口的情况下创建消息循环?

main(){
    Discovery disc;
    disc.startDiscovery();
}


Discovery::startDiscovery(){
  __hook(&CallBackFromLibrary::OnDiscoveryStarted, &obj, &Discovery::OnDiscoveryStarted);
  __hook(&CallBackFromLibrary::OnDiscoveryComplete, &obj, &Discovery::OnDiscoveryComplete);  
}


apiObject.discoverBluetoothDevices();

在此示例代码中,我应该在调用 apiObject.discoverBluetoothDevices() 后收到回调为 OnDiscoveryStarted 和 OnDiscoveryComplete。

由于他们使用消息循环进行回调,所以我只在 GUI 应用程序上得到了回调。如何使用消息循环接收回调,因为库文档说需要消息循环。

标签: c++visual-c++windows-messagesmessage-loop

解决方案


是的,这是可能的——当/如果线程尝试使用一个消息队列时,Windows 会将消息队列与一个线程相关联。但是,这样做时会有一点竞争条件。要发布到线程的消息队列,请使用PostThreadMessage. 但是,在线程调用函数尝试从消息队列中读取之前,线程不会有消息队列(即,Windows 不会为线程创建消息队列,直到线程尝试使用它)。

为了防止竞争条件,您通常希望按此顺序执行某些操作:

  1. cal CreateEvent 创建一个事件(无信号)
  2. call CreateThread,将要传递给新线程的事件句柄传递给它
  3. 让父母等待事件
  4. 让孩子调用PeekMessage(不期待任何结果,因为尚未创建队列 - 但这会强制创建它)。
  5. 让孩子发出事件信号
  6. 现在父母将恢复,并且可以使用PostThreadMessage,安全的“知识”,孩子有一个消息队列,所以这将起作用。

另一种可能性是让孩子创建一个窗口,但将其隐藏。这里的明显优势是与期望使用SendMessage, PostMessage,SendMessageTimeout等而不是特殊的PostThreadMessage. 另一个明显的优点是它避免了上面概述的线程-消息-队列舞。

当您深入了解它时,Windows“窗口”的主要特征不是显示器上的东西——它是一个消息队列,显示器上显示的只是为响应某些特定消息而完成的绘图。隐藏的窗口不仅仅是一个消息队列。


推荐阅读