![](/img/trans.png)
[英]C++ WTL8.1 How to create a window in a new thread with message loop?
[英]Is it possible to create a message loop without creating a window in 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 應用程序上獲得了回調。 如何使用消息循環接收回調,因為庫文檔說需要消息循環。
是的,這是可能的——當/如果線程嘗試使用一個線程時,Windows 會將一個消息隊列與一個線程相關聯。 不過,這樣做時會有一點競爭條件。 要發布到線程的消息隊列,請使用PostThreadMessage
。 但是,線程在調用函數嘗試從消息隊列中讀取之前不會有消息隊列(即,在線程嘗試使用消息隊列之前,Windows 不會為該線程創建消息隊列)。
為了防止競爭條件,您通常希望按以下順序執行某些操作:
CreateThread
,將要傳遞給新線程的事件句柄傳遞給它PeekMessage
(不期望任何結果,因為尚未創建隊列 - 但這會強制其創建)。PostThreadMessage
,確保子級具有消息隊列的“知識”安全,因此這將起作用。 另一種可能性是讓孩子創建一個窗口,但將其隱藏。 這里的明顯優勢是與期望使用SendMessage
、 PostMessage
、 SendMessageTimeout
將消息發布/發送到普通消息隊列的代碼兼容,而不是特殊的PostThreadMessage
。 另一個明顯的優點是它避免了上面概述的線程消息隊列舞蹈。
當您深入了解它時,Windows“窗口”的主要特征不是顯示器上的某些東西——它是一個消息隊列,顯示器上顯示的只是響應某些特定消息而完成的繪圖。 隱藏窗口只不過是一個消息隊列。
非 GUI 線程中的消息循環:
#include "stdafx.h"
#include <Windows.h>
#include <thread>
#include <iostream>
using namespace std;
void ThreadFunction()
{
MSG msg;
BOOL result;
for (;;)
{
result = GetMessage(&msg, nullptr, 0, 0);
if (result <= 0)
{
break;
}
cout << msg.message << " " << msg.wParam << " " << msg.lParam << endl;
//TranslateMessage(&msg);
//DispatchMessage(&msg);
}
}
int main()
{
thread t(ThreadFunction);
HANDLE h = t.native_handle();
DWORD dw = GetThreadId(h);
PostThreadMessage(dw, WM_APP + 1, 1, 2);
PostThreadMessage(dw, WM_APP + 2, 10, 20);
PostThreadMessage(dw, WM_QUIT, 10, 20);
t.join();
return 0;
}
更新:
根據評論,這段代碼不是在gcc中編譯的。 試圖在 VC++ 中重現這一點,我發現該程序在 x64 中不起作用。 這個更新的解決方案有望解決這兩個問題:
#include "stdafx.h"
#include <Windows.h>
#include <thread>
#include <iostream>
using namespace std;
DWORD threadID{};
void ThreadFunction(HANDLE event_handle)
{
MSG msg;
BOOL result;
threadID = GetCurrentThreadId();
SetEvent(event_handle);
for (;;)
{
result = GetMessage(&msg, nullptr, 0, 0);
if (result <= 0)
{
break;
}
cout << msg.message << " " << msg.wParam << " " << msg.lParam << endl;
}
}
int main()
{
HANDLE e = CreateEvent(nullptr, FALSE, FALSE, nullptr);
thread t(ThreadFunction, e);
WaitForSingleObject(e, INFINITE);
CloseHandle(e);
PostThreadMessage(threadID, WM_APP + 1, 1, 2);
PostThreadMessage(threadID, WM_APP + 2, 10, 20);
PostThreadMessage(threadID, WM_QUIT, 10, 20);
t.join();
return 0;
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.