在WndProc的WM_CREATE中的OpenGL – > wglCreateContext,wglMakeCurrent使渲染失败

操作系统:Windows 7,64位Visual Studio 2010,debugging,32位

我正在尝试一个简单的Windows程序来开始使用OpenGL:所有的程序应该做的是用glClear(GL_COLOR_BUFFER_BIT)清除颜色缓冲区。

在网上find的教程中,我发现人们在创build窗口期间(以及在处理WM_CREATE消息的过程中)创build和设置openGL上下文。 不知何故,我发现这不适合我的代码,我似乎无法弄清楚。 所以如果有人能指出我的正确方向。

请在下面find代码我期望它应该基于教程工作:

#include <windows.h> #include <GL\glew.h> #include <GL\wglew.h> #include "Application.h" HWND ghMainWnd = 0; bool InitWindowsApp(HINSTANCE instanceHandle, int show); int Run(); LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam); HDC hDC; HGLRC hGLRC; HPALETTE hPalette; void SetupPixelFormat() { PIXELFORMATDESCRIPTOR pfd = {}; 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 = 24; pfd.cAlphaBits = 8; pfd.cDepthBits = 32; pfd.iLayerType = PFD_MAIN_PLANE; int pixelFormat = ChoosePixelFormat(hDC, &pfd); if(pixelFormat == 0) { MessageBox(ghMainWnd, L"ChoosePixelFormat() failed", L"Error", MB_ICONERROR | MB_OK); exit(1); } if(!SetPixelFormat(hDC, pixelFormat, &pfd)) { MessageBox(ghMainWnd, L"SetPixelFormat() failed", L"Error", MB_ICONERROR | MB_OK); exit(1); } } int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR pCmdLine, int nShowCmd) { if(!InitWindowsApp(hInstance, nShowCmd)) return 0; return Run(); } bool InitWindowsApp(HINSTANCE instanceHandle, int show) { WNDCLASS wc; wc.style = CS_OWNDC | CS_HREDRAW | CS_VREDRAW; wc.lpfnWndProc = WndProc; wc.cbClsExtra = 0; wc.cbWndExtra = 0; wc.hInstance = instanceHandle; wc.hIcon = LoadIcon(0, IDI_APPLICATION); wc.hCursor = LoadCursor(0, IDC_ARROW); wc.hbrBackground = (HBRUSH) GetStockObject(BLACK_BRUSH); wc.lpszMenuName = 0; wc.lpszClassName = L"BasicWndClass"; if(!RegisterClass(&wc)) { MessageBox(0, L"RegisterClass failed", 0, 0); return false; } ghMainWnd = CreateWindow( L"BasicWndClass", L"BasicWindowsApp", WS_OVERLAPPEDWINDOW, 0, 0, 600, 600, 0, 0, instanceHandle, 0); if(ghMainWnd == 0) { MessageBox(0, L"CreateWindow failed", 0, 0); return false; } ShowWindow(ghMainWnd, show); UpdateWindow(ghMainWnd); return true; } int Run() { MSG msg = {0}; Application *pApp = new Application(); pApp->Init(); while(msg.message != WM_QUIT) { if(PeekMessage(&msg, 0, 0, 0, PM_REMOVE)) { TranslateMessage(&msg); DispatchMessage(&msg); } else { //Do Other stuff pApp->Draw(); SwapBuffers(hDC); } } if(pApp) { delete pApp; pApp = nullptr; } return (int)msg.wParam; } LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) { switch(msg) { case WM_CREATE: hDC = GetDC(ghMainWnd); SetupPixelFormat(); hGLRC = wglCreateContext(hDC); if(!hGLRC) { MessageBox(ghMainWnd, L"wglCreateContext() failed", L"Error", MB_ICONERROR | MB_OK); exit(1); } if(!wglMakeCurrent(hDC, hGLRC)) { MessageBox(ghMainWnd, L"wglMakeCurrent() failed", L"Error", MB_ICONERROR | MB_OK); exit(1); } glViewport(0, 0, 600, 600); glClearColor(1.0f, 0.0f, 0.0f, 1.0f); return 0; case WM_LBUTTONDOWN: return 0; case WM_KEYDOWN: if(wParam == VK_ESCAPE) DestroyWindow(ghMainWnd); return 0; case WM_DESTROY: if(hGLRC) { wglMakeCurrent(nullptr, nullptr); wglDeleteContext(hGLRC); } ReleaseDC(ghMainWnd, hDC); PostQuitMessage(0); return 0; } return DefWindowProc(hWnd, msg, wParam, lParam); } 

下面,我find了一个“黑客”,使其工作:我基本上将opengl上下文创build到InitWindowsApp()函数…但为什么上面的代码不起作用?

 #include <windows.h> #include <GL\glew.h> #include <GL\wglew.h> #include "Application.h" HWND ghMainWnd = 0; bool InitWindowsApp(HINSTANCE instanceHandle, int show); int Run(); LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam); HDC hDC; HGLRC hGLRC; HPALETTE hPalette; void SetupPixelFormat() { PIXELFORMATDESCRIPTOR pfd = {}; 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 = 24; pfd.cAlphaBits = 8; pfd.cDepthBits = 32; pfd.iLayerType = PFD_MAIN_PLANE; int pixelFormat = ChoosePixelFormat(hDC, &pfd); if(pixelFormat == 0) { MessageBox(ghMainWnd, L"ChoosePixelFormat() failed", L"Error", MB_ICONERROR | MB_OK); exit(1); } if(!SetPixelFormat(hDC, pixelFormat, &pfd)) { MessageBox(ghMainWnd, L"SetPixelFormat() failed", L"Error", MB_ICONERROR | MB_OK); exit(1); } } int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR pCmdLine, int nShowCmd) { if(!InitWindowsApp(hInstance, nShowCmd)) return 0; return Run(); } bool InitWindowsApp(HINSTANCE instanceHandle, int show) { WNDCLASS wc; wc.style = CS_OWNDC | CS_HREDRAW | CS_VREDRAW; wc.lpfnWndProc = WndProc; wc.cbClsExtra = 0; wc.cbWndExtra = 0; wc.hInstance = instanceHandle; wc.hIcon = LoadIcon(0, IDI_APPLICATION); wc.hCursor = LoadCursor(0, IDC_ARROW); wc.hbrBackground = (HBRUSH) GetStockObject(BLACK_BRUSH); wc.lpszMenuName = 0; wc.lpszClassName = L"BasicWndClass"; if(!RegisterClass(&wc)) { MessageBox(0, L"RegisterClass failed", 0, 0); return false; } ghMainWnd = CreateWindow( L"BasicWndClass", L"BasicWindowsApp", WS_OVERLAPPEDWINDOW, 0, 0, 600, 600, 0, 0, instanceHandle, 0); if(ghMainWnd == 0) { MessageBox(0, L"CreateWindow failed", 0, 0); return false; } ShowWindow(ghMainWnd, show); UpdateWindow(ghMainWnd); hDC = GetDC(ghMainWnd); SetupPixelFormat(); hGLRC = wglCreateContext(hDC); if(!hGLRC) { MessageBox(ghMainWnd, L"wglCreateContext() failed", L"Error", MB_ICONERROR | MB_OK); exit(1); } if(!wglMakeCurrent(hDC, hGLRC)) { MessageBox(ghMainWnd, L"wglMakeCurrent() failed", L"Error", MB_ICONERROR | MB_OK); exit(1); } glViewport(0, 0, 600, 600); glClearColor(1.0f, 0.0f, 0.0f, 1.0f); return true; } int Run() { MSG msg = {0}; Application *pApp = new Application(); pApp->Init(); while(msg.message != WM_QUIT) { if(PeekMessage(&msg, 0, 0, 0, PM_REMOVE)) { TranslateMessage(&msg); DispatchMessage(&msg); } else { //Do Other stuff pApp->Draw(); SwapBuffers(hDC); } } if(pApp) { delete pApp; pApp = nullptr; } return (int)msg.wParam; } LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) { switch(msg) { case WM_CREATE: return 0; case WM_LBUTTONDOWN: return 0; case WM_KEYDOWN: if(wParam == VK_ESCAPE) DestroyWindow(ghMainWnd); return 0; case WM_DESTROY: if(hGLRC) { wglMakeCurrent(nullptr, nullptr); wglDeleteContext(hGLRC); } ReleaseDC(ghMainWnd, hDC); PostQuitMessage(0); return 0; } return DefWindowProc(hWnd, msg, wParam, lParam); } 

WM_CREATE到达时,您的ghMainWnd仍然是NULL (该消息在CreateWindow调用返回之前发送)。 而是在您的GetDC调用中使用消息的hWnd参数。