Jump to content
  • Advertisement
Sign in to follow this  
ajm113

(Classes) Setting a class pointer to NULL? (C++)

This topic is 3448 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hi, I just got full screen mode working on my game finally, and now I run into a problem where the window is not checking for messages, WM_CLOSE, WM_KEYUP
LRESULT CALLBACK Core::WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) {
		
			Core* pWnd = NULL;
		static bool bProcessed = false;

		switch (message) {
			case WM_NCCREATE: {

				SetWindowLong(hWnd, GWL_USERDATA, (long) (LPCREATESTRUCT(lParam)->lpCreateParams));
		break;
			}
			default: {
				pWnd = (Core*) GetWindowLong(hWnd, GWL_USERDATA);
				if(NULL != pWnd) {
					bProcessed = pWnd->MessageHandler(message, wParam, lParam);
				}
			}
		}
		if(!bProcessed) {
		return DefWindowProc(hWnd, message, wParam, lParam);
		}

		return 0;
	} //Window Proc






What's supposed to happen is that MessageHandler() is supposed to get called, but can't since pWnd is NULL. I did look over other code, but seem's I can't get pWnd->MessageHandler function to execute, since GetWindowLong isn't doing anything for me. Core class just has the game variables and function, just like any other 'basic' class would. window height, width, bits, fps pointer, etc. I am not sure how to handle this situation, I would appreciate any feed back on this issue, since I don't know what I am doing wrong. Can this issue have anything to do with the last argument in the function for CreateWindowEx? I did have the last arg, (void*)this, but that just caused my window to be invisible, but if the last arg on CreaWindowEX was NULL, fullscreen and window mode works just not the Message Handler any more. [Edited by - ajm113 on December 16, 2008 6:36:21 PM]

Share this post


Link to post
Share on other sites
Advertisement
Is the value in GWL_USERDATA actually getting set to something useful? Have you put a breakpoint there and looked at it?

Did you just copy this from somewhere or did you actually write it? Do you understand what its doing?

Share this post


Link to post
Share on other sites
Yes, I break pointed it and looked through the pWned pointer and didn't see anything new or not NULL, so pretty much I don't know what I am looking for.

I did do a msdn on that function, but didn't have time to look over it, but it's supposed too retrieve information about the specified window?

I learned it from a video series.

[Edited by - ajm113 on December 16, 2008 7:52:44 PM]

Share this post


Link to post
Share on other sites
IIRC, that GWL_USERDATA value lets you attach any 32-bits of data you want to the window. I've seen in used to allow object-oriented window abstraction and that sort of thing (tuck a pointer to the object into that value so that you can retrieve the object in the event handler, etc).

Actually, that appears to be exactly what the code is going. It's casting that value to a Core*. So it should be hitting the SetWindowLong after you instantiate your Core object. What is it putting in there? That's sort of integral to your problem.

Share this post


Link to post
Share on other sites
Post the code to your MessageHandler(), you may not be returning the correct value for a certain message, thus causing it to be invisible.

Share this post


Link to post
Share on other sites
Its not changing a thing on GetWindowLong still, sorry to sound dumb, but should I make a pointer in the class just for GetWindowLong? I'm kinda lost on what you said...

I don't want to seem I need to get spoon feed, but can you write a small example of what you want me to try? If it's not too much to ask?

@ fitfool, sure why not:



bool Core::MessageHandler(UINT message, WPARAM wParam, LPARAM lParam) {

switch(message) {

case WM_CREATE: {
if(MaxMe) { ShowWindow(hWnd, SW_MAXIMIZE); }
return true;
}
case WM_CLOSE: {
DestroyWindow(hWnd);
ClearAll();
return true;
}
case WM_DESTROY: {
m_pErrorHandler.Message("#Game Closing!");
PostQuitMessage(0);
return true;
}
case WM_ACTIVATE: {
if(LOWORD(wParam) == WA_INACTIVE) {
m_bActive = false;
WindowFocusLost();
}else{
m_bActive = false;
WindowFocusRecived();
}
return true;
}
case WM_SYSKEYDOWN:{
m_bKeys[wParam] = true;
break;}

case WM_SYSKEYUP:{
m_bKeys[wParam] = false;
break;}


case WM_SYSCOMMAND: {

switch (wParam) {
case SC_SCREENSAVE:
case SC_MONITORPOWER: {
return true;
}


default: {
return false;
}
}
}
case WM_SIZE: {
RECT rect;

GetClientRect (hWnd, &rect);
//MoveWindow (RenderWindow, 0, 0, rect.right-rect.left-0, rect.bottom-rect.top, true);

GetClientRect (hWnd, &rect);
ResizeGLWindow (rect.right-rect.left, rect.bottom-rect.top);

m_iWidth = rect.right-rect.left;
m_iHeight = rect.bottom-rect.top;
break;

return 0;
}
case WM_KEYDOWN: {

m_bKeys[wParam] = true;
return true;
}
case WM_KEYUP: {
m_bKeys[wParam] = false;
return true;
}

default: {

return false;
}
}
return false;
}







Had to git rid of a few cases to make it shorter and easier too look at.

[Edited by - ajm113 on December 17, 2008 12:22:32 AM]

Share this post


Link to post
Share on other sites
The WindowProc is entered for every single message. Your pWnd variable is redeclared and reset to NULL everytime.

Either make pWnd a member of Core or static to the procedure.


And, i see it once again, if your message gets processed you return 0 as default. This is wrong!
There is no simple single return value for handled messages. It completely depends on the message and can be any value. If a message gets handled you should usually still pass it on to DefWindowProc (unless the MSDN states you shouldn't).

Share this post


Link to post
Share on other sites
Alright, well I fixed those problems with my code. I changed pWned into a static and got rid of making it NULL and removed the if(bProcessed) for DefWindowProc and removed return 0; in the code.

I am still having the same issue, becuase pWned isn't being set to anything thing when it goes through the if statment. If MessageHandler was called with pWned being NULL I get a access violation error, FYI.

Share this post


Link to post
Share on other sites
pWnd was *supposed* to be set to NULL everytime, and it MUST be set to NULL evertime for it to work... that isn't the problem. I'm asking "what is put in the GWL_USERDATA when your window is created?"... you keep telling me what comes out of GetWindowLong, but I'm not interested in that because it is CLEARLY wrong. I want to know what gets put into GWL_USERDATA in the first place.

Here's what's supposed to be happening... you create an instance of Core, which presumably creates a window using CreateWindowEx(). CreateWindowEx() (or CreateWindow()) takes an LPVOID lpParam value, which Core presumably sets to "this"--meaning a pointer to itself. That CreateWindow() call results in a WM_NCCREATE message sent to that method you posted.

Your event handler sees that it has a WM_NCCREATE message, so it uses SetWindowLong to set the GWL_USERDATA value for that hwnd to that same pointer that it passed to CreateWindowEx (which is passed along to the handler there as an argument lParam [EDIT: the pointer is actually passed as a member of a CREATEPARAMS struct, and the lParam argument is a pointer to that struct... sorry for the confusion, I screwed up my description there a bit, but it isn't too important for you at this point]

Now, anytime a message comes in, the call to GetWindowLong pulls that pointer out as a LONG, and casts it to a Core*. That gives you the pointer to the actual Core* associated with the hwnd for which you just received a message.

Does that makes sense? That bit of GWL_USERDATA that is placed/removed using Set/GetWindowLong is a pointer to a Core instance. Windows uses a C API... if you want an object oriented wrapper you have to use tricks like this.

Now, what I want to know and have been asking, is WHAT EXACTLY IS IT STICKING INTO THE GWL_USERDATA VALUE in the WM_NCCREATE message handler?

EDIT:

I just saw in your OP:
Quote:
Can this issue have anything to do with the last argument in the function for CreateWindowEx?

I did have the last arg, (void*)this, but that just caused my window to be invisible, but if the last arg on CreaWindowEX was NULL, fullscreen and window mode works just not the Message Handler any more.

YES, it has everything to do with it. If you put NULL in there, you get NULL out to be assigned to pWnd. Of course I can't see the rest of your code, but I see no reason why that wouled make your window invisible. More likely, the "invisibility" is a side effect of something else you're doing in your message handler after you get the pWnd pointer.


[Edited by - smitty1276 on December 17, 2008 12:19:37 AM]

Share this post


Link to post
Share on other sites
Oh, I understand now, sorry. This hasn't been my day today.. So I must have been thinking about my frustration with Maya today at school.

Anyways

Well the return value is 0 for SetWindowLong, and the value entered is 0 as well.

(EDIT)
I knew it! (Slap To The Head)

Well I'll cast it as (void*)this and check around for the problem, unless you can spot it in a minute, be my guest and go a head and tell me.


//Tmain
WNDCLASS wc;

hInstance = GetModuleHandle(NULL); // Grab An Instance For Our Window
wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC; // Redraw On Move, And Own DC For Window
wc.lpfnWndProc = (WNDPROC) core.WindowProc; // WndProc Handles Messages
wc.cbClsExtra = 0; // No Extra Window Data
wc.cbWndExtra = 0; // No Extra Window Data
wc.hInstance = hInstance; // Set The Instance
wc.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_SMALL)); // Load The Default Icon
wc.hCursor = LoadCursor(NULL, IDC_CROSS); // Load The Arrow Pointer
wc.hbrBackground = NULL; // No Background Required For GL
wc.lpszMenuName = NULL; // We Don't Want A Menu
wc.lpszClassName = "OpenGL"; // Set The Class Name

if(!RegisterClass(&wc)) {
hInstance = NULL;

return false;
}
//End of tMain



//Create inside of core class
if(fullscreen){

DEVMODE dmScreenSettings; // Device Mode
memset(&dmScreenSettings,0,sizeof(dmScreenSettings)); // Makes Sure Memory's Cleared
dmScreenSettings.dmSize=sizeof(dmScreenSettings); // Size Of The Devmode Structure
dmScreenSettings.dmPelsWidth = m_iWidth; // Selected Screen Width
dmScreenSettings.dmPelsHeight = m_iHeight; // Selected Screen Height
dmScreenSettings.dmBitsPerPel = 32; // Selected Bits Per Pixel
dmScreenSettings.dmFields=DM_BITSPERPEL|DM_PELSWIDTH|DM_PELSHEIGHT;


if(ChangeDisplaySettings(&dmScreenSettings,CDS_FULLSCREEN)!=DISP_CHANGE_SUCCESSFUL)
{
// If The Mode Fails, Offer Two Options. Quit Or Run In A Window.
if (MessageBox(NULL,"The Requested Fullscreen Mode Is Not Supported By\nYour Video Card. Use Windowed Mode Instead?","NeHe GL",MB_YESNO|MB_ICONEXCLAMATION)==IDYES)
{
fullscreen=FALSE; // Select Windowed Mode (Fullscreen=FALSE)
}
}
}



hInst = _hInst;
//LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
//LoadString(hInstance, IDC_THEARICLE, szWindowClass, MAX_LOADSTRING);

if((m_iHeight <= 0) || (m_iWidth <= 0) || (m_iRefreshRate <= 0)) {

m_pErrorHandler.Message("Window Parameters Are Invalid!");
m_pErrorHandler.SetError(EC_Windows, "Window Parameters Are Invalid!");
m_pErrorHandler.ShowErrorMessage();

return false;
}





RECT rcWnd;

rcWnd.left = 0;
rcWnd.right = m_iWidth;
rcWnd.top = 0;
rcWnd.bottom = m_iHeight;

DWORD dwStyle, dwStyleEx;
if(fullscreen) { //Fullscreen Application
dwStyle = WS_POPUP;
dwStyleEx = WS_EX_APPWINDOW;

}else{ //Windowed Game!
dwStyle = WS_VISIBLE | WS_OVERLAPPED | WS_SYSMENU | WS_MINIMIZEBOX | WS_MAXIMIZEBOX;
dwStyleEx = WS_EX_APPWINDOW;

}

AdjustWindowRectEx(&rcWnd, dwStyle, FALSE, dwStyleEx); // Adjust Window To True Requested Siz

if (!(hWnd = CreateWindowEx(dwStyleEx, "OpenGL", "Space Music 1.0", dwStyle | WS_CLIPSIBLINGS | WS_CLIPCHILDREN,
CW_USEDEFAULT, 0,

rcWnd.right - rcWnd.left,
rcWnd.bottom - rcWnd.top,

NULL,
NULL,
hInst, NULL))) {
m_pErrorHandler.Message("Could Not Create Window!");
m_pErrorHandler.SetError(EC_Windows, "Could Not Create Window!");
m_pErrorHandler.ShowErrorMessage();

return FALSE; // Return FALSE

}

//Skipping To End

ShowWindow(hWnd, SW_SHOW);
SetForegroundWindow(hWnd);
SetFocus(hWnd);
UpdateWindow(hWnd);
ResizeGLWindow (rcWnd.right-rcWnd.left, rcWnd.bottom-rcWnd.top);

Core::SetGLDefaults();



while(!bQuit)
{
Core::Render();
if(PeekMessage(&message, NULL, 0, 0, PM_REMOVE))
{
if(WM_QUIT == message.message) {
bQuit = true;

}else{
TranslateMessage(&message);
DispatchMessage(&message);
}
}else{
Core::Frame();
}
}


Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

Participate in the game development conversation and more when you create an account on GameDev.net!

Sign me up!