Я работал с некоторой библиотекой Bluetooth, и для некоторого обратного вызова Bluetooth необходимо использовать цикл сообщений Windows. Но согласно моему требованию, мне нужно создать нормальную программу на C ++ без какого-либо графического интерфейса. Можно ли создать цикл сообщений без окна?
main(){
Discovery disc;
disc.startDiscovery();
}Discovery::startDiscovery(){
__hook(&CallBackFromLibrary::OnDiscoveryStarted, &obj, &Discovery::OnDiscoveryStarted);
__hook(&CallBackFromLibrary::OnDiscoveryComplete, &obj, &Discovery::OnDiscoveryComplete);
}apiObject.discoverBluetoothDevices();
В этом примере кода я должен получить обратные вызовы как OnDiscoveryStarted и OnDiscoveryComplete после вызова apiObject.discoverBluetoothDevices ().
Поскольку они используют циклы сообщений для обратных вызовов, я получил обратный вызов только в приложении с графическим интерфейсом. Как получить обратный вызов, используя циклы сообщений, поскольку в документации библиотеки говорится, что циклы сообщений необходимы.
Цикл сообщений в потоке без 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;
}
Да, это возможно — Windows свяжет очередь сообщений с потоком, когда / если поток попытается использовать ее. При этом есть немного гоночного состояния. Чтобы публиковать сообщения в очереди сообщений, вы используете PostThreadMessage
. Но у потока не будет очереди сообщений до тех пор, пока он не вызовет функцию для чтения из очереди сообщений (т. Е. Windows не создает очередь сообщений для потока, пока поток не попытается использовать ее).
Чтобы предотвратить состояние гонки, вы обычно хотите сделать что-то в этом порядке:
CreateThread
, передавая ему дескриптор мьютекса, который будет передан новому потокуPeekMessage
(не ожидая никакого результата, так как очередь еще не была создана — но это форсирует ее создание).PostThreadMessage
Убедитесь в том, что у «ребенка» есть очередь сообщений, так что это сработает.Еще одна возможность для ребенка — создать окно, но оставить его скрытым. Очевидным преимуществом здесь является совместимость с кодом, который ожидает отправки / отправки сообщений в обычную очередь сообщений с использованием SendMessage
, PostMessage
, SendMessageTimeout
и так далее, вместо специального PostThreadMessage
, Другое очевидное преимущество состоит в том, что он избегает описанного выше танца очереди сообщений.
Когда вы приступаете к этому, основной характеристикой «окна» Windows не является что-то на дисплее — это очередь сообщений, и то, что отображается на дисплее, это просто рисунок, выполненный в ответ на некоторые конкретные сообщения. Скрытое окно не намного больше, чем очередь сообщений.