一般來講,UI的所有操作都必須在主線程,否則會出現未知錯誤。但有時候我們會需要一個功能比較單一的窗口,同時希望他在一個單獨的線程運行。並不影響主線程的效率。
下面說明一下新建子線程創建的新窗口的方法,關鍵在於在子線程中,有一套自己的事件循環機制,即可脫離主線程單獨運行
LRESULT CALLBACK WndProc(HWND hWnd, UINT wMsg, WPARAM wParam, LPARAM lParam)
{
return DefWindowProc(hWnd, wMsg, wParam, lParam);
}
void CreateWndInThread(int nWidth, int nHeight)
{
WNDCLASSEXA wcex;
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc = WndProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = GetModuleHandle(nullptr);
wcex.hIcon = 0;
wcex.hCursor = LoadCursor(nullptr, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
wcex.lpszMenuName = NULL;
char cName[MAX_PATH] = { 0 };
GetModuleFileNameA(wcex.hInstance, cName, sizeof(cName));
char* szApp = strrchr(cName, '\\') + 1;
strchr(szApp, '.')[0] = '\0';
wcex.lpszClassName = szApp;
wcex.hIconSm = 0;
RegisterClassExA(&wcex);
g_hWnd = CreateWindowA(szApp, nullptr, WS_POPUP | WS_CLIPCHILDREN | WS_CLIPSIBLINGS, 0, 0, nWidth, nHeight, NULL, NULL, wcex.hInstance, 0);
ShowWindow(g_hWnd, SW_SHOW);
UpdateWindow(g_hWnd);
MSG msg;
while (GetMessage(&msg, nullptr, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
其實基本就是模擬win sdk創建窗口的方式,只是將整個動作包含到一個線程里而已
std::thread t(CreateWndInThread, 960, 480); t.detach();
在需要的時候,啟動一個線程,執行創建,這個線程在while (GetMessage(&msg, nullptr, 0, 0))的循環中負責處理這個子線程窗口的事件循環即可
