I'm new to OpenGL, and I bought a book on it for beginners. I finished writing the sample code for making a context/window. I get an error on this line at the part PFNWGLCREATECONTEXTATTRIBSARBPROC, saying "Error: expected a ')'":
typedef HGLRC(APIENTRYP PFNWGLCREATECONTEXTATTRIBSARBPROC)(HDC, HGLRC, const int*);
Replacing it or adding a ")" makes it error, but the error disappears when I use the OpenGL headers included in the books CD, which are OpenGL 3.0. I would like a way to make this work with the newest gl.h/wglext.h and without libraries.
Here's the rest of the class if it's needed:
#include <ctime>
#include <windows.h>
#include <iostream>
#include <gl\GL.h>
#include <gl\wglext.h>
#include "Example.h"
#include "GLWindow.h"
typedef HGLRC(APIENTRYP PFNWGLCREATECONTEXTATTRIBSARBPROC)(HDC, HGLRC, const int*);
PFNWGLCREATECONTEXTATTRIBSARBPROC wglCreateContextAttribsARB = NULL;
bool GLWindow::create(int width, int height, int bpp, bool fullscreen)
{
DWORD dwExStyle; //Window Extended Style
DWORD dwStyle; //Window Style
m_isFullscreen = fullscreen;//Store the fullscreen flag
m_windowRect.left = 0L;
m_windowRect.right = (long)width;
m_windowRect.top = 0L;
m_windowRect.bottom = (long)height;//Set bottom to height
// fill out the window class structure
m_windowClass.cbSize = sizeof(WNDCLASSEX);
m_windowClass.style = CS_HREDRAW | CS_VREDRAW;
m_windowClass.lpfnWndProc = GLWindow::StaticWndProc; //We set our static method as the event handler
m_windowClass.cbClsExtra = 0;
m_windowClass.cbWndExtra = 0;
m_windowClass.hInstance = m_hinstance;
m_windowClass.hIcon = LoadIcon(NULL, IDI_APPLICATION); // default icon
m_windowClass.hCursor = LoadCursor(NULL, IDC_ARROW); // default arrow
m_windowClass.hbrBackground = NULL; // don't need background
m_windowClass.lpszMenuName = NULL; // no menu
m_windowClass.lpszClassName = (LPCWSTR)"GLClass";
m_windowClass.hIconSm = LoadIcon(NULL, IDI_WINLOGO); // windows logo small icon
if (!RegisterClassEx(&m_windowClass))
{
MessageBox(NULL, (LPCWSTR)"Failed to register window class", NULL, MB_OK);
return false;
}
if (m_isFullscreen)//If we are fullscreen, we need to change the display
{
DEVMODE dmScreenSettings; //Device mode
memset(&dmScreenSettings, 0, sizeof(dmScreenSettings));
dmScreenSettings.dmSize = sizeof(dmScreenSettings);
dmScreenSettings.dmPelsWidth = width; //Screen width
dmScreenSettings.dmPelsHeight = height; //Screen height
dmScreenSettings.dmBitsPerPel = bpp; //Bits per pixel
dmScreenSettings.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;
if (ChangeDisplaySettings(&dmScreenSettings, CDS_FULLSCREEN) != DISP_CHANGE_SUCCESSFUL)
{
MessageBox(NULL, (LPCWSTR)"Display mode failed", NULL, MB_OK);
m_isFullscreen = false;
}
}
if (m_isFullscreen) //Is it fullscreen?
{
dwExStyle = WS_EX_APPWINDOW; //Window Extended Style
dwStyle = WS_POPUP; //Windows Style
ShowCursor(false); //Hide mouse pointer
}
else
{
dwExStyle = WS_EX_APPWINDOW | WS_EX_WINDOWEDGE; //Window Exteneded Style
dwStyle = WS_OVERLAPPEDWINDOW; //Windows Style
}
AdjustWindowRectEx(&m_windowRect, dwStyle, false, dwExStyle); //Adjust window to true requested size
//Class registered, so now create window
m_hwnd = CreateWindowEx(NULL, //Extended Style
(LPCWSTR)"GLClass", //Class name
(LPCWSTR)"Chapter 2", //App name
dwStyle | WS_CLIPCHILDREN | WS_CLIPSIBLINGS,
0, 0, //x, y coordinates
m_windowRect.right - m_windowRect.left,
m_windowRect.bottom - m_windowRect.top, //Width and height
NULL, //Handle to parent
NULL, //Handle to menu
m_hinstance, //Application instance
this); //Pass a pointer to the GLWindow here
//Check if window creation failed, hwnd would equal NULL
if (!m_hwnd)
{
return 0;
}
m_hdc = GetDC(m_hwnd);
ShowWindow(m_hwnd, SW_SHOW);
UpdateWindow(m_hwnd);
m_lastTime = GetTickCount() / 1000.0f;
return true;
}
LRESULT CALLBACK GLWindow::StaticWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
GLWindow* window = nullptr;
//If this is the create message
if (uMsg == WM_CREATE)
{
//Get the pointer we stored during create
window = (GLWindow*)((LPCREATESTRUCT)lParam)->lpCreateParams;
//Associate the window pointer with the hwnd for the other events to access
SetWindowLongPtr(hWnd, GWL_USERDATA, (LONG_PTR)window);
}
else
{
//If this is not a creation event, then we should have stored a pointer to the window
window = (GLWindow*)GetWindowLongPtr(hWnd, GWL_USERDATA);
if (!window)
{
//Do the default event handling
return DefWindowProc(hWnd, uMsg, wParam, lParam);
}
}
//Call our window's member WndProc(allows us to access member variables)
return window->WndProc(hWnd, uMsg, wParam, lParam);
}
LRESULT GLWindow::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg)
{
case WM_CREATE:
{
m_hdc = GetDC(hWnd);
setupPixelFormat();
//Set the version that we want, in this case 3.0
int attribs[] = {
WGL_CONTEXT_MAJOR_VERSION_ARB, 3,
WGL_CONTEXT_MINOR_VERSION_ARB, 0,
0};
//Create temporary context so we can get a pointer to the function
HGLRC tmpContext = wglCreateContext(m_hdc);
//Make the context current
wglMakeCurrent(m_hdc, tmpContext);
//Get the function pointer
wglCreateContextAttribsARB = (PFNWGLCREATECONTEXTATTRIBSARBPROC)wglGetProcAddress("wglCreateContextAttribsARB");
//If this is NULL then OpenGl 3.0 is not supported
if (!wglCreateContextAttribsARB)
{
MessageBox(NULL, (LPCWSTR)"OpenGL 3.0 is not supported", (LPCWSTR)"An error occured", MB_ICONERROR | MB_OK);
DestroyWindow(hWnd);
return 0;
}
//Create an OpenGL 3.0 context using the new function
m_hglrc = wglCreateContextAttribsARB(m_hdc, 0, attribs);
//Delete the temporary context
wglDeleteContext(tmpContext);
//Make the GL3 context current
wglMakeCurrent(m_hdc, m_hglrc);
m_isRunning = true;
}
break;
case WM_DESTROY: //Window destroy
case WM_CLOSE: //Windows is closing
wglMakeCurrent(m_hdc, NULL);
wglDeleteContext(m_hglrc);
m_isRunning = false; //Stop the main loop
PostQuitMessage(0);
break;
case WM_SIZE:
{
int height = HIWORD(lParam); //Get height and width
int width = LOWORD(lParam);
getAttachedExample()->onResize(width, height); //Call the example's resize method
}
break;
case WM_KEYDOWN:
if (wParam == VK_ESCAPE) //If the escape key was pressed
{
DestroyWindow(m_hwnd);
}
break;
default:
break;
}
return DefWindowProc(hWnd, uMsg, wParam, lParam);
}
void GLWindow::processEvents()
{
MSG msg;
//While there are messages in the queue, store them in msg
while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
//Process the messages
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
Here is the header:
#pragma once
#include <ctime>
#include <windows.h>
class Example;//Declare our example class
class GLWindow
{
public:
GLWindow(HINSTANCE hInstance); //default constructor
bool create(int width, int height, int bpp, bool fullscreen);
void destroy();
void processEvents();
void attachExample(Example* example);
bool isRunning(); //Is the window running?
void swapBuffers() { SwapBuffers(m_hdc); }
static LRESULT CALLBACK StaticWndProc(HWND wnd, UINT msg, WPARAM wParam, LPARAM lParam);
LRESULT CALLBACK WndProc(HWND wnd, UINT msg, WPARAM wParam, LPARAM lParam);
float getElapsedSeconds();
private:
Example* m_example; //A link to the example program
bool m_isRunning; //Is the window still running?
bool m_isFullscreen;
HWND m_hwnd; //Window handle
HGLRC m_hglrc; //Rendering context
HDC m_hdc; //Device context
RECT m_windowRect; //Window bounds
HINSTANCE m_hinstance; //Application instance
WNDCLASSEX m_windowClass;
void setupPixelFormat(void);
Example* getAttachedExample() { return m_example; }
float m_lastTime;
};