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
(Classes) Setting a class pointer to NULL? (C++)
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
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]
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?
Did you just copy this from somewhere or did you actually write it? Do you understand what its doing?
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]
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]
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.
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.
Post the code to your MessageHandler(), you may not be returning the correct value for a certain message, thus causing it to be invisible.
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:
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]
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]
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).
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).
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.
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.
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:
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]
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]
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.
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.
//TmainWNDCLASS 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 classif(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 EndShowWindow(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(); } }
This topic is closed to new replies.
Advertisement
Popular Topics
Advertisement