user2297599
user2297599

Reputation: 31

Windows function ChoosePixelFormat returns ERR_OLD_WIN_VERSION on windows 7

I'm trying to teach myself the win32 API by making a window and attaching an OpenGL context to it. In order to fetch the appropriate pixel format a call to ChoosePixelFormat must be made which should return a pixel format that the system supports and best meets my needs. When I check for errors everything goes smoothly until this function is called which stops execution and logs error 1150-ERR_OLD_WIN_VERSION which is supposed to mean that my version of windows does not support this function. This is obviously not the case and msdn confirms that this function runs on all versions of windows since windows 2000. Right now I'm running windows 7 x64 on my desktop and I made sure my video driver and os were fully updated. Lots of people seem to have had trouble with the pixel format functions but I have not found any with my problem so I decided to post here for help. Here is my full code; I have not tested it on any machines other than my own.

WinMain.cpp (the only non-default msvc lib this is linked with is 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 (problem occurs in the class constructor)

#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);}

Upvotes: 2

Views: 1839

Answers (4)

hundolin
hundolin

Reputation: 61

After I have tried all mentioned solutions I still had the same problem with ERR_OLD_WIN_VERSION after ChoosePixelFormat. In my case the problem was about the graphics card driver:

The system I'm working on uses an EVGA card with a GTX 770 GPU and yesterday I installed driver version 331.65. After that I got the same problems as the questioner. Installing the current Version 337.88 fixed the issue in my case. However ERR_OLD_WIN_VERSION seams to lead us in the wrong direction.

Upvotes: 1

user2297599
user2297599

Reputation: 31

I was not able to boot up my older machine, but I did discover something when looking through the source code of SDL. It seems that they defined their own version of ChoosePixelFormat that loops through all available pixel formats using DescribePixelFormat and then compares them to the desired pixel format before choosing the best one. Since this is the exact same definition of windows's ChoosePixelFormat I suspect they had a good reason to make their own. Perhaps they knew it gave trouble in certain situations. Unfortunately since Microsoft Developer support is a myth, and barely anyone seems to care, this is as good an answer as I'll get for now. And since I've stopped caring too, this is probably the closest this question will ever get to an answer. Thnaks to those of you who tried to help.

Upvotes: 0

Andon M. Coleman
Andon M. Coleman

Reputation: 43319

Instead of testing the address of the GetLastError function, you should be calling it and testing its return value against ERROR_SUCCESS. I think this may be an oversight when you pasted the code, as you seem to be getting meaningful results from GetLastError (...).

UPDATE:

You might want to try something like:

#ifndef WINVER
# define WINVER 0x0500
#endif

Before #include <Windows.h>

That tells it to include all of the fields in the data structures that are new in Windows NT 5.0 (Windows 2000). Many of these structures determine the version of Windows they are targeting by the sizeof your structure, which will vary depending on how you have WINVER defined.

Upvotes: 0

JWWalker
JWWalker

Reputation: 22707

In your Display constructor, it looks like you don't initialize the hWindow member before you use it. That would be the value returned by CreateWindowEx.

Upvotes: 0

Related Questions