In one of my projects, I need to create a window in a non-main thread. I have never done that so I don't much experience on that.
According to the MSDN documentation and the SO question, I should be able to create a window in other thread, but I cannot succeed. Even though, in thread start routine, I register a window class, create a window and provide a message loop, the thread starts and exits immediately. In addition, I cannot debug the thread start routine so I cannot hit the break points inside it.
Is there something I am missing? I hope I don't miss anything silly.
Please consider the following demo. Thank you for taking your time.
#include <Windows.h>
#include <tchar.h>
HANDLE hThread;
DWORD WINAPI OtherUIThreadFunc(LPVOID args);
LRESULT CALLBACK WndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
HWND m_hwnd;
MSG msg;
WNDCLASSEX m_wcx;
const int MESSAGE_PROCESSED = 0;
const TCHAR* m_szClassName = _T("DemoWndCls");
const TCHAR* m_szWindowTitle = _T("Demo Window");
int WINAPI _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR szCmdLine, int nCmdShow)
{
hThread = CreateThread(NULL, NULL, (LPTHREAD_START_ROUTINE)OtherUIThreadFunc, hInstance, 0, NULL);
/*MSG msg;
ZeroMemory(&m_wcx, sizeof(m_wcx));
m_wcx.cbSize = sizeof(m_wcx);
m_wcx.style = CS_VREDRAW | CS_HREDRAW;
m_wcx.hInstance = hInstance;
m_wcx.lpszClassName = m_szClassName;
m_wcx.lpfnWndProc = WndProc;
m_wcx.hIcon = LoadIcon(NULL, IDI_APPLICATION);
m_wcx.hCursor = LoadCursor(NULL, IDC_ARROW);
m_wcx.hbrBackground = (HBRUSH)COLOR_WINDOW;
if (!RegisterClassEx(&m_wcx))
return false;
m_hwnd = CreateWindowEx(0, m_wcx.lpszClassName, m_szWindowTitle, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, 480, 360, NULL, NULL, hInstance, NULL);
if (!m_hwnd)
return false;
ShowWindow(m_hwnd, SW_NORMAL);
UpdateWindow(m_hwnd);
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;*/
}
DWORD WINAPI OtherUIThreadFunc(LPVOID args)
{
HINSTANCE hInstance = (HINSTANCE)args;
ZeroMemory(&m_wcx, sizeof(m_wcx));
m_wcx.cbSize = sizeof(m_wcx);
m_wcx.style = CS_VREDRAW | CS_HREDRAW;
m_wcx.hInstance = hInstance;
m_wcx.lpszClassName = m_szClassName;
m_wcx.lpfnWndProc = WndProc;
m_wcx.hIcon = LoadIcon(NULL, IDI_APPLICATION);
m_wcx.hCursor = LoadCursor(NULL, IDC_ARROW);
m_wcx.hbrBackground = (HBRUSH)COLOR_WINDOW;
if (!RegisterClassEx(&m_wcx))
return false;
m_hwnd = CreateWindowEx(0, m_wcx.lpszClassName, m_szWindowTitle, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, 480, 360, NULL, NULL, hInstance, NULL);
if (!m_hwnd)
return false;
ShowWindow(m_hwnd, SW_NORMAL);
UpdateWindow(m_hwnd);
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}
LRESULT WndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg)
{
case WM_CLOSE:
DestroyWindow(hwnd);
return MESSAGE_PROCESSED;
case WM_DESTROY:
PostQuitMessage(0);
return MESSAGE_PROCESSED;
default:
return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
}
CodePudding user response:
Window creation succeeds (in theory, anyway). The issue is that the primary thread moves one to return, which causes the runtime to terminate the process.
To solve the issue you will have to keep the primary thread alive. A call to WaitForSingleObject, or a message loop are possible options.
This is mostly a result of following the conventions of C and C . In either case returning from the main function is equivalent to calling the exit() function. This explains why returning from the primary thread tears down the entire process.
Bonus reading: If you return from the main thread, does the process exit?
