c ++ Win32 Api GetMessage在线程内关闭程序

时间:2017-05-15 08:41:30

标签: c++ multithreading winapi getmessage

我正在使用win32 api构建一个接口,我想管理另一个类中的所有后缀,并使用一个线程继续在main中工作。 我有这段代码:

WindowManager.h

class UIManager::WindowManager {
private:
    //Class data
    HINSTANCE hInstance;
    WNDCLASSEX winClass; /* Data structure for the windowclass */
    MSG msg;
    HWND hwnd;
    //Window Data
    LPCSTR wiName;
    int startX = 250;
    int startY = 150;
    int endX = 544;
    int endY = 375;
    //Private managers
    void makeWindow();
public:
    WindowManager(HINSTANCE & hInstance, std::string wiName = "Window Name");
    void show();
};

WindowManager.c (我使用bind,因为我在命名空间中有类,这是我发现该线程允许我编译而不是抛出错误的唯一方法)

#include "WindowManager.h"

LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);

//Private
//
void UIManager::WindowManager::makeWindow()
{
    int ms = GetMessage(&msg, 0, 0, 0); //I do this to see if it gets to
    while (GetMessage(&msg, NULL, 0, 0)) { //this part, but never happens
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }
}

//Public
//
UIManager::WindowManager::WindowManager(HINSTANCE & hInstance, std::string wiName)
{
    this->wiName = wiName.c_str();
    this->hInstance = hInstance;
    winClass.cbSize = sizeof(winClass);
    winClass.hInstance = hInstance;
    winClass.lpszClassName = this->wiName;
    winClass.lpfnWndProc = WndProc; //Execution callback
    //Load default editable ellements
    winClass.hCursor = LoadCursor(0, IDC_ARROW);        /*Default*/
    winClass.hIcon = LoadIcon(NULL, IDI_APPLICATION);   /*Default*/     //Alt+Tab Dialog
    winClass.hbrBackground = GetSysColorBrush(COLOR_3DFACE);
    winClass.lpszMenuName = NULL;                       /* No menu */
    RegisterClassEx(&winClass);

    //Create Window
    hwnd = CreateWindowEx(
        0,
        this->wiName,           /* Title Class */
        this->wiName,           /* Title Text */
        WS_OVERLAPPED | WS_MINIMIZEBOX | WS_SYSMENU | WS_VISIBLE | WS_OVERLAPPEDWINDOW,
        startX,                         /* X Start */
        startY,                         /* Y Start */
        endX,                           /* The programs width */
        endY,                           /* and height in pixels */
        HWND_DESKTOP,                   /* The window is a child-window to desktop */
        NULL,                           /* No menu */
        hInstance,              /* Program Instance handler */
        NULL
    );
    SetWindowPos(hwnd, 0, 0, 0, 20, 20, 0);
}

void UIManager::WindowManager::show()
{
    std::thread listener(std::bind(&WindowManager::makeWindow, this));
    listener.detach();
}

LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
    switch (msg)
    {
    case WM_CREATE:
    { //This part is executed
        //...blablabla
        break;
    }

    case WM_COMMAND:
    {//This part is never executed
        //...blablabla
        break;
    }

    case WM_DESTROY:
    {//This part is never executed
        //...blabla
        PostQuitMessage(0);
        break;
    }
    }
    return DefWindowProc(hwnd, msg, wParam, lParam);
}

窗口执行并正确显示甚至执行WM_CREATE,但是当" GetMessage"执行它会立即结束程序而不会抛出任何错误或类似的东西。

我添加了一个带有GetMessage值的int,以查看它是否到达"而#34;在调试模式下但它发生了。 有没有办法看到可能抛出或阻止它关闭程序的错误?或者是我做错了调用" GetMessage"从一个线程?

1 个答案:

答案 0 :(得分:0)

您的代码有几个问题:

  • 您在一个线程中创建窗口,但尝试在另一个线程中运行meesage循环。 GetMessage仅处理属于调用线程的窗口的消息。
  • 你永远不会等待后台线程处理消息,而是从它分离并继续在主线程可能结束应用程序中执行。
  • 您不检查GetMessage返回的值并将其用作布尔值。

如果你想制作背景ui线程,你需要在那里移动所有窗口创建代码并在线程上调用join。消息循环应该如下所示:

::MSG msg;
for(;;)
{
    auto const res{::GetMessage(&msg, NULL, 0, 0))};
    if(0 < res)
    {
        ::TranslateMessage(&msg);
        ::DispatchMessage(&msg);
    }
    else if(0 == res)
    {   //  PostQuitMessage was called...
        break;
    }
    else
    {   //  an error occurred...
        break;
    }
}