一般來講,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))的循環中負責處理這個子線程窗口的事件循環即可