Skip to main content
gamedev.net
🔒 Locked

'CreateWindowEx' causes error when called from a class function?

Started by TFS_Waldo 15 replies 3.6k views
Original Post
TFS_Waldo
TFS_Waldo
Hey again. I am posting regarding the same project I was working on yesterday, when I made a post. I am creating an OpenGL framework that I can use for my OpenGL projects, if you didn't know. Anyhow, I am creating a window like this in a class:

BOOL CGLWindow::CreateGLWindow(LPCTSTR lpszClassName, LPCTSTR lpszTitle,
							   UINT nWidth/* = 640*/, UINT nHeight/* = 480*/, UINT nBpp/* = 16*/,
							   BOOL bFullscreen/* = FALSE*/) 
{
	// TODO: Create the OpenGL window
	GLuint nPixelFormat;      // Window's pixel format
	WNDCLASS wndClass;        // Window class structure
	DWORD dwStyle, dwExStyle;   // Window's styles and extended styles

	RECT wndRect;     // Window's rectangle
	wndRect.left   = 0;            // Left side
	wndRect.right  = nWidth;       // Right side (width)
	wndRect.top    = 0;            // Top side
	wndRect.bottom = nHeight;      // Bottom side (height)

	// Copy each variable to its corresponding class member
	m_nWidth  = nWidth;    // Window width
	m_nHeight = nHeight;   // Window height
	m_nBpp    = nBpp;      // Window bpp
	m_bFullscreen = bFullscreen;      // Copy fullscreen flag


	// Setup and register window class
	m_hInstance = GetModuleHandle(NULL);       // Get handle to application's instance
	wndClass.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;      // Class style
	wndClass.lpfnWndProc = (WNDPROC) glWndProc;               // Wnd. proc. function
	wndClass.cbClsExtra = 0;        // No extra class data
	wndClass.cbWndExtra = 0;        // No extra window data
	wndClass.hInstance = m_hInstance;    // Set app. instance handle
	wndClass.hIcon = LoadIcon(NULL, IDI_WINLOGO);     // Set default icon
	wndClass.hCursor = LoadCursor(NULL, IDC_ARROW);   // Set default cursor
	wndClass.hbrBackground = NULL;     // No background (OGL does not require it)
	wndClass.lpszMenuName = NULL;      // No menu
	wndClass.lpszClassName = lpszClassName;    // Window's class name

	if (! RegisterClass(&wndClass))     // Register the window class (from 'wndClass' object)
	{
		// Display error message and return error
		MessageBox(NULL, "Error registering window class in 'CGLWindow::CreateGLWindow'...\n", NULL, NULL);
		return FALSE;
	}


	// Check for fullscreen mode
	if (bFullscreen)      // Go fullscreen
	{
		DEVMODE dmScreen;      // Screen settings
		memset(&dmScreen, 0, sizeof(dmScreen));     // Make sure memory is cleared

		// Setup members of 'dmScreen'
		dmScreen.dmSize = sizeof(dmScreen);   // Set memory size
		dmScreen.dmPelsWidth  = nWidth;     // Set width
		dmScreen.dmPelsHeight = nHeight;    // Set height
		dmScreen.dmBitsPerPel = nBpp;       // Set bits-per-pixel
		dmScreen.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;   // Set flags for use

		// Try to switch to desired fullscreen mode
		if (ChangeDisplaySettings(&dmScreen, CDS_FULLSCREEN) != DISP_CHANGE_SUCCESSFUL) 
		{
			if (MessageBox(NULL, "Fullscreen mode could not initialize.\nWould you like to use windowed mode?\n",
				           "Error", MB_YESNO | MB_ICONQUESTION) == IDYES)    // Prompt for windowed mode
			{
				m_bFullscreen = FALSE;     // Switch to windowed mode
			}
			else     // Exit the application (fullscreen could not switch and user did not want windowed mode)
				return FALSE;     // Return on error
		}
	}

	// Check for fullscreen mode
	if (m_bFullscreen)    // Are we in fullscreen mode?
	{
		dwExStyle = WS_EX_APPWINDOW;     // Set window ext. style
		dwStyle   = WS_POPUP;            // Set window style
		ShowCursor(FALSE);      // Hide the cursor
	}
	else      // Windowed mode
	{
		dwExStyle = WS_EX_APPWINDOW | WS_EX_WINDOWEDGE;    // Set window ext. style
		dwStyle   = WS_OVERLAPPEDWINDOW;                   // Set window style
	}

	AdjustWindowRectEx(&wndRect, dwStyle, FALSE, dwExStyle);     // Adjust window's rect.


	// Attempt to create the window itself using 'CreateWindowEx'
	if (! (m_hWnd = CreateWindowEx(dwExStyle,             // Window's extended style
		                           lpszClassName,         // Window's class name
								   lpszTitle,             // Window's title
								   WS_CLIPSIBLINGS | WS_CLIPCHILDREN | dwStyle,    // Set window style
								   0, 0,         // Window position (top-left corner)
								   wndRect.right - wndRect.left,     // Adjusted window width
								   wndRect.bottom - wndRect.top,     // Adjusted window height
								   NULL,      // No parent window
								   NULL,      // No menu
								   m_hInstance,   // Application instance handle
								   NULL)))     // Don't pass anything to 'WM_CREATE' message
	{
		// Kill the window, display error message, and return an error
		char szError[256];
		sprintf(szError, "Last Error: %d", GetLastError());

		KillWindow();     // Kill the window (and anything else that was already initialized)
		MessageBox(NULL, "Error in 'CreateWindowEx' in function 'CGLWindow::CreateGLWindow'...\n", NULL, NULL);
		MessageBox(NULL, szError, NULL, NULL);

		return FALSE;
	}


	// Setup a pixel format descriptor
	static PIXELFORMATDESCRIPTOR pfd = 
	{
		sizeof(PIXELFORMATDESCRIPTOR),       // Set size of 'pfd' object

		1,      // Version number
		PFD_DRAW_TO_WINDOW |      // Format must support window
		PFD_SUPPORT_OPENGL |      // Format must support OpenGL
		PFD_DOUBLEBUFFER |        // Format must support double-buffering
		PFD_TYPE_RGBA,            // Request RGBA format
		nBpp,                     // Select specified color depth (bpp)
		0, 0, 0, 0, 0, 0,         // Ignore the color bits
		0,                        // No alpha buffer
		0,                        // Shift bit ignored
		0,                        // No accumulation buffer
		0, 0, 0, 0,               // Accumulation bits ignored
		16,                       // 16-bit depth (Z) buffer
		0, 0,                     // No stencil or auxiliary buffer
		PFD_MAIN_PLANE,           // Main drawing layer
		0,                        // Reserved (ignore)
		0, 0, 0                   // Layer masks ignored
	};


	// Attempt to get device context for window
	if (! (m_hDC = GetDC(m_hWnd))) 
	{
		// Kill the window, display error message, and return an error
		KillWindow();      // Kill the window
		MessageBox(NULL, "Error creating Device Context in function 'CGLWindow::CreateGLWindow'...\n", NULL, NULL);

		return FALSE;
	}

	// Attempt to select the pixel format (from 'pfd' object)
	if (! (nPixelFormat = ChoosePixelFormat(m_hDC, &pfd))) 
	{
		// Kill the window, display error message, and return an error
		KillWindow();      // Kill the window
		MessageBox(NULL, "Error in 'ChoosePixelFormat' in function 'CGLWindow::CreateGLWindow'...\n", NULL, NULL);

		return FALSE;
	}

	// Attempt to set the pixel format for the screen
	if (! SetPixelFormat(m_hDC, nPixelFormat, &pfd)) 
	{
		// Kill the window, display error message, and return an error
		KillWindow();      // Kill the window
		MessageBox(NULL, "Error in 'SetPixelFormat' in function 'CGLWindow::CreateGLWindow'...\n", NULL, NULL);

		return FALSE;
	}

	// Attempt to create an OpenGL rendering context
	if (! (m_hRC = wglCreateContext(m_hDC))) 
	{
		// Kill the window, display error message, and return an error
		KillWindow();      // Kill the window
		MessageBox(NULL, "Error creating GLRC in function 'CGLWindow::CreateGLWindow'...\n", NULL, NULL);

		return FALSE;
	}

	// Attempt to activate the rc
	if (! wglMakeCurrent(m_hDC, m_hRC)) 
	{
		// Kill the window, display error message, and return an error
		KillWindow();      // Kill the window
		MessageBox(NULL, "Error activating 'm_hRC' in function 'CGLWindow::CreateGLWindow'...\n", NULL, NULL);

		return FALSE;
	}


	ShowWindow(m_hWnd, SW_SHOW);        // Show the window
	SetForegroundWindow(m_hWnd);        // Set window as foreground window
	SetFocus(m_hWnd);                   // Set focus to this window
	ResizeScene(m_nWidth, m_nHeight);   // Resize the GL scene to the window

	// Attempt to initialize OpenGL
	if (! InitGL()) 
	{
		// Kill the window, display error message, and return an error
		KillWindow();      // Kill the window
		MessageBox(NULL, "Error initializing OpenGL in function 'CGLWindow::InitGL'...\n", NULL, NULL);

		return FALSE;
	}


	return TRUE;    // Successful; return okay
}

The call to 'CreateWindowEx' fails, and displays "Last Error: 87". I used the 'Error Lookup' tool, and it says "The parameter is incorrect." Why is this happening? I have never had a problem creating a window before, and it only does this when called from a class function. It has nothing to do with any of the other functions that are called in 'CreateGLWindow'. It successfully registers the window class, and everything between 'RegisterClass' and 'CreateWindowEx' succeeds. Can anyone tell me why this is happening? I am using MSVC++ 6.0 on Win98.
:==- Why don't the voices just leave me alone?! -==:
The_Apocalypse
The_Apocalypse
When you call the function, are you sure you are passing a valid class name and a valid title?
Apocalypse, the End of the World!
TFS_Waldo
TFS_Waldo
Yes, I am sure. =(
:==- Why don't the voices just leave me alone?! -==:
Agony
Agony
Some windows styles and extended styles might be incompatible with each other. That be my first course of investigation: looking up the styles that you use in the documentation to see if there are any conflicts. I know WS_POPUP has some restrictions; don't know if WS_EX_APPWINDOW is one of them.
"We should have a great fewer disputes in the world if words were taken for what they are, the signs of our ideas nly, and not for things themselves." - John Locke o
TFS_Waldo
TFS_Waldo
Well, I don't think that's the problem. And I just tried altering it, and it's the same thing. I used the NeHe base code as an example for my code. And I'm not using 'WS_POPUP' because I am first testing it in windowed mode. I only specify the 'WS_POPUP' style when I go fullscreen (as does NeHe).
:==- Why don't the voices just leave me alone?! -==:
TFS_Waldo
TFS_Waldo
Does anyone else have any suggestions. I don't understand why 'CreateWindow(Ex)' works until I call it from a class function. If I create a standard Win32 app., it works just fine. But somehow, I am passing an invalid parameter (as told by error # '87'). Anyone else?
:==- Why don't the voices just leave me alone?! -==:
Mastaba
Mastaba
How is glWndProc declared?
TFS_Waldo
TFS_Waldo
In the 'CGLWindow' class:

static LRESULT CALLBACK glWndProc(CGLWindow *pGLWnd, HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); // Default wnd. proc. (overrideable)

I had to declare it static, because if I didn't, I would get an error. Does that help any? =)
:==- Why don't the voices just leave me alone?! -==:
Skeleton_V@T
Skeleton_V@T
At the first glance I can see you're using WNDCLASS for CreateWindowEx (), what does that mean ?.[smile]
This should cause an unhandled exception...
--> The great thing about Object Oriented code is that it can make small, simple problems look like large, complex ones <--
xDS4Lx
xDS4Lx
Try passing the application instance to the function instead of using GetModuleHandle() to make sure that ur getting the right application instance, just a guess.
"Computer games don't affect kids; I mean if Pac-Man affected us as kids, we'd all be running around in darkened rooms, munching magic pills and listening to repetitive electronic music." - Kristian Wilson, Nintendo, Inc, 1989
TFS_Waldo
TFS_Waldo
That didn't do anything. =(
:==- Why don't the voices just leave me alone?! -==:
Mastaba
Mastaba
glWndProc is declared incorrectly. It must be of the form
static LRESULT CALLBACK glWndProc(HWND hwnd,UINT uMsg,WPARAM wParam,LPARAM lParam);
TFS_Waldo
TFS_Waldo
That was a result of my own stupidity! =P LoL, I never thought about that. I had declared it to take a 'CGLWindow' pointer so it could access the members of the window class (since the function is static, it can't do it by itself). But now, when I create the function definition, I just do it in my 'WinMain' file, so that I can access the 'g_pMainWnd' object.

Thank you all for your suggestions/solution! =)
:==- Why don't the voices just leave me alone?! -==:
Skeleton_V@T
Skeleton_V@T
Did you try to redeclare wndClass to be WNDCLASSEX ?.
If so, put wndClass.hIconSm = NULL to fully initialize wndClass, it should be no problem then.
Also glWndProc is declared incorrectly as Mastaba stated.

Good luck.
Edit: Well, :-p congrats.
--> The great thing about Object Oriented code is that it can make small, simple problems look like large, complex ones <--
Mastaba
Mastaba
You could still have glWndProc in your class if you store the class instance in the window's user data space when the window is created. Then glWndProc could retrieve the instance from the user data space of the window.
TFS_Waldo
TFS_Waldo
Yeah. It's still in my class. I just don't create the definition for the function in the 'GL_Window.cpp' file. I create the code in the file containing my 'WinMain' function. =)

Thank you all though! =)
:==- Why don't the voices just leave me alone?! -==:
The_Apocalypse
The_Apocalypse
@Skeleton_V@T
WNDCLASSEX doesn't have anything to do with CreateWindowEx(). You can use both types of window classes on both types of windows.
... and you forgot to say to set the size of the structure to sizeof(WNDCLASSEX)! (WNDCLASS doesn't have a size variable)
Apocalypse, the End of the World!

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.