Windows函数ChoosePixelFormat在Windows 7上返回ERR_OLD_WIN_VERSION

我试图通过制作一个窗口并附加一个OpenGL上下文来教会自己的win32 API。 为了获取适当的像素格式,必须调用ChoosePixelFormat,它应该返回系统支持的像素格式,并最能满足我的需求。 当我检查错误一切顺利,直到这个函数被调用,停止执行,并logging错误1150-ERR_OLD_WIN_VERSION,这应该是我的版本的Windows不支持此function。 这显然不是这种情况,MSDN确认这个函数运行在Windows 2000以后的所有版本的Windows上。现在,我正在桌面上运行Windows 7 x64,并确保我的video驱动程序和操作系统完全更新。 像素格式函数似乎有很多人有麻烦,但我还没有find任何与我的问题,所以我决定张贴在这里寻求帮助。 这是我的完整代码; 我没有在我自己的机器上testing过。

WinMain.cpp(这是链接的唯一的非默认msvc lib是opengl32.lib)

#include"Display.h" #include<iostream> #include<fstream> MSG message; DWORD error; int status; LRESULT CALLBACK WndProc(HWND hWindow, UINT message, WPARAM wParam, LPARAM lParam) { switch(message) {case WM_CREATE: return 0; case WM_DESTROY: PostQuitMessage(0); return 0; case WM_KEYDOWN: switch(wParam) {case VK_ESCAPE: PostQuitMessage(0); return 0;}} return DefWindowProc(hWindow, message, wParam, lParam);} int MainLoop(Display d) { while((status = PeekMessage(&message, d.hWindow, 0, 0, PM_REMOVE)) != 0) { if (status == -1) { return -1; } DispatchMessage(&message); } return 0; } int CALLBACK WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { std::ofstream file("log.txt", std::ios::trunc); Display window("TEST", hInstance, WndProc, 50, 50, 50, 50, NULL, NULL); if(window.status == -1) { error = GetLastError(); file << error; return 1;} ShowWindow(window.hWindow, SW_SHOWNORMAL); EnableWindow(window.hWindow, true); MainLoop(window); return 0; } 

Display.h(问题发生在类的构造函数中)

 #include <Windows.h> class Display {public: Display(const char*, HINSTANCE, WNDPROC, int, int, int, int, DWORD, DWORD); ~Display(); HWND hWindow; int status; private: WNDCLASSEX data; HDC hDeviceContext; HGLRC hGLContext; PIXELFORMATDESCRIPTOR PFD; int x, y, width, height;}; Display::Display(const char* title, HINSTANCE InstanceHandle, WNDPROC WindowProcedure, int ScreenPositionX, int ScreenPositionY, int WindowWidth, int WindowHeight, DWORD StyleFlags, DWORD ExtendedStyleFlags) { data.cbSize = sizeof(WNDCLASSEX); data.style = CS_OWNDC; data.lpfnWndProc = WindowProcedure; data.cbClsExtra = 0; data.cbWndExtra = 0; data.hInstance = InstanceHandle; data.hIcon = NULL; data.hCursor = NULL; data.hbrBackground = NULL; data.lpszMenuName = NULL; data.lpszClassName = "WIN1"; data.hIconSm = NULL; RegisterClassEx(&data); hWindow = CreateWindowEx(ExtendedStyleFlags, data.lpszClassName, title, StyleFlags | WS_CLIPSIBLINGS | WS_CLIPCHILDREN, x = ScreenPositionX, y = ScreenPositionY, width = WindowWidth, height = WindowHeight, NULL, NULL, InstanceHandle, NULL); PFD.nSize = sizeof(PIXELFORMATDESCRIPTOR); PFD.nVersion = 1; PFD.iPixelType = PFD_TYPE_RGBA; PFD.iLayerType = PFD_MAIN_PLANE; PFD.dwVisibleMask = 0; PFD.dwLayerMask = 0; PFD.dwDamageMask = 0; PFD.dwFlags = PFD_DRAW_TO_WINDOW | PFD_DOUBLEBUFFER | PFD_SUPPORT_OPENGL; PFD.cAuxBuffers = 0; PFD.bReserved = 0; PFD.cColorBits = 24; PFD.cAccumBits = 0; PFD.cDepthBits = 32; PFD.cStencilBits = 0; PFD.cAlphaBits = 0; PFD.cAccumAlphaBits = 0; PFD.cAlphaShift = 0; PFD.cBlueBits = 0; PFD.cAccumBlueBits = 0; PFD.cBlueShift = 0; PFD.cGreenBits = 0; PFD.cAccumGreenBits = 0; PFD.cGreenShift = 0; PFD.cRedBits = 0; PFD.cAccumRedBits = 0; PFD.cRedShift = 0; hDeviceContext = GetDC(hWindow); int pf = ChoosePixelFormat(hDeviceContext, &PFD); //throws error 1150, next three throw error 2000 because of this failing SetPixelFormat(hDeviceContext, pf, &PFD); hGLContext = wglCreateContext(hDeviceContext); wglMakeCurrent(hDeviceContext, hGLContext); if(GetLastError() != ERROR_SUCCESS) {status = -1;} else {status = 0;} return;} Display::~Display() { wglMakeCurrent(NULL, NULL); wglDeleteContext(hGLContext); DestroyWindow(hWindow); UnregisterClass(data.lpszClassName, data.hInstance);} 

在我尝试了所有提到的解决方案之后,我仍然遇到与ChoosePixelFormat之后的ERR_OLD_WIN_VERSION相同的问题。 在我的情况下,问题是关于显卡驱动程序:

我正在使用的系统使用带有GTX 770 GPU的EVGA卡,昨天我安装了驱动程序版本331.65。 之后,我也遇到了和提问者一样的问题。 安装当前的版本337.88解决了这个问题。 但是,ERR_OLD_WIN_VERSION会导致我们朝错误的方向发展。

在你的Display构造函数中,它看起来像你在使用它之前不初始化hWindow成员。 这将是CreateWindowEx返回的值。

而不是测试GetLastError函数的地址,您应该调用它并根据ERROR_SUCCESS测试其返回值。 我认为这可能是你粘贴代码时的疏忽,因为你似乎从GetLastError (...)获得有意义的结果。

更新:

你可能想尝试像这样的:

 #ifndef WINVER # define WINVER 0x0500 #endif 

#include <Windows.h>之前

这告诉它包括Windows NT 5.0(Windows 2000)中新增的所有数据结构中的字段。 这些结构中的许多结构会根据您的结构sizeof来确定它们所针对的Windows版本,这取决于您如何定义WINVER。

我无法启动旧版本的机器,但在查看SDL的源代码时发现了一些问题。 他们似乎定义了自己的ChoosePixelFormat版本,它使用DescribePixelFormat循环遍历所有可用的像素格式,然后在选择最佳像素格式之前将其与所需的像素格式进行比较。 由于这是Windows的ChoosePixelFormat完全相同的定义,我怀疑他们有一个很好的理由,使自己的。 也许他们知道在某些情况下给了麻烦。 不幸的是,由于Microsoft开发人员的支持是一个神话,几乎没有人愿意关心,这是我现在得到的一个好答案。 因为我也不再关心,所以这个问题可能是最接近答案的问题。 告诉那些试图帮助你的人。