Jump to content
  • Advertisement

Archived

This topic is now archived and is closed to further replies.

oditogre

Problem with closing window

This topic is 5284 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

Ok, I just picked up ''Beginning DirectX9'', by Wendy Jones. My problem is that when I close the example window program from Chapter 2, it appears to close but after a couple seconds it locks my system. I can ctrl-alt-del and kill it and then everything is normal, though. I have another ''basic window'' program I wrote when trying to work through another book from...enh...maybe a year or so ago that works fine and accomplishes about the same thing, but that''s about how long it''s been since I tried Windows programming, and I''m having hell figuring out what''s different between the two that''s making one work and not the other, aside from that the older one doesn''t separate out the window class registration, it''s just done within winmain, and it uses WNDCLASS instead of WNDCLASSEX. I''m using MS-VC++ 6.0 on a Win98SE machine, if that makes a difference. Any tips on what I might be missing?

Share this post


Link to post
Share on other sites
Advertisement
you''ll need to post some code for us to see where the issue is. Include your Window Procedure at least. Otherwise all this thread is, is just a rant, and I''m sure you wanted more out of opening this thread than that.

Share this post


Link to post
Share on other sites
Working code (edited to conserve space, hopefully still readable):

#include <windows.h>
#include <d3d9.h>
LRESULT CALLBACK WndProc (HWND hWindow, UINT iMessage, WPARAM wParam, LPARAM lParam);
int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInst, LPSTR lpCmdLine, int nShowCmd)
{
WNDCLASS kWndClass;
kWndClass.hCursor = LoadCursor(NULL, IDC_ARROW);
kWndClass.hIcon = LoadIcon (NULL, IDI_APPLICATION);
kWndClass.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH);
kWndClass.hInstance = hInstance;
kWndClass.lpfnWndProc = WndProc;
kWndClass.lpszClassName = "01 Basic Window";
kWndClass.lpszMenuName = NULL;
kWndClass.cbClsExtra = NULL;
kWndClass.cbWndExtra = NULL;
kWndClass.style = NULL;
if(!RegisterClass (&kWndClass))
{
return -1;
}
HWND hWindow;
hWindow = CreateWindow ("01 Basic Window", "A BASIC Window", WS_OVERLAPPEDWINDOW |
WS_VISIBLE, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL,
hInstance, NULL);
ShowWindow (hWindow, nShowCmd);
MSG kMessage;
while (GetMessage (&kMessage, hWindow, 0, 0))
{
TranslateMessage(&kMessage);
DispatchMessage(&kMessage);
}
return 0;
}
LRESULT CALLBACK WndProc (HWND hWindow, UINT iMessage, WPARAM wParam, LPARAM lParam)
{
switch (iMessage)
{
case WM_CLOSE:
PostQuitMessage (0);
break;
default:
return DefWindowProc (hWindow, iMessage, wParam, lParam);
}
return 0;
}


Non-Working code (Again, edited a bit):

#include <windows.h>
#include <d3d9.h>
HINSTANCE hInst;
HWND wndHandle;
bool initWindow(HINSTANCE hInstance);
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow)
{
if (!initWindow(hInstance))
{
return false;
}
MSG msg;
ZeroMemory (&msg, sizeof(msg));
while(msg.message != WM_QUIT)
{
while(GetMessage(&msg, wndHandle, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
return (int)msg.wParam;
}
bool initWindow(HINSTANCE hInstance)
{
WNDCLASSEX wcex;
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc = (WNDPROC)WndProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = hInstance;
wcex.hIcon = 0;
wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wcex.lpszMenuName = NULL;
wcex.lpszClassName = "DirectXExample";
wcex.hIconSm = 0;
RegisterClassEx(&wcex);
wndHandle = CreateWindow("DirectXExample", "DirectXExample", WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT, 640, 480, NULL, NULL, hInstance, NULL);
if(!wndHandle)
{
return false;
}
ShowWindow(wndHandle, SW_SHOW);
UpdateWindow(wndHandle);
return true;
}
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch(message)
{
case WM_DESTROY:
PostQuitMessage(0);
break;
case WM_CLOSE:
PostQuitMessage(0);
break;
default:
return DefWindowProc (hWnd, message, wParam, lParam);
}
return DefWindowProc(hWnd, message, wParam, lParam);
}


[edited by - Oditogre on June 3, 2004 6:12:43 AM]

[edited by - Oditogre on June 3, 2004 7:04:01 AM]

Share this post


Link to post
Share on other sites
The code is kind of hard to read, but you can try this out:

At WM_CLOSE and WM_DESTROY, instead of break; put return 0 in its place...This is usually what I do. If that doesn't work, I'll try and take a closer look at the rest of your code. Try to use the [ source ] [ /source ] tags to enclose your code.

EDIT: Additionally, I don't always process WM_CLOSE, but I believe you should call DestroyWindow() if you handle that message, but not too sure. You'd have to try it and see how that works as well.

[edited by - nervo on June 3, 2004 6:49:12 AM]

Share this post


Link to post
Share on other sites
The 'return 0' fixed it, thanks.

Sorry 'bout the code, didn't know about the source tags.

Side notes (In case anybody else reads this topic later):
Removing the WM_CLOSE breaks it again...it needs to be in there, with return 0 instead of break, in order for the program to work.

The WM_CLOSE should not have been in there in my previous post. I had added it in while trying to figure it out on my own...it was not in the book, nor was there a 'default' case for the switch; I also added that one in.

Although this is a more-or-less functional fix, it still doesn't explain why the older code works and this doesn't. I'll have to edit that last post and put in the source tags, just in case anybody else wants to read through and maybe point out what the real problem is.

[edited by - Oditogre on June 3, 2004 7:02:39 AM]

Share this post


Link to post
Share on other sites
so you're saying that if your code looks like this:


switch(message)
{
case WM_DESTROY:
PostQuitMessage(0);
return 0;
}
return DefWindowProc(hWnd, message, wParam, lParam);
}


In that code, I deleted the default label, because its really unncessary here since if a match isn't made in the switch-case label it will drop out to returning DefWindowProc() anyway. I took out WM_CLOSE and just returned 0 from WM_DESTROY. That really should work.

You see, if you process a message and then break off from the switch-case code, you are basically passing off the same message to a default windows procedure for handling of the message, which will means a particular message will be handled twice, when it should only be handled once. Structure your code to simply return 0 at the end of each label so it doesn't drop out to DefWindowProc() unncessarily. DefWindowProc() should normally only handle messages that you do not choose to handle in your switch-case code.

[edited by - nervo on June 3, 2004 7:13:53 AM]

Share this post


Link to post
Share on other sites
Yep, that hangs my system. I can''t even begin to guess why, either. Like as not, I''ll look at it again in a day or two and figure it out, or I never will. *shrug* as long as it works, I suppose...but I''d really rather know why it does(n''t).

Share this post


Link to post
Share on other sites
Ok, I realized that I needed to compile your code and debug it myself. The culprit is this:

GetMessage()

Make the second parameter NULL and not just your window handle. I suppose the reason for this is so that the program can signal the OS that you are killing the app and not just sending messages solely to the window.(not sure about that) Try that.

EDIT: To be honest, I'm still trying to work it out in my head as to what is really going on behind the scenes. I imagine that using the sole window that you have as the second parameter should be fine in theory.

[edited by - nervo on June 3, 2004 7:43:02 AM]

Share this post


Link to post
Share on other sites
You won''t get your WM_QUIT message, if you supply a HWND handle in there. Therefore your window is gone and the loop keeps waiting for a message to a non-existant window.

Share this post


Link to post
Share on other sites
Ok, with:


while(GetMessage(&msg, NULL, 0, 0))

....
and
....

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch(message)
{
case WM_DESTROY:
PostQuitMessage(0);
break;
}
return DefWindowProc(hWnd, message, wParam, lParam);
}


The program works. Again, thanks for your help.

STILL, though, I'm not quite following why this is the case. :/

Edit: Strike that last comment, just looked at it again...ok, sooo...if case WM_DESTROY, the window is killed, but the embedded loop never gets to die, because there is no window for it to receive the message from, so it just keeps on truckin', yes?

[edited by - Oditogre on June 3, 2004 8:15:36 AM]

Share this post


Link to post
Share on other sites

  • Advertisement
×

Important Information

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

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!