简体   繁体   中英

Registering a Window Class in the Win32API

Despite reading plenty of information throughout the web, along with Petzold's book, Programming the Windows API , and damn near copying the exact same methodology out of the book, along with this documentation on how to initialize an OpenGL context, I haven't been able to get an up and running Window Class.

I've tried compiling on both VC++ and MinGW (I'm using Qt Creator), in order to see if this would work. I've tried making my WNDCLASSEXA a pointer, as well as allocating it on the stack. No dice for both.

Thus, I'm quite unsure what to do about this. Sometimes the class simply fails to register, where as other times the HWND which is returned from CreateWindowExA simply doesn't work and returns NULL. After trying to just continue the program, despite these incidents happening, I wind up with an application which fails to draw a window.

The idea is simple: I have a struct which I'm using to simply store all of the data used ( DEVMODEA , WNDCLASSEXA , HGLRC , etc).

From there, I use that struct to create a Window, and then pass it back to the function's caller.

All I'm really looking to do is write a simple pong-like game in OpenGL using GLSL/OpenGL 3.3. To do that, I obviously need a context first, but I can't discern whether or not the issue is Qt Creator, Windows, or something else.

So, what could I be doing wrong?

GameData Struct

typedef struct
{
    HGLRC        hrc;
    HDC          hdc;
    HWND         hwnd;
    HINSTANCE    hInstance;
    UINT         numFormats;
    WNDCLASSEXA* winClass;
    DWORD        dwExStyle;
    DWORD        dwStyle;
    RECT         winRect;
    DEVMODEA     screenSettings;

    bool         fullscreen;
    const char*  winClassName;
    int          pixelFormat;
    bool         keys[ 256 ];
    bool         active;
}
GameData;

initPong() function

static GameData* initContextAndWindow( void )
{
    GameData* dat = new GameData;

    const int width     = 640;
    const int height    = 480;
    const int bitsPerPixel = 32;

    dat->winRect.left   = ( long )0;
    dat->winRect.right  = ( long )width;
    dat->winRect.top    = ( long )0;
    dat->winRect.bottom = ( long )height;

    dat->fullscreen     = false;

    dat->hInstance              = GetModuleHandleA( NULL );

    dat->winClass = ( WNDCLASSEXA* )calloc( sizeof( WNDCLASSEXA ), 1 );

    if( !dat->winClass )
        MessageBoxA( NULL, "Something wrong!", "ERROR", MB_OK | MB_ICONINFORMATION );

    dat->winClass->style         = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
    dat->winClass->lpfnWndProc   = ( WNDPROC ) eventHandler;
    dat->winClass->cbClsExtra    = 1;
    dat->winClass->cbWndExtra    = 1;
    dat->winClass->cbSize        = sizeof( WNDCLASSEXA );
    dat->winClass->hInstance     = dat->hInstance;
    dat->winClass->hIcon         = LoadIcon( NULL, IDI_WINLOGO );
    dat->winClass->hCursor       = LoadCursor( NULL, IDC_ARROW );
    dat->winClass->hbrBackground = ( HBRUSH ) GetStockObject( WHITE_BRUSH );
    dat->winClass->lpszMenuName  = NULL;
    dat->winClass->lpszClassName = "PongDH";

    if ( !RegisterClassExA( dat->winClass ) )
    {
        MessageBoxA( NULL, "Failed to register class.", "ERROR", MB_OK | MB_ICONINFORMATION );
        exit( 1 );
    }

    if ( dat->fullscreen )
    {
        memset( &dat->screenSettings, 0, sizeof( dat->screenSettings ) );

        dat->screenSettings.dmSize          = sizeof( dat->screenSettings );
        dat->screenSettings.dmPelsWidth     = width;
        dat->screenSettings.dmPelsHeight    = height;
        dat->screenSettings.dmBitsPerPel    = bitsPerPixel;
        dat->screenSettings.dmFields        = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;

        if ( ChangeDisplaySettingsA( &dat->screenSettings, CDS_FULLSCREEN ) != DISP_CHANGE_SUCCESSFUL )
        {
            dat->fullscreen = false;



            const int continuePlaying = MessageBoxA(
                NULL,
                "Could not implement fullscreen. Please check your drivers. Do you plan to continue?",
                "ERROR",
                MB_YESNO | MB_ICONEXCLAMATION
            );

            if ( continuePlaying == IDYES )
            {
                MessageBoxA( NULL, "Will revert back to fullscreen.", "Notifcation", MB_OK );
                dat->fullscreen = false;
            }
            else
            {
                MessageBoxA( NULL, "The program will now close", "Notification", MB_OK );
                exit( 1 );
            }
        }

    }

    if ( dat->fullscreen )
    {
        dat->dwExStyle = WS_EX_APPWINDOW;
        dat->dwStyle = WS_POPUP;
        ShowCursor( FALSE );
    }
    else
    {
        dat->dwExStyle  = WS_EX_APPWINDOW | WS_EX_WINDOWEDGE;
        dat->dwStyle    = WS_OVERLAPPEDWINDOW;
    }

    AdjustWindowRectEx( &dat->winRect, dat->dwStyle, FALSE, dat->dwExStyle );

    dat->hwnd = CreateWindowExA(
                    dat->dwStyle,
                    dat->winClass->lpszClassName,
                    "PongDH",
                    WS_CLIPSIBLINGS | WS_CLIPCHILDREN,
                    CW_USEDEFAULT, CW_USEDEFAULT,
                    dat->winRect.right,
                    dat->winRect.bottom,
                    NULL,
                    NULL,
                    dat->hInstance,
                    NULL
                );


    if ( dat->hwnd == NULL )
    {
        MessageBoxA( NULL, "Failed to create window; exiting program.", "ERROR", MB_OK | MB_ICONEXCLAMATION );
        exit( 1 );
    }

    const int attrList[] =
    {
        WGL_DRAW_TO_WINDOW_ARB  , GL_TRUE,
        WGL_SUPPORT_OPENGL_ARB  , GL_TRUE,
        WGL_DOUBLE_BUFFER_ARB   , GL_TRUE,
        WGL_PIXEL_TYPE_ARB      , WGL_TYPE_RGBA_ARB,
        WGL_COLOR_BITS_ARB      , 32,
        WGL_DEPTH_BITS_ARB      , 24,
        WGL_STENCIL_BITS_ARB    , 8,
        0,
    };

    wglChoosePixelFormatARB( dat->hdc, attrList, NULL, 1, &dat->pixelFormat, &dat->numFormats );

    const int contextList[] =
    {
        WGL_CONTEXT_MAJOR_VERSION_ARB, 3,
        WGL_CONTEXT_MINOR_VERSION_ARB, 3,
        0,
    };

    dat->hrc = wglCreateContextAttribsARB( dat->hdc, NULL, contextList );

    if( !wglMakeCurrent( dat->hdc, dat->hrc ) )
    {
        MessageBoxA( NULL, "Error making OpenGL Rendering Context current.", "ERROR", MB_OK | MB_ICONEXCLAMATION );
        exit( 1 );
    }

    ShowWindow( dat->hwnd, SW_SHOW );
    SetForegroundWindow( dat->hwnd );
    SetFocus( dat->hwnd );
    resizeScene( width, height );

    UpdateWindow( dat->hwnd );

    glEnable( GL_DEPTH_TEST );

    return dat;
}

Update

Here, I'll post the procedure of what I did:

I first tried setting cbClsExtra to 1, whereas before it was 0. Then I set cbWndExtra to 1. After that I tried setting the cbSize to sizeof( WNDCLASSEXA ) .

I also tried compiling under both VC++ and MinGW; in VC++, the class simply fails to register, where as in MinGW, the class will register, but it won't actually create the required hwnd .

I've also tried editing my code by making WNDCLASSEXA (which is dat->winClass ) a pointer, as opposed to a stack allocated variable.

I've also commenting out my exit functions in my if checks to see if either the class doesn't register, or if the hwnd isn't created. This yields a segmentation fault upon trying to render the OpenGL context with wglChoosePixelFormatARB .

Update 2

Here is my WndProc:

LRESULT CALLBACK eventHandler( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
{
    return DefWindowProcA( hwnd, uMsg, wParam, lParam );
}

I haven't been able to get an up and running Window Class.

There really is not a lot to registering and creating a window using the WinAPI.

As an example this simple test.cpp file:

#define STRICT
#include <windows.h>

long PASCAL WndProc (HWND, UINT, WPARAM, LPARAM);

int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
                     LPSTR lpszCmdParam, int nCmdShow)
{
   static char szClassName[] = "Hello World";
   MSG         msg;
   WNDCLASS    wndclass;

   memset(&wndclass, '\0', sizeof(wndclass));

   if (!hPrevInstance) {
      // define the 'Hello World' window class
      wndclass.style          = CS_HREDRAW|CS_VREDRAW;
      wndclass.lpfnWndProc    = WndProc;
      wndclass.cbClsExtra     = 0;
      wndclass.cbWndExtra     = 0;
      wndclass.hInstance      = hInstance;
      wndclass.hIcon          = LoadIcon (NULL, IDI_APPLICATION);
      wndclass.hCursor        = LoadCursor (NULL, IDC_ARROW);
      wndclass.hbrBackground  = (HBRUSH)GetStockObject (WHITE_BRUSH);
      wndclass.lpszMenuName   = 0;
      wndclass.lpszClassName  = szClassName;

      // register the 'Hello World' window class
      RegisterClass (&wndclass);
   }

   // create a new window that is a 'Hello World' window class
   HWND hwnd = CreateWindowEx(WS_EX_OVERLAPPEDWINDOW,
                              szClassName,
                              "My Hello World Window",
                              WS_OVERLAPPEDWINDOW,
                              CW_USEDEFAULT,
                              CW_USEDEFAULT,
                              CW_USEDEFAULT,
                              CW_USEDEFAULT,
                              NULL,
                              NULL,
                              hInstance,
                              NULL);

   ShowWindow (hwnd, nCmdShow);

   while (GetMessage (&msg, NULL, 0, 0)) {
      TranslateMessage (&msg);
      DispatchMessage (&msg);
   }

   return msg.wParam;
}

long APIENTRY WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    switch (message) {
       case WM_DESTROY:
          PostQuitMessage (0);
          return 0;
    }

    return DefWindowProc (hwnd, message, wParam, lParam);
}

can be compiled and linked from the command line:

C:\TEMP>cl test.cpp user32.lib gdi32.lib
Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 15.00.30729.01 for 80x86
Copyright (C) Microsoft Corporation.  All rights reserved.

test.cpp
Microsoft (R) Incremental Linker Version 9.00.30729.01
Copyright (C) Microsoft Corporation.  All rights reserved.

/out:test.exe
test.obj
user32.lib
gdi32.lib

and the resulting test.exe can be run and it will display a window:

C:\TEMP>test.exe

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM