C++ WM_关闭事件从未发送/接收?

C++ WM_关闭事件从未发送/接收?,c++,windows,winapi,win32gui,C++,Windows,Winapi,Win32gui,我正在学习DX12,在此过程中,我还学习了“好的旧Win32”。 我无法退出主循环,这似乎与我没有收到WM_CLOSE消息有关 在C++、Windows 10、控制台应用程序中, #include <iostream> #include <d3d12.h> #include <dxgi1_4.h> #include <tchar.h> LRESULT WINAPI WndProc(HWND hWnd, UINT msg, WPARAM wPara

我正在学习DX12,在此过程中,我还学习了“好的旧Win32”。 我无法退出主循环,这似乎与我没有收到WM_CLOSE消息有关

在C++、Windows 10、控制台应用程序中,

#include <iostream>
#include <d3d12.h>
#include <dxgi1_4.h>
#include <tchar.h>

LRESULT WINAPI WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
    return ::DefWindowProc(hWnd, msg, wParam, lParam);
}


int main()
{
    std::cout << "Hello World!\n";

    WNDCLASSEX wc = {
        sizeof(WNDCLASSEX),
        CS_CLASSDC,
        WndProc,
        0L, 0L,
        GetModuleHandle(NULL),
        NULL, NULL, NULL, NULL,
        _T("ker engine"),
        NULL
    };

    std::cout << "Registering Class\n";
    ::RegisterClassEx(&wc);

    std::cout << "Creating Window\n";
    HWND hwnd = ::CreateWindow(
        wc.lpszClassName,
        _T("Ker Engine DX12"),
        WS_OVERLAPPEDWINDOW,
        100, 100, 1280, 800, NULL, NULL,
        wc.hInstance, NULL
    );

    std::cout << "Show Window\n";
    ::ShowWindow(hwnd, SW_SHOWDEFAULT);

    std::cout << "Update Window\n";
    ::UpdateWindow(hwnd);

    std::cout << "Entering main loop\n";
    MSG msg;
    ZeroMemory(&msg, sizeof(msg));

    while (msg.message != (WM_QUIT))
    {
        if (::PeekMessage(&msg, NULL, 0U, 0U, PM_REMOVE))
        {
            ::TranslateMessage(&msg);
            ::DispatchMessage(&msg);
            std::cout << msg.message << std::endl;
            switch (msg.message)
            {
            case WM_CLOSE:
                std::cout << "close received\n";
                ::PostQuitMessage(0);
                break;
            }
            continue;
        }

    }
    std::cout << "leaving main loop\n";

    std::cout << "Destroy Window\n";
    ::DestroyWindow(hwnd);
    std::cout << "Unregister Class\n";
    ::UnregisterClass(wc.lpszClassName, wc.hInstance);
    std::cout << "Bye\n";

    return 0;
}
没有WM_关闭,或WM_销毁,或WM_退出。在BUTTONDOW和计时器之间,应该有一个与窗口关闭相关的事件,不是吗

我是这方面的初学者。我试图搜索google和stackoverflow,但我不知道上下文是否适用于我,或者它太具体/不相关。可能是复制品,但我找不到


我是否正在丢失/跳过消息?这就是我所能想到的。

多亏了Simon Mourier的评论和教程链接,问题才得以解决

消息处理必须在WndProc中完成,而不是在“主循环”中完成

我正在重新发布修改、清理、工作的代码:

#include <iostream>
#include <d3d12.h>
#include <dxgi1_4.h>
#include <tchar.h>

LRESULT WINAPI WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
    switch (msg)
    {
    case WM_CLOSE:
        std::cout << "close received\n";
        ::PostQuitMessage(0);
        return 0;
    }
    return ::DefWindowProc(hWnd, msg, wParam, lParam);
}


int main()
{
    WNDCLASSEX wc = {
        sizeof(WNDCLASSEX),
        CS_CLASSDC,
        WndProc,
        0L, 0L,
        GetModuleHandle(NULL),
        NULL, NULL, NULL, NULL,
        _T("ker engine"),
        NULL
    };

    ::RegisterClassEx(&wc);

    HWND hwnd = ::CreateWindow(
        wc.lpszClassName,
        _T("Ker Engine DX12"),
        WS_OVERLAPPEDWINDOW,
        100, 100, 1280, 800, NULL, NULL,
        wc.hInstance, NULL
    );

    ::ShowWindow(hwnd, SW_SHOWDEFAULT);
    ::UpdateWindow(hwnd);

    MSG msg;
    ZeroMemory(&msg, sizeof(msg));
    while (msg.message != (WM_QUIT))
    {
        if (::PeekMessage(&msg, NULL, 0U, 0U, PM_REMOVE))
        {
            ::TranslateMessage(&msg);
            ::DispatchMessage(&msg);
        }    
    }
    ::DestroyWindow(hwnd);
    ::UnregisterClass(wc.lpszClassName, wc.hInstance);

    return 0;
}
#包括
#包括
#包括
#包括
LRESULT WINAPI WndProc(HWND HWND、UINT msg、WPARAM WPARAM、LPARAM LPARAM)
{
开关(msg)
{
案例WM_结束:

std::cout感谢Simon Mourier的评论和教程链接,问题得以解决

消息处理必须在WndProc中完成,而不是在“主循环”中完成

我正在重新发布修改、清理、工作的代码:

#include <iostream>
#include <d3d12.h>
#include <dxgi1_4.h>
#include <tchar.h>

LRESULT WINAPI WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
    switch (msg)
    {
    case WM_CLOSE:
        std::cout << "close received\n";
        ::PostQuitMessage(0);
        return 0;
    }
    return ::DefWindowProc(hWnd, msg, wParam, lParam);
}


int main()
{
    WNDCLASSEX wc = {
        sizeof(WNDCLASSEX),
        CS_CLASSDC,
        WndProc,
        0L, 0L,
        GetModuleHandle(NULL),
        NULL, NULL, NULL, NULL,
        _T("ker engine"),
        NULL
    };

    ::RegisterClassEx(&wc);

    HWND hwnd = ::CreateWindow(
        wc.lpszClassName,
        _T("Ker Engine DX12"),
        WS_OVERLAPPEDWINDOW,
        100, 100, 1280, 800, NULL, NULL,
        wc.hInstance, NULL
    );

    ::ShowWindow(hwnd, SW_SHOWDEFAULT);
    ::UpdateWindow(hwnd);

    MSG msg;
    ZeroMemory(&msg, sizeof(msg));
    while (msg.message != (WM_QUIT))
    {
        if (::PeekMessage(&msg, NULL, 0U, 0U, PM_REMOVE))
        {
            ::TranslateMessage(&msg);
            ::DispatchMessage(&msg);
        }    
    }
    ::DestroyWindow(hwnd);
    ::UnregisterClass(wc.lpszClassName, wc.hInstance);

    return 0;
}
#包括
#包括
#包括
#包括
LRESULT WINAPI WndProc(HWND HWND、UINT msg、WPARAM WPARAM、LPARAM LPARAM)
{
开关(msg)
{
案例WM_结束:

std::cout你的程序在做什么?作为用户你在用程序做什么?你在按windows关闭按钮吗?请尝试将你的代码简化为a并显示给我们。正确的代码应该是gist链接中的代码,但没有注释“links”指向文档或类似注释。此外,不鼓励指向代码的链接。链接可能会消失,或者内容可能会更改,这可能使问题无法回答。问题需要是自包含的。如果您有控制台应用程序,则不需要消息循环(除非你在做一些COM或其他东西,否则消息与窗口应用程序不同)。如果你有一个窗口应用程序,不要尝试重新发明轮子,只需从本教程开始:hooo,等等,我明白了。我已经有了这个WndProc函数。这是我应该将windows事件消息处理放在这里的地方,而不是放在循环中,对吗?是的!就是这样!我在WndProc中移动了开关,现在它可以工作了。而帮助只是一点点护航UTE,它确实解决了我的问题。thx你的程序在做什么?作为用户你在用程序做什么?你在按windows关闭按钮吗?请尝试将你的代码简化为a并显示给我们。正确的代码应该是gist链接中的代码,但没有注释“链接”指向文档或类似注释。此外,不鼓励指向代码的链接。链接可能会消失,或者内容可能会更改,这可能使问题无法回答。问题需要是自包含的。如果您有控制台应用程序,则不需要消息循环(除非你在做一些COM或其他东西,否则消息与窗口应用程序不同)。如果你有一个窗口应用程序,不要尝试重新发明轮子,只需从本教程开始:hooo,等等,我明白了。我已经有了这个WndProc函数。这是我应该将windows事件消息处理放在这里的地方,而不是放在循环中,对吗?是的!就是这样!我在WndProc中移动了开关,现在它可以工作了。而帮助只是一点点护航UTE,它确实解决了我的问题。thx脱离主题:
PeekMessage
将忙循环。有没有理由不使用
GetMessage
?虽然代码似乎可以工作,但它仍然有缺陷。PostQuitMessage应该用于最后一个窗口,因为它将停止消息循环(或者代码应该得到“我只有一个窗口”这样的注释)它应该对WM_DESTROY而不是WM_CLOSE做出反应:@Paul Sanders:不,没有理由。我会检查一下。谢谢。@simon:我确实有,确实只有一个窗口。但我会考虑它,并相应地修改(只要我理解其中的含义和区别)这可能会有帮助:脱离主题:
PeekMessage
将忙循环。有没有不使用
GetMessage
的理由?虽然代码似乎可以工作,但它仍然有缺陷。PostQuitMessage应该用于最后一个窗口,因为它将停止消息循环(或者代码应该加上“我只有一个窗口”这样的注释)它应该对WM_DESTROY而不是WM_CLOSE做出反应:@Paul Sanders:不,没有理由。我会检查一下。谢谢。@simon:确实,我只有一个窗口。但我会考虑到它,并相应地修改(一旦我理解其含义和区别),这可能会有所帮助: