Цель, которую я пытаюсь достичь, - прослушивать уведомления сеанса о блокировке, разблокировке и т. д. Я должен сделать это в другом потоке из-за архитектуры и избежать блокировки основного потока. Вот что я делаю:
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch (msg)
{
case WM_CLOSE:
DestroyWindow(hwnd);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
case WM_WTSSESSION_CHANGE:
switch (wParam) {
case WTS_CONSOLE_CONNECT:
case WTS_SESSION_LOGON:
case WTS_REMOTE_CONNECT:
case WTS_SESSION_UNLOCK:
case WTS_CONSOLE_DISCONNECT:
case WTS_REMOTE_DISCONNECT:
case WTS_SESSION_LOGOFF:
case WTS_SESSION_LOCK:
case WTS_SESSION_REMOTE_CONTROL:
case WTS_SESSION_CREATE:
case WTS_SESSION_TERMINATE:
break;
default:
break;
}
break;
default:
return DefWindowProc(hwnd, msg, wParam, lParam);
}
return 0;
}
void startListeningNotifications()
{
const wchar_t g_szClassName[] = L"myWindowClass";
WNDCLASSEX wc = {};
wc.lpfnWndProc = WndProc;
wc.lpszClassName = g_szClassName;
wc.cbSize = sizeof(WNDCLASSEX);
if (!RegisterClassEx(&wc))
{
return;
}
HWND hwnd = CreateWindowEx(NULL, g_szClassName, L"", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, 0, 0, NULL, NULL, GetModuleHandle(NULL), NULL);
if (hwnd == NULL)
{
return;
}
if (!WTSRegisterSessionNotification(hwnd, NOTIFY_FOR_ALL_SESSIONS))
{
return;
}
ShowWindow(hwnd, SW_HIDE);
MSG Msg = {};
while (GetMessage(&Msg, NULL, 0, 0) > 0)
{
TranslateMessage(&Msg);
DispatchMessage(&Msg);
}
}
int main()
{
std::thread listener(startListeningNotifications);
listener.join();
return 0;
}
Проблема, с которой я сейчас сталкиваюсь, заключается в том, что я не знаю, как правильно написать метод stopListeningNotifications(). Я должен каким-то образом уничтожить свое окно и выйти из цикла сообщений. Посоветуйте, как это сделать безопасно. Заранее спасибо.
PostMessageW(hwnd, WM_CLOSE, 0, 0)
Но безопасен ли этот поток?
конечно потокобезопасный. что здесь может быть не безопасно?
Предоставлены дескрипторы функций WndProc
WM_CLOSE
и WM_DESTROY
.
case WM_CLOSE:
DestroyWindow(hwnd);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
Таким образом, вы можете отправить WM_CLOSE
сообщение с hwnd
окна, созданного в треде:
PostMessage(hwnd, WM_CLOSE, 0, 0)
Могу ли я отправить это сообщение в любую тему? В моем случае это будет основной поток.
Вы можете отправлять сообщения в любой поток, даже в тот, который не создавал окно (PostThreadMessage), но в целевом потоке должен быть цикл сообщений.
Я уже пробовал это, но это не работает для меня. Но когда я попробовал этот PostMessage() из основного потока (без PostThreadMessage), он работает.
Публикация WM_CLOSE
решила вашу проблему?
Да, но я отправляю это из другой темы, я не думаю, что это потокобезопасно.
Использование PostMessage
с дескриптором окна является потокобезопасным.
Вы должны знать, что каждый цикл обработки сообщений выполняется в своем собственном потоке. Так что просто отправить сообщение в это окно не будет хорошей идеей. Я бы попробовал использовать std::condition_variable, чтобы сигнализировать окну, которое должно быть закрыто. Окно приема может просто вызвать свою функцию
Close()
, если уведомление получено.