Problem with closing window

Started by
10 comments, last by oditogre 19 years, 10 months ago
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?
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.
Well, R2D22U2..
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]
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]
Well, R2D22U2..
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]
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]
Well, R2D22U2..
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).
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]
Well, R2D22U2..
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.

Fruny: Ftagn! Ia! Ia! std::time_put_byname! Mglui naflftagn std::codecvt eY'ha-nthlei!,char,mbstate_t>

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]

This topic is closed to new replies.

Advertisement