Search code examples
c++multithreadingwinapiconsolewindows-console

C++ Create New Window From Console in New Thread (Win32)


Working environment:

I am working in VS 2015, and a win32 console.

Overview:

I am creating a new window to act as a worker thread to perform some functions that cannot be completed in the console.

The code to create the new window and complete the tasks works well. However it freezes the console.

I have code to create a thread from the console and complete tasks while the console is not frozen. This also works well.

Problem:

I am unable to join the two pieces of code, I want to run the new window in the thread so it doesn't block the console.

Code:

=============== int main ======================

Start thread

x = 0;
hPrintMutex = CreateMutex(NULL, false, NULL);

HANDLE hThread1 = (HANDLE)_beginthread(printNumber, 0, &x);
WaitForSingleObject(hThread1, INFINITE);

Make new window

WNDCLASSEX wndclass = { sizeof(WNDCLASSEX), CS_DBLCLKS, WindowProcedure,
0, 0, GetModuleHandle(0), LoadIcon(0,IDI_APPLICATION),
LoadCursor(0,IDC_ARROW), HBRUSH(COLOR_WINDOW + 1),
0, myclass, LoadIcon(0,IDI_APPLICATION) };

if (RegisterClassEx(&wndclass))
{
    HWND window = CreateWindowEx(0, myclass, "title",
        WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT,
        CW_USEDEFAULT, CW_USEDEFAULT, 0, 0, GetModuleHandle(0), 0);
    if (window)
    {
        ShowWindow(window, SW_SHOWDEFAULT);
        MSG msg;
        while (GetMessage(&msg, 0, 0, 0)) DispatchMessage(&msg);
    }
}

======== outside main =======================================

code to do something in the new thread

( * The actual contents are just an example, they will be erased and replaced with the window code * )

void printNumber(void* pInt)
{

int* xp = (int*)pInt;
while (*xp<100)
{
    WaitForSingleObject(hPrintMutex, INFINITE);

    ++*xp;
    cout << *xp << endl;

    ReleaseMutex(hPrintMutex);
    Sleep(10);
}


}

code to create new window and do something

long __stdcall WindowProcedure(HWND window, unsigned int msg, WPARAM wp, LPARAM lp)
{
switch (msg)
{

case something: { 

}
default: 

    return DefWindowProc(window, msg, wp, lp);
}
}

Any thoughts? Thanks.

***** SOLUTION *****

See my posted solution below, tested and working.



Solution

  • Got this working, thought I would post it to help out others who are also starting out and having difficulties

    In your main start the thread

    HANDLE myhandle;
    
    myhandle = (HANDLE)_beginthreadex(0, 0, &mythread, 0, 0, 0);
    

    If your console runs in a loop then you don't need to call WaitForSingleObject, if it doesn't you will need to call it so the console doesn't close.

    Outside the main

    create the thread, and inside the thread you will create your window

    unsigned int __stdcall mythread(void* data)
    {
    
    cout << "/n created monitor window /n";
    
    const char* const myclass = "myclass";
    
    WNDCLASSEX wndclass = { sizeof(WNDCLASSEX), CS_DBLCLKS, WindowProcedure,
        0, 0, GetModuleHandle(0), LoadIcon(0,IDI_APPLICATION),
        LoadCursor(0,IDC_ARROW), HBRUSH(COLOR_WINDOW + 1),
        0, myclass, LoadIcon(0,IDI_APPLICATION) };
    
    if (RegisterClassEx(&wndclass))
    {
        HWND window = CreateWindowEx(0, myclass, "title",
            WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT,
            CW_USEDEFAULT, CW_USEDEFAULT, 0, 0, GetModuleHandle(0), 0);
        if (window)
        {
            ShowWindow(window, SW_SHOWDEFAULT);
            MSG msg;
            while (GetMessage(&msg, 0, 0, 0)) DispatchMessage(&msg);
        }
    }
    
    return 0;
    }
    

    also outside the main, the new window

    long __stdcall WindowProcedure(HWND window, unsigned int msg, WPARAM wp, LPARAM lp)
    { 
    switch (msg)
    {
    
    case checksomethinghere: { 
    
    }
    default: // fall thru 
    
        return DefWindowProc(window, msg, wp, lp);
    }
    }
    

    Now you can have your monitor window working in conjunction with your console, without blocking the console activity.

    Tested, and working well.

    From what I've read, you don't have to worry about calling CloseHandle for the created thread, because when the console is closed it will kill the thread and the window you created.

    In my scenario the window and thread remain alive for the entire time the console app is running.