C++ 在新线程中从控制台新建 Window (Win32)

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

工作环境:

我在 VS 2015 和 win32 控制台中工作。

概览:

我正在创建一个新的 window 作为工作线程来执行一些无法在控制台中完成的功能。

创建新 window 和完成任务的代码运行良好。但是它冻结了控制台。

我有代码从控制台创建线程并在控制台未冻结时完成任务。这也很好用。

问题:

我无法加入这两段代码,我想 运行 线程中的新 window 这样它就不会阻塞控制台。

代码:

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

开始线程

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

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

新建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);
    }
}

======== 在主线之外 ========================= ==============

在新线程中执行某些操作的代码

( * 实际内容仅为示例,将被删除并替换为 window 代码 * )

void printNumber(void* pInt)
{

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

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

    ReleaseMutex(hPrintMutex);
    Sleep(10);
}


}

用于创建新 window 并执行某些操作的代码

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

case something: { 

}
default: 

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

有什么想法吗?谢谢。

***** 解决方案 *****

请参阅下面我发布的解决方案,该解决方案经过测试并且可以正常工作。


得到这个工作,我想我会 post 帮助其他同样刚起步并遇到困难的人

在你的主线程中启动

HANDLE myhandle;

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

如果您的控制台在循环中运行,那么您不需要调用 WaitForSingleObject,否则您将需要调用它,这样控制台就不会关闭。

外主

创建线程,并在线程内创建您的 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;
}

还外主,新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);
}
}

现在您可以让您的监视器 window 与您的控制台一起工作,而不会阻塞控制台 activity。

已经过测试,运行良好。

根据我的阅读,您不必担心为创建的线程调用 CloseHandle,因为当控制台关闭时它会终止线程和您创建的 window。

在我的场景中,window 和线程在控制台应用 运行 的整个时间内保持活动状态。

是否可以向 UI 线程发送消息?

完整示例 + PostMessage 到 UI 线程 ?

#include <Windows.h>
#include <process.h>

UINT test_message = 0;
long __stdcall WindowProcedure(HWND window, unsigned int msg, WPARAM wp, LPARAM lp)
{
    if (test_message == msg) {
        printf("Got it !\n"); // to console
        return 0;
    }
    else
        return DefWindowProc(window, msg, wp, lp);
}
static HWND window = NULL;
void SendMeMessage(HWND _window)
{
    window = _window;
    test_message = RegisterWindowMessage("TEST");
    PostMessage(window, test_message, 0, 0);
}

unsigned int __stdcall mythread(void* data)
{
    const LPCSTR 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))
    {
        window = CreateWindowEx(0, myclass, "title",
            WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT,
            CW_USEDEFAULT, CW_USEDEFAULT, 0, 0, GetModuleHandle(0), 0);
        if (window)
        {
            SendMeMessage(window);
            ShowWindow(window, SW_SHOWDEFAULT);
            MSG msg;
            while (GetMessage(&msg, 0, 0, 0)) DispatchMessage(&msg);
        }
    }

    return 0;
}

int main()
{
    HANDLE myhandle;

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