Sign in to follow this  
ajm113

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

Recommended Posts

ajm113    355
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
smitty1276    560
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
ajm113    355
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
smitty1276    560
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
fitfool    113
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
ajm113    355
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
Endurion    5411
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
ajm113    355
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
smitty1276    560
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
ajm113    355
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
smitty1276    560
Quote:
Original post by ajm113
Well the return value is 0 for SetWindowLong, and the value entered is 0 as well.
Right. If I had read your original post more carefully, I would have noticed that myself. :-)

That's your problem. You need to be passing "this" for the last arg of CreateWindowEx. That is the value that gets passed to SetWindowLong, and which later comes out of GetWindowLong. If it isn't there, you get a NULL pointer, and the event handler is never called.

Your invisible window problem is unrelated to the "this" you're passing in. It's something else you're doing in the event handler, most likely.

Share this post


Link to post
Share on other sites
ajm113    355
Alright, at least I am getting somewhere, thanks!

I know I had this issue before somewhere along the ways, but I can't remember what I did on my first full screen..

I'll let you know if the message handler still isn't working when I have the window going, unless someone here spots the problem right away or suggests something.

I'll work on it tomorrow, I have a lot of free time, but I don't know how much of a help NeHe's tutorial will be much of a help since, my methods are different then his tutorials on window creation.

Share this post


Link to post
Share on other sites
ajm113    355
It resizes the OpenGL view port so it fits the screen of my window, doubt that has to do with the problem, since there is no Win32 API functionality in it.

EDIT: Yeah commented out or not full screen doesn't work, but it looks in window mode the game works fine.

Share this post


Link to post
Share on other sites
smitty1276    560
It's sort of hard for me to get a sense of the chronology of all of this code. If I were you, I would set some breakpoints and figure out what is and isn't getting called to pinpoint the problem. Something you are calling is causing your window to be invisible... what's getting called that isn't called when you pass NULL?

Is that MoveWindow call actually commented out still? Anything that affects the window state is suspect.

Share this post


Link to post
Share on other sites
ajm113    355
I was thinking the same, I'll do it today like I said since it's 12 AM.

MoveWindow func was for a map editor I was making a while back and I was moving code around. I don't think it does anything any more except do the same thing for GL resize, but I had a 'control container' that held the OpenGL view port, I wouldn't worry about it, since that control doesn't exist anymore.

Share this post


Link to post
Share on other sites
ajm113    355
Huh so it was MoveWindow! I had a small script that centered the window and maybe not updated it and that's probably why it wasn't showing!

The only problems I have now on full screen is that my mouse won't center on the screen and my fonts on the full screen mode aren't showing.

SetCursorPos(m_iWidth>>1, m_iHeight);

& for the fonts in Y position are set up like this:
m_iHeight-25.0

I have it set up like that, and the font issue mite be a mis calculation on position I don't know, have to debug it.

Share this post


Link to post
Share on other sites
fitfool    113
Don't forget to read the docs for the windows messages too. For instance, you return 'true' for the WM_CREATE message, when it states that you should return 0 if you want to continue creation of your window.

http://msdn.microsoft.com/en-us/library/ms632619(VS.85).aspx

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this