我有一个带有静态控件的Win32应用程序,我想使用OpenGL渲染它。问题是,当我运行应用程序时,我的计算机突然停止,现在不止一次,我不得不重新启动它。它需要不到一秒钟,它真的很残酷。我的大部分代码都是从互联网或我的OpenGL蓝皮书中删除的。我尝试过其他几种方法,一些具有相同的结果,一些具有不同但不太理想的结果,包括使静态控件所有者绘制,子类化静态控件,以及只是渲染到它的父级的控件(主要的)窗口)WM_PAINT消息。我甚至没有渲染任何几何体,我只想看到清晰的颜色。我在网上找到的大多数资源(如果不是全部)都不包括渲染到控件或使用MFC而不是本机Win32 API调用。
我已经确定它只会发生,因为我正在调用glClear()。如果我不打电话,我没有经历减速,但我也没有看到静电控制中的任何内容。
更多信息:
这是我的代码:
#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);
}
答案 0 :(得分:2)
您不得为每一个窗口消息调用Render()
!仅针对WM_PAINT消息致电Render()
。
答案 1 :(得分:0)
这听起来像某处的内存泄漏。如果PF使用率过高,计算机将会突然停止。
打开任务管理器,在运行程序之前,然后再查看PF使用情况。如果它跳起来.5GB或更多,并继续攀爬,那么你手上的内存泄漏。
如果它以上述方式运行,最可能的罪魁祸首是您要么多次制作一个新对象(或纹理),导致Windows需要为您分配更多的PF空间,或者您可以关闭VSYNC 。
我可能不必告诉你内存泄漏会发生什么,但是当VSYNC关闭时,程序将尝试以CPU允许的速度运行。它将最大化你的CPU,它会快速完成。
希望这有帮助。