尽管在整个网络上阅读了大量的信息,以及Petzold的书,编程Windows API ,并且该死的几乎要复制完全相同的方法,以及{{ 3}}关于如何初始化OpenGL上下文的文档,我还没有能够启动并运行Window类。
我已尝试在VC ++和MinGW(我使用Qt Creator)上进行编译,以确定这是否有效。我尝试将WNDCLASSEXA
指针作为指针,并将其分配到堆栈中。两者都没有骰子。
因此,我很不确定该怎么做。有时候这个类根本没有注册,而其他时候从HWND
返回的CreateWindowExA
根本不起作用并返回NULL。在尝试继续该程序之后,尽管发生了这些事件,我最终得到了一个无法绘制窗口的应用程序。
这个想法很简单:我有一个结构,我只是用它来存储所有使用的数据(DEVMODEA
,WNDCLASSEXA
,HGLRC
等。 / p>
从那里,我使用该结构创建一个Window,然后将其传递回函数的调用者。
我真正想做的就是使用GLSL / OpenGL 3.3在OpenGL中编写一个类似pong的游戏。要做到这一点,我显然首先需要一个上下文,但我无法辨别问题是Qt Creator,Windows还是别的。
那么,我可能做错了什么?
GameData
结构
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()
功能
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;
}
更新
在这里,我将发布我所做的过程:
我首先尝试将cbClsExtra
设置为1,然后将其设置为0.然后我将cbWndExtra
设置为1.之后我尝试将cbSize
设置为sizeof( WNDCLASSEXA )
。
我也尝试在VC ++和MinGW下进行编译;在VC ++中,该类无法注册,而在MinGW中,类将注册,但它实际上不会创建所需的hwnd
。
我还尝试通过使WNDCLASSEXA
(dat->winClass
)指针而不是堆栈分配变量来编辑我的代码。
我还在我的exit
项检查中评论了我的if
个功能,看看是否注册,或者{ {1}} 不是创建的。这会在尝试使用hwnd
呈现OpenGL上下文时产生分段错误。
更新2
这是我的WndProc:
wglChoosePixelFormatARB