【问题标题】:Windows function ChoosePixelFormat returns ERR_OLD_WIN_VERSION on windows 7Windows 函数 ChoosePixelFormat 在 Windows 7 上返回 ERR_OLD_WIN_VERSION
【发布时间】:2014-06-22 19:31:55
【问题描述】:

我正在尝试通过制作一个窗口并将 OpenGL 上下文附加到它来自学 win32 API。为了获取适当的像素格式,必须调用 ChoosePixelFormat,它应该返回系统支持并最能满足我需求的像素格式。当我检查错误时,一切都很顺利,直到调用该函数停止执行并记录错误 1150-ERR_OLD_WIN_VERSION 这应该意味着我的 Windows 版本不支持此函数。显然情况并非如此,msdn 确认此功能可在自 windows 2000 以来的所有 windows 版本上运行。现在我在桌面上运行 windows 7 x64,并确保我的视频驱动程序和操作系统已完全更新。很多人似乎在使用像素格式功能时遇到了问题,但我没有发现任何问题,所以我决定在这里发帖寻求帮助。这是我的完整代码;除了我自己的机器,我没有在任何机器上测试过。

WinMain.cpp(唯一与之链接的非默认 msvc 库是 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);}

【问题讨论】:

  • 当您说 "non-default msvc lib" 时,您是说您正在链接一个不属于 Windows SDK 的 OpenGL32.lib?此外,为了确保您的链接器确实链接到特定库,您可以指定 /VERBOSE:LIB 链接器选项来显示搜索的库。
  • 你是说ChoosePixelFormat返回1150吗?如果是这样,这就是文档的成功:If the function succeeds, the return value is a pixel format index (one-based) that is the closest match to the given pixel format descriptor.
  • @Ninja 很抱歉选词不当。该函数返回一个零,表示失败。如果 GetLastError() 刚刚被调用,它将返回 1150
  • @IInspectable 是我的另一个糟糕的选择。在链接器设置中,Opengl32.lib 被列为依赖项。我对此没有任何问题,我只是将其包含在内,以防运行代码的其他人遇到未定义“wgl”函数的问题
  • 我认为你的WndProc函数中应该有一个default:标签。

标签: c++ windows opengl


【解决方案1】:

在尝试了所有提到的解决方案后,在选择像素格式后,我仍然遇到与 ERR_OLD_WIN_VERSION 相同的问题。就我而言,问题在于显卡驱动程序:

我正在使用的系统使用带有 GTX 770 GPU 的 EVGA 卡,昨天我安装了驱动程序版本 331.65。之后,我遇到了与提问者相同的问题。安装当前版本 337.88 解决了我的问题。然而,ERR_OLD_WIN_VERSION 接缝将我们引向错误的方向。

【讨论】:

    【解决方案2】:

    在您的 Display 构造函数中,您似乎没有在使用 hWindow 成员之前对其进行初始化。那将是CreateWindowEx 返回的值。

    【讨论】:

    • 我多么愚蠢。这并不能解决我遇到的错误 1150,但我猜它仍然很有帮助。我对 GetDC(hWindow); 的调用很有趣。 hWindow 未初始化时没有触发任何错误
    • @user2297599:这是因为GetDC (NULL) 是一个特殊情况,它返回“桌面”窗口的设备上下文。由于未初始化的值在 MSVC 中通常为 NULL,这可能就是正在发生的事情。
    【解决方案3】:

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

    更新:

    您可能想尝试以下方法:

    #ifndef WINVER
    # define WINVER 0x0500
    #endif
    

    #include &lt;Windows.h&gt;之前

    这告诉它在数据结构中包含 Windows NT 5.0 (Windows 2000) 中新增的所有字段。其中许多结构通过 sizeof 您的结构确定它们所针对的 Windows 版本,这取决于您定义 WINVER 的方式。

    【讨论】:

    • 我很想知道为什么这个答案被默默地否决了。在任何情况下,您都在测试GetLastError 的地址而不是调用它,并且您的窗口进程的返回值是CreateWindow&lt;Ex&gt; (...) 用来确定您的窗口创建是否成功的,它期望值为0成功,其他都代表失败。至少,为WM_CREATE 添加一个case 并返回0。
    • 我也想知道开车投反对票。关于GetLastError 的观点似乎是正确的,但我不足以让Windows 程序员确定WM_CREATE 的问题。无论如何,我会让你回到 0。
    • 我没有足够的声望投票所以我真的不知道是谁做的,但这是有用的信息。我要更新代码。另外,如果你们中的一个人可以在您的机器上试用代码并告诉我您是否在 log.txt 中遇到类似的错误,那就太好了,这样我就知道我的 windows 版本没有问题。
    • @user2297599:我刚刚想起了一些关于预处理器定义的事情:WINVER,这可能与这种情况有关......有关更多详细信息,请参阅我的更新答案。
    • WM_CREATE 传递给DefWindowProc 很好,它将返回成功并创建窗口。但是,似乎确实缺少 default: 标签。
    【解决方案4】:

    我无法启动我的旧机器,但在查看SDL 的源代码时确实发现了一些东西。似乎他们定义了自己的 ChoosePixelFormat 版本,该版本使用 DescribePixelFormat 遍历所有可用的像素格式,然后在选择最佳像素格式之前将它们与所需的像素格式进行比较。由于这与 windows 的 ChoosePixelFormat 的定义完全相同,我怀疑他们有充分的理由制作自己的。也许他们知道这在某些情况下会带来麻烦。不幸的是,由于 Microsoft 开发人员支持是一个神话,而且似乎几乎没有人关心,所以这是我现在得到的最好的答案。而且由于我也不再关心,这可能是这个问题最接近答案的地方。感谢那些试图提供帮助的人。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-06-25
      • 2014-04-14
      • 2012-01-31
      • 1970-01-01
      • 1970-01-01
      • 2017-07-14
      • 2010-12-17
      • 1970-01-01
      相关资源
      最近更新 更多