0

我正在尝试在 C 中创建一个简单的 OpenGL 窗口,但我遇到了窗口本身的问题。创建了一个窗口,然后它突然消失了。我通过将“msg”归零来解决这个问题,但是窗口仍然试图退出并且所有其他消息都没有传递。所以我无法通过按 Escape 退出(未通过 WM_KEYDOWN)。渲染图形就像它应该的那样工作。有谁知道这是什么原因,以及如何解决?

入口点.c

#include "main.h"
#include "graphics.h"

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
{
    int breedte, hoogte;
    DEVMODE dmScreenSettings;
    HWND hWnd;
    WNDCLASSEX wcex;
    MSG msg;

    wcex.cbSize = sizeof(WNDCLASSEX);
    wcex.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
    wcex.lpfnWndProc = Actie;
    wcex.cbClsExtra = 0;
    wcex.cbWndExtra = 0;
    wcex.hInstance = hInstance;
    wcex.hIcon = LoadIcon(NULL,IDI_APPLICATION);
    wcex.hCursor = LoadCursor(NULL,IDC_ARROW);
    wcex.hbrBackground = (HBRUSH) GetStockObject(GRAY_BRUSH);
    wcex.lpszMenuName = NULL;
    wcex.lpszClassName = L"WinClass";
    wcex.hIconSm = NULL;
    breedte = GetSystemMetrics(SM_CXSCREEN);
    hoogte = GetSystemMetrics(SM_CYSCREEN);
    RegisterClassEx(&wcex);

    // Tijdelijk "nep" venster maken
    hWnd = CreateWindowEx(WS_EX_APPWINDOW, L"WinClass", L"My Window", WS_POPUP,
        0, 0, 640, 480, NULL, NULL, hInstance, NULL);
    if(hWnd == NULL) {
        MessageBox(NULL, L"Error: er kon geen venster worden gemaakt.", L"ERROR", MB_OK);
        return -1;
    }

    if (InitializeExtensions(hWnd) != 0) {
        MessageBox(NULL, L"Error: OpenGL extensies konden niet worden geladen.", L"ERROR", MB_OK);
        return -1;
    }

    // Tijdelijk venster verwijderen
    DestroyWindow(hWnd);

    if (FULLSCREEN == 1) {
        memset(&dmScreenSettings, 0, sizeof(dmScreenSettings));
        dmScreenSettings.dmSize       = sizeof(dmScreenSettings);
        dmScreenSettings.dmPelsWidth  = (unsigned long)breedte;
        dmScreenSettings.dmPelsHeight = (unsigned long)hoogte;
        dmScreenSettings.dmBitsPerPel = 32;         
        dmScreenSettings.dmFields     = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;
        ChangeDisplaySettings(&dmScreenSettings, CDS_FULLSCREEN);
        hWnd = CreateWindowEx(WS_EX_APPWINDOW, L"WinClass", L"My Window", WS_POPUP, 
            0, 0, breedte, hoogte, NULL, NULL, hInstance, NULL);
    }
    else {
        hWnd = CreateWindowEx(WS_EX_APPWINDOW, L"WinClass", L"My Window", WS_POPUP,  
            (breedte / 4), (hoogte / 4), (breedte / 2), (hoogte / 2), NULL, NULL, hInstance, NULL);
        breedte /= 2;
        hoogte /= 2;
    }

    if(hWnd == NULL) {
        MessageBox(NULL, L"Error: er kon geen venster worden gemaakt.", L"ERROR", MB_OK);
        return -1;
    }

    if (InitializeOpenGL(hWnd, breedte, hoogte, SCREEN_DEPTH, SCREEN_NEAR, VSYNC) != 0) {
        MessageBox(NULL, L"Error: OpenGL kon niet worden geïnitialiseerd", L"ERROR", MB_OK);
        return -1;
    }

    // Scherm laten zien
    ShowWindow(hWnd, SW_SHOW);
    UpdateWindow(hWnd);
    SetForegroundWindow(hWnd);
    SetFocus(hWnd);

    main_loop(&msg, hWnd);
    return msg.wParam;
}

主程序

#include "main.h"
#include "graphics.h"

void keyevent();

BYTE key_down[256];

LRESULT CALLBACK CALLBACK Actie(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
    switch (msg)
    {
    case WM_DESTROY:
        ShutdownOpenGL(hWnd);
        PostQuitMessage(0);
        return 0;
    case WM_KEYDOWN:
        key_down[(unsigned int)wParam] = 1;
        keyevent();
        return 0;
    case WM_KEYUP:
        key_down[(unsigned int)wParam] = 0;
        return 0;
    default:
        return DefWindowProc(hWnd, msg, wParam, lParam);
        break;
    }
}

void main_loop(MSG* msg, HWND hWnd)
{
    memset(key_down, 0, 256);
    memset(&msg, 0, sizeof(MSG));

    while (1) {
        if(PeekMessage(msg, NULL, 0, 0, PM_REMOVE)) {
            if(msg->message == WM_QUIT) 
                break;

            TranslateMessage(msg);  
            DispatchMessage(msg);
        }

        if (Render() != 0) {
            break;
        }
    }
}

void keyevent()
{
    if (key_down[VK_ESCAPE] == 1) {
        PostQuitMessage(0);
    }
}

主文件

#ifndef MAIN_HEADER

#define MAIN_HEADER
#define FULLSCREEN      1
#define VSCYNC          1
#define SCREEN_DEPTH    1000.0f
#define SCREEN_NEAR     0.1f

#include <Windows.h>

LRESULT CALLBACK CALLBACK Actie(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
void main_loop(MSG* msg, HWND hWnd);

#endif
4

1 回答 1

1
  1. 您的 ZeroMemory'ing 过多并且正在破坏您的堆栈。
  2. 当您销毁临时窗口时,它会调用PostQuitMessage,因为这是您在其WM_DESTROY处理程序中告诉它执行的操作。然后,您的消息循环会拾取该退出消息,这会导致它立即退出。
于 2013-02-03T17:03:14.713 回答