当我尝试将OpenGL渲染为静态控件时,为什么我的Win32应用程序几乎崩溃了我的计算机?

时间:2011-12-01 01:17:34

标签: winapi opengl rendering

我有一个带有静态控件的Win32应用程序,我想使用OpenGL渲染它。问题是,当我运行应用程序时,我的计算机突然停止,现在不止一次,我不得不重新启动它。它需要不到一秒钟,它真的很残酷。我的大部分代码都是从互联网或我的OpenGL蓝皮书中删除的。我尝试过其他几种方法,一些具有相同的结果,一些具有不同但不太理想的结果,包括使静态控件所有者绘制,子类化静态控件,以及只是渲染到它的父级的控件(主要的)窗口)WM_PAINT消息。我甚至没有渲染任何几何体,我只想看到清晰的颜色。我在网上找到的大多数资源(如果不是全部)都不包括渲染到控件或使用MFC而不是本机Win32 API调用。

我已经确定它只会发生,因为我正在调用glClear()。如果我不打电话,我没有经历减速,但我也没有看到静电控制中的任何内容。

更多信息:

  • Visual Studio 2010 Ultimate
  • Windows SDK v7.0a
  • GLEW 1.7
  • 带有最新驱动程序的nVidia Quadro 1600M
  • Windows 7 x64 Ultimate

这是我的代码:

#define WINVER 0x0600
#define _WIN32_WINNT 0x0600
#define GLEW_STATIC
#include <windows.h>
#include <gl\glew.h>
#include <gl\wglew.h>
#include <Uxtheme.h>
#include <commctrl.h>
#include <tchar.h>
#include "resource.h"
//#define WIN32_LEAN_AND_MEAN

#define IDC_THE_BUTTON 9001

#pragma comment(linker,"\"/manifestdependency:type='win32' \
name='Microsoft.Windows.Common-Controls' version='6.0.0.0' \
processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"")

struct GlobalSection
{
    HINSTANCE   app;
    HWND        wnd;
    HWND        button;
    HWND        panel;
    HWND        text;
    HGLRC       glrc;
    HDC         fdc;
} g;

bool initWindow(int cmdShow);
LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam);
void Init(HWND wnd);
void Render();

int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR lpCmd, int nCmdShow)
{
    g.app = hInst;

    INITCOMMONCONTROLSEX iccex;
    iccex.dwSize = sizeof(iccex);
    iccex.dwICC = ICC_BAR_CLASSES|ICC_COOL_CLASSES|ICC_LISTVIEW_CLASSES|ICC_PROGRESS_CLASS|ICC_STANDARD_CLASSES|ICC_TAB_CLASSES;
    InitCommonControlsEx(&iccex);

    initWindow(nCmdShow);

    MSG m;
    ZeroMemory(&m, sizeof(m));
    while(m.message != WM_QUIT)
    {
        Render();

        if(PeekMessage(&m, NULL, 0, 0, PM_REMOVE) && !IsDialogMessage(g.wnd, &m))
        {
            TranslateMessage(&m);
            DispatchMessage(&m);
        }
    }
}

bool initWindow(int cmdShow)
{
    WNDCLASSEX wc;
    ZeroMemory(&wc, sizeof(wc));
    wc.cbSize = sizeof(wc);
    wc.lpfnWndProc = (WNDPROC)WndProc;
    wc.lpszClassName = _T("Window Party");
    wc.hInstance = g.app;
    wc.hbrBackground = (HBRUSH)COLOR_WINDOW;
    wc.lpszMenuName = MAKEINTRESOURCE(IDR_MENU1);
    wc.hIcon = LoadIcon(g.app, MAKEINTRESOURCE(IDI_ICON2));
    wc.hIconSm = wc.hIcon;
    RegisterClassEx(&wc);

    g.wnd = CreateWindowEx(WS_EX_CLIENTEDGE, _T("Window Party"), _T("Window Party"), WS_SYSMENU|WS_CLIPCHILDREN|WS_OVERLAPPED, CW_USEDEFAULT, CW_USEDEFAULT, 1280, 800, NULL, NULL, g.app, NULL);

    ShowWindow( g.wnd, cmdShow );                           // technically should be nCmdShow

    return true;
}

LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
{
    switch(message)
    {
    case WM_CREATE:
        Init(hwnd);
        return DefWindowProc(hwnd, message, wparam, lparam);
    case WM_DESTROY:
        PostQuitMessage(0);
        break;
    case WM_COMMAND:
        {
            int wmId    = LOWORD(wparam);
            int wmEvent = HIWORD(wparam);
            switch(wmId)
            {
            case IDM_FILE_CLOSE:
                PostQuitMessage(0);
                break;
            case IDOK:
            case IDC_THE_BUTTON:
                {
                    MessageBox(hwnd, _T("You have pressed the button!"), _T("Congraturation"), MB_OK);
                }
                break;
            default:
                return DefWindowProc(hwnd, message, wparam, lparam);
            }
        }
        break;
    case WM_KEYDOWN:
        {
            TCHAR buff[64] = {0};
            wsprintf(buff, _T("Key Pressed: 0x%X"), (unsigned)wparam);
            MessageBox(hwnd, buff, _T("YOYOYO"), MB_OK);
            break;
        }
    default:
        return DefWindowProc(hwnd, message, wparam, lparam);
    }

    return 0;
}

void Init(HWND wnd)
{
    //Creating controls
    RECT cr;
    GetClientRect(wnd, &cr);
    g.panel = CreateWindow(_T("STATIC"), NULL, WS_CHILDWINDOW|WS_VISIBLE|CS_OWNDC|CS_VREDRAW|CS_HREDRAW, 0, 0, cr.right, cr.bottom-26, wnd, NULL, g.app, NULL);
    g.button = CreateWindow(_T("BUTTON"), _T("The Button"), WS_CHILDWINDOW|BS_DEFPUSHBUTTON|WS_VISIBLE, cr.right-160, cr.bottom-26, 160, 26, wnd, (HMENU)IDC_THE_BUTTON, g.app, NULL);
    g.text = CreateWindowEx(WS_EX_CLIENTEDGE, _T("EDIT"), NULL, WS_CHILDWINDOW|ES_LEFT|WS_VISIBLE, 0, cr.bottom-26, cr.right-160, 26, wnd, NULL, g.app, NULL);

    //Setting fonts
    HFONT hf = NULL;
    hf = (HFONT)GetStockObject(DEFAULT_GUI_FONT);
    SendMessage(g.button, WM_SETFONT, (WPARAM)hf, TRUE);
    SendMessage(g.text, WM_SETFONT, (WPARAM)hf, TRUE);

    //Creating wgl context
    g.fdc = GetDC(g.panel);
    PIXELFORMATDESCRIPTOR pfd = {0};
    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 = 16;
    pfd.cStencilBits = 8;

    SetPixelFormat(g.fdc, 1, &pfd);
    g.glrc = wglCreateContext(g.fdc);
    wglMakeCurrent(g.fdc, g.glrc);

    RECT pcr;
    GetClientRect(g.panel, &pcr);
    glViewport(0, 0, pcr.right, pcr.bottom);

    glewInit();

    glClearColor(0.0, 0.0, 0.0, 1.0);

    UpdateWindow(wnd);
}

void Render()
{
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    SwapBuffers(g.fdc);
}

2 个答案:

答案 0 :(得分:2)

您不得为每一个窗口消息调用Render()!仅针对WM_PAINT消息致电Render()

答案 1 :(得分:0)

这听起来像某处的内存泄漏。如果PF使用率过高,计算机将会突然停止。

打开任务管理器,在运行程序之前,然后再查看PF使用情况。如果它跳起来.5GB或更多,并继续攀爬,那么你手上的内存泄漏。

如果它以上述方式运行,最可能的罪魁祸首是您要么多次制作一个新对象(或纹理),导致Windows需要为您分配更多的PF空间,或者您可以关闭VSYNC 。

我可能不必告诉你内存泄漏会发生什么,但是当VSYNC关闭时,程序将尝试以CPU允许的速度运行。它将最大化你的CPU,它会快速完成。

希望这有帮助。