WINAPI- WM_QUIT消息未被发送

时间:2017-07-22 12:15:55

标签: winapi event-handling message-queue

我有一个回调函数:

LRESULT CALLBACK MainWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) {
    if(msg == WM_DESTROY || msg == WM_CLOSE) {
        std::cout << "Close or get DESTROYED!\n";
    }
    if(g_mApp)
        return g_mApp->MsgProc(hwnd, msg, wParam, lParam);
    else
        return DefWindowProc(hwnd, msg, wParam, lParam);
}

然而,&#34;关闭或被摧毁&#34;单击X按钮或按Alt + F4时不打印。事实上,我无法通过鼠标移动窗口!

其他一些功能:

int GLApp::run() {

    __int64 prevTime = 0;
    QueryPerformanceCounter((LARGE_INTEGER*)&prevTime);

    __int64 countsPerSec = 0;
    QueryPerformanceCounter((LARGE_INTEGER*)&countsPerSec);
    float secondsPerCount = 1.0f / countsPerSec;
    MSG msg = {0};
    while(msg.message != WM_QUIT) {
        if(!PeekMessage(&msg, NULL, NULL, NULL, PM_REMOVE)) {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
        else {
            __int64 curTime = 0;
            QueryPerformanceCounter((LARGE_INTEGER*)&curTime);
            float deltaTime = (curTime - prevTime) * secondsPerCount;
            update(deltaTime);
            render();
            calculateFPS(deltaTime);

            prevTime = curTime;
        }
    }

    shutdown();

    return static_cast<int>(msg.wParam);
}

bool GLApp::initWindow() {
    WNDCLASSEX wcex;
    ZeroMemory(&wcex, sizeof(WNDCLASSEX));
    wcex.cbClsExtra = 0;
    wcex.cbWndExtra = 0;
    wcex.cbSize = sizeof(WNDCLASSEX);
    wcex.style = CS_HREDRAW | CS_VREDRAW;
    wcex.hInstance = m_hAppInstance;
    wcex.lpfnWndProc = MainWndProc;
    wcex.hIcon = LoadIcon(NULL, IDI_APPLICATION);
    wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
    wcex.hbrBackground = (HBRUSH)GetStockObject(NULL_BRUSH);
    wcex.lpszClassName = "GLAPPWNDCLASS";
    wcex.lpszMenuName = NULL;
    wcex.hIconSm = LoadIcon(NULL, IDI_APPLICATION);

    if(!RegisterClassEx(&wcex)) {
        return outErrorMessage("Failed to register GLAPPWNDCLASS");
    }

    // ADJUST WINDOW RECT FOR REQUESTED CLIENT SIZE
    RECT r;
    r.left = r.top = 0;
    r.right = m_ClientWidth;
    r.bottom = m_ClientHeight;
    AdjustWindowRect(&r, m_WindowStyle, FALSE);
    int width = r.right - r.left;
    int height = r.bottom - r.top;
    int x = GetSystemMetrics(SM_CXSCREEN)/2 - width / 2;
    int y = GetSystemMetrics(SM_CYSCREEN)/2 - height / 2;

    m_hAppWnd = CreateWindow("GLAPPWNDCLASS", m_AppTitle, m_WindowStyle, x, y, width, height, NULL, NULL, m_hAppInstance, NULL);
    if(!m_hAppWnd) return outErrorMessage("Failed to create window from GLAPPWNDCLASS");

    ShowWindow(m_hAppWnd, SW_SHOW);

    return true;
}    

g_mApp是我自己的实现窗口的对象。 initWindow()run()仅分别调用一次。全班,如果你愿意:

#include "GLApp.h"
#include <iostream>
namespace {
    GLApp* g_mApp = NULL;
}

LRESULT CALLBACK MainWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) {
    if(msg == WM_DESTROY || msg == WM_CLOSE) {
            std::cout << "Close or get DESTROYED!\n";
    }
    if(g_mApp)
        return g_mApp->MsgProc(hwnd, msg, wParam, lParam);
    else
        return DefWindowProc(hwnd, msg, wParam, lParam);
}

GLApp::GLApp(void)
{

}

GLApp::GLApp(HINSTANCE hInstance) {
    m_hAppInstance = hInstance;
    m_hAppWnd = NULL;
    m_hDevContext = NULL;
    m_hGLRenderContext = NULL;
    m_ClientWidth = 800;
    m_ClientHeight = 600;
    m_AppTitle = "OpenGL Application";
    m_WindowStyle = WS_OVERLAPPED | WS_SYSMENU | WS_CAPTION | WS_MINIMIZEBOX;
    m_FPS = 0.0f;
    g_mApp = this;
}

GLApp::~GLApp()
{
}

int GLApp::run() {

    __int64 prevTime = 0;
    QueryPerformanceCounter((LARGE_INTEGER*)&prevTime);

    __int64 countsPerSec = 0;
    QueryPerformanceCounter((LARGE_INTEGER*)&countsPerSec);
    float secondsPerCount = 1.0f / countsPerSec;
    MSG msg = {0};
    while(msg.message != WM_QUIT) {
        if(!PeekMessage(&msg, NULL, NULL, NULL, PM_REMOVE)) {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
        else {
            __int64 curTime = 0;
            QueryPerformanceCounter((LARGE_INTEGER*)&curTime);
            float deltaTime = (curTime - prevTime) * secondsPerCount;
            update(deltaTime);
            render();
            calculateFPS(deltaTime);

            prevTime = curTime;
        }
    }

    shutdown();

    return static_cast<int>(msg.wParam);
}

bool GLApp::init() {
    return initWindow() && initGL();
}

bool GLApp::initWindow() {
    WNDCLASSEX wcex;
    ZeroMemory(&wcex, sizeof(WNDCLASSEX));
    wcex.cbClsExtra = 0;
    wcex.cbWndExtra = 0;
    wcex.cbSize = sizeof(WNDCLASSEX);
    wcex.style = CS_HREDRAW | CS_VREDRAW;
    wcex.hInstance = m_hAppInstance;
    wcex.lpfnWndProc = MainWndProc;
    wcex.hIcon = LoadIcon(NULL, IDI_APPLICATION);
    wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
    wcex.hbrBackground = (HBRUSH)GetStockObject(NULL_BRUSH);
    wcex.lpszClassName = "GLAPPWNDCLASS";
    wcex.lpszMenuName = NULL;
    wcex.hIconSm = LoadIcon(NULL, IDI_APPLICATION);

    if(!RegisterClassEx(&wcex)) {
        return outErrorMessage("Failed to register GLAPPWNDCLASS");
    }

    // ADJUST WINDOW RECT FOR REQUESTED CLIENT SIZE
    RECT r;
    r.left = r.top = 0;
    r.right = m_ClientWidth;
    r.bottom = m_ClientHeight;
    AdjustWindowRect(&r, m_WindowStyle, FALSE);
    int width = r.right - r.left;
    int height = r.bottom - r.top;
    int x = GetSystemMetrics(SM_CXSCREEN)/2 - width / 2;
    int y = GetSystemMetrics(SM_CYSCREEN)/2 - height / 2;

    m_hAppWnd = CreateWindow("GLAPPWNDCLASS", m_AppTitle, m_WindowStyle, x, y, width, height, NULL, NULL, m_hAppInstance, NULL);
    if(!m_hAppWnd) return outErrorMessage("Failed to create window from GLAPPWNDCLASS");

    ShowWindow(m_hAppWnd, SW_SHOW);

    return true;
}

bool GLApp::initGL() {
    // CREATE OUR DEVICE CONTEXT
    m_hDevContext = GetDC(m_hAppWnd);

    // CREATE PIXEL FORMAT DESCRIPTOR
    PIXELFORMATDESCRIPTOR pfd;
    ZeroMemory(&pfd, sizeof(PIXELFORMATDESCRIPTOR));
    pfd.nSize = sizeof(PIXELFORMATDESCRIPTOR);
    pfd.nVersion = 1;
    pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
    pfd.iPixelType = PFD_TYPE_RGBA;
    pfd.cColorBits = 32;
    pfd.cDepthBits = 24;
    pfd.cStencilBits = 8;
    int format = ChoosePixelFormat(m_hDevContext, &pfd);
    if(!SetPixelFormat(m_hDevContext, format, &pfd)) {
        return outErrorMessage("Failed to set pixel format");
    }

    // CREATE RENDER CONTEXT
    m_hGLRenderContext = wglCreateContext(m_hDevContext);
    if(!wglMakeCurrent(m_hDevContext, m_hGLRenderContext)) {
        return outErrorMessage("Failed to create and activate render context");
    }

    // INITIALIZE GLEW
    if(glewInit() != GLEW_OK) {
        return outErrorMessage("Failed to initialize GLEW");
    }

    return true;
}

LRESULT GLApp::MsgProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) {
    switch(msg) {
    case WM_CLOSE: {
        DestroyWindow(hwnd);
        return 0;
    }
    case WM_DESTROY: {
        PostQuitMessage(0);
        return 0;
    }
    default:
        return DefWindowProc(hwnd, msg, wParam, lParam);
    }
}

void GLApp::calculateFPS(float dt) {

}

void GLApp::shutdown() {
    wglMakeCurrent(NULL, NULL);
    wglDeleteContext(m_hGLRenderContext);
    ReleaseDC(m_hAppWnd, m_hDevContext);
}

这是如何实施的:

#include "GLApp.h"
#include <iostream>

class TestApp : public GLApp {
public:
    TestApp(HINSTANCE hInstance);
    ~TestApp();

    // OVERRIDES
    bool init() override;
    void update(float dt) override;
    void render() override;
    LRESULT MsgProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) override;
};

TestApp::TestApp(HINSTANCE hInstance) : GLApp(hInstance) {

}

TestApp::~TestApp() {}

bool TestApp::init() {
    return GLApp::init();
}

void TestApp::update(float dt) {

}

void TestApp::render() {

}

LRESULT TestApp::MsgProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) {
    switch(msg) {
    default:
        return GLApp::MsgProc(hwnd, msg, wParam, lParam);
    }
}

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE prevInstance, LPSTR lpCmdLine, int nCmdShow) {
    TestApp app(hInstance);
    if(!app.init()) {
        return 1;
    }

    return app.run();

}

bool outErrorMessage(const char* message) {
    MessageBox(NULL, message, NULL, MB_OK);
    return false;
}

1 个答案:

答案 0 :(得分:2)

!PeekMessage错误,如果它返回非零,则会收到您需要处理的消息。