Можно ли создать цикл сообщений без создания окна в C++
Я работал с некоторой библиотекой 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().
Поскольку они используют циклы сообщений для обратных вызовов, я получил обратный вызов только в приложении с графическим интерфейсом. Как получить обратный вызов, используя циклы сообщений, поскольку в документации библиотеки говорится, что циклы сообщений необходимы.
2 ответа
Цикл сообщений в потоке без 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 не является что-то на дисплее - это очередь сообщений, и то, что отображается на дисплее, это просто рисунок, выполненный в ответ на некоторые конкретные сообщения. Скрытое окно не намного больше, чем очередь сообщений.