【问题标题】:Win32 window gets closed immediatelyWin32 窗口立即关闭
【发布时间】:2014-03-07 19:44:57
【问题描述】:

我试图通过我的应用程序显示一个简单的 win32 窗口,但该窗口没有显示。程序将立即退出,因为通过消息泵发送了WM_DESTROY 消息。 以下是相关代码:

    WNDCLASSEX wClass; //window class structur
    wClass.hInstance = appInstance;
    wClass.lpszClassName = CLASSNAME;
    wClass.lpfnWndProc = WindowProc;
    wClass.style = CS_HREDRAW | CS_VREDRAW;
    wClass.cbSize = sizeof(WNDCLASSEX);
    wClass.hIcon = NULL;
    wClass.hCursor = LoadCursor(NULL, IDC_ARROW);
    wClass.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
    wClass.lpszMenuName = NULL;
    wClass.hbrBackground = NULL;
    wClass.cbClsExtra = 0;
    wClass.cbWndExtra = 0;
    if (!RegisterClassEx(&wClass))
    {
        Debug::getInstance().log("Faild to create Window Class", EDEBUG_LEVEL::E_ERROR);
        //throw some errors
        return;
    }


    windowHandle = CreateWindowEx(
        NULL,
        CLASSNAME,
        title.c_str(), //real window title
        WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX,
        position.x, position.y,
        size.x, size.y,
        NULL,
        NULL,
        appInstance,
        NULL
        );
    if (windowHandle == NULL)
    {
        Debug::getInstance().log("CreateWindow failed.", EDEBUG_LEVEL::E_ERROR);
    }

在此代码中,appInstance 是来自条目 WinMain 函数的 hInstance。我已经调试了这段代码,但这里似乎没有任何问题。

这是我的 WndProc:

LRESULT CALLBACK WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    // sort through and find what code to run for the message given
    switch (message)
    {
        // this message is read when the window is closed
    case WM_DESTROY:
    {
                       // close the application entirely
                       PostQuitMessage(0);
                           return 0;
    } break;
    }

    // Handle any messages the switch statement didn't
    return DefWindowProc(hWnd, message, wParam, lParam);
}

还有我的信息泵:

   while (TRUE) {
        while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }

        if (msg.message == WM_QUIT) {
            break;
        }
    }

调试WndProc 函数后,我发现WM_DESTROYWM_CREATE 和0x0090 之后发送(我不知道这是什么意思)。 我做错了什么?

哦,忘了说。在我创建我的窗口后,这也会被执行:

    ShowWindow(windowHandle, SW_SHOW);
    UpdateWindow(windowHandle);
    SetFocus(windowHandle);

编辑:经过进一步调查,我发现问题似乎是由构造函数调用窗口构建方法引起的:

Window::Window(HINSTANCE thisInstance, DirectX::XMINT2 size, wstring title, bool enableFullscreen) :
appInstance(thisInstance),
position(0, 0),
size(size),
#ifdef UNICODE
title(title),
#else
title(string(title.begin(), title.end())),
#endif
fullscreen(false)
{
    this->buildWindow();
    if (fullscreen)
        setFullscreenWindowed(true);
}

this->buildWindow() 是我发布的第一个代码。如果我将buildWindow() 作为另一个类的公共成员方法调用,它就可以正常工作。 这里有什么问题?它不是虚拟功能。 Window 不继承或实现另一个类。

【问题讨论】:

  • 您的消息泵异常。它通常是这样的:while(::GetMessage(&Msg, NULL, 0, 0) > 0) { ::TranslateMessage(&Msg); ::DispatchMessage(&Msg); }。您可以尝试用这个替换您现有的泵并报告结果吗?
  • @AlwaysLearningNewStuff 这看起来像一个典型的游戏循环消息泵;游戏处理将在 PeekMessage() 循环之后完成。
  • @puelo - 这是你的全部代码吗?听起来 WM_DESTROY 上面的 case 语句可能缺少一个中断。
  • @HerrJoebob:在我看来也是如此,但我不确定。尽管如此,我认为没有什么是错的。也许这不是实际代码,他有if (msg.message = WM_QUIT) 而不是if (msg.message == WM_QUIT)
  • 如果PeekMessageWM_QUIT 之后在其循环中检索其他消息,那么您将错过它,使用上述逻辑。此外,如果队列中根本没有消息,那么当您进行比较时,msg 可能未初始化。

标签: c++ winapi window


【解决方案1】:

我发现了问题所在。可悲的是,因为我认为这并不重要,所以我没有将这行代码放在我的问题中。 问题是类的初始化,因为我没有定义复制构造函数。

Window mainWindow = Window(...)

导致窗口实例未注册,因为在对象被复制构造函数复制后,原始对象被破坏,并且我在我的析构函数中有一个对 UnregisterClass(..) 的方法调用。

使用:

 Window mainWindow(..)

解决了问题。

【讨论】:

    猜你喜欢
    • 2021-05-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-02-24
    • 2020-11-08
    • 2015-01-23
    • 1970-01-01
    相关资源
    最近更新 更多