How to catch WM_DESTROY (from Alt+F4 or Close)

Hi there

Fooling around with my first window. Following problem:

I have included a security question to ask the user if he really wants to close the window. It has a "yes" and a "no" button and the QuitMessage only gets posted if the user presses "yes". So far so good.

The problem is that, if the user presses Alt+F4 or klicks the "Close" symbol in the topright corner of the window, this does not work. While the security question does appear, the window already closes before it appears. Even worse, if "no" is pressed, the program seems to continue running in the background despite the window no longer being open (indicated by the fact that VisualStudio can no longer access the solution).

I have already tried using WM_CLOSE instead, but the only effect this had was that the window stayed open until one of the buttons of the security question was pressed, but then it would still be closed no matter what was pressed. And the problem with it still running somewhere in the background after pressing "no" also persisted.

So, how can I catch "WM_DESTROY" and only pass it on if the user presses the "yes"-button on the security message?

My code so far:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125

#include <windows.h>

// Callback-Fcuntion Prototype
//
LRESULT CALLBACK WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);

// Main Program
//
int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR lpcmdline, int ncmdshow)
{
	WNDCLASSEX	windowclass;	// structure for the window properties
	HWND		hWnd;			// window handle
	MSG			message;		// message

	// Class Name for the Window can be chosen freely
	const TCHAR szClassName[] = TEXT("My first Window");

	// Fill Structure with desired Properties

	// Save size of Structure
	windowclass.cbSize = sizeof(WNDCLASSEX);

	// Window shall be redrawn when moved
	windowclass.style = CS_HREDRAW | CS_VREDRAW;

	// Pointer to Callback-Function
	windowclass.lpfnWndProc = WindowProc;

	// No advanced Settings
	windowclass.cbClsExtra = 0;
	windowclass.cbWndExtra = 0;

	// Save Instance
	windowclass.hInstance = hInst;

	// Specify Icons and Cursor
	windowclass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
	windowclass.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
	windowclass.hCursor = LoadCursor(NULL, IDC_ARROW);

	// Specify Background Color
	windowclass.hbrBackground = (HBRUSH)COLOR_BACKGROUND + 1;	// uses current windows setting for background, the +1 is necessary for that to work, but it is not clear why

	// We don't need a Menu yet
	windowclass.lpszMenuName = NULL;

	// Specify Class Name
	windowclass.lpszClassName = szClassName;

	// Register Window Class
	if (!RegisterClassEx(&windowclass))
		return (0);

	// Create Window
	//
	hWnd = CreateWindowEx(NULL, szClassName, TEXT("The first Window!"), WS_OVERLAPPEDWINDOW | WS_VISIBLE, CW_USEDEFAULT, CW_USEDEFAULT, 1000, 500, NULL, NULL, hInst, NULL);

	// Check if everything went as it should
	if (hWnd == NULL)
		return(0);

	// The Heartbeat of the Program
	// Here all Messages are collected, translated and handed over
	//
	while (GetMessage(&message, NULL, 0, 0))
	{
		TranslateMessage(&message);		// translate message to a format usable by the callback-function
		DispatchMessage(&message);		// hand the translated message over to the callback function

	}

	// End Program
	return (int)(message.wParam);

}// WinMain


 // Callback-Function for Message Handling
 //
LRESULT CALLBACK WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
	// Analyze Messages
	//
	switch (message)
	{
	case WM_DESTROY:	// close Window? (also Alt+F4)

		if (MessageBox(hWnd, TEXT("End Program?"), TEXT("Security Check"), MB_YESNO | MB_ICONQUESTION) == 6)	// if "yes" has been pressed
		{
			PostQuitMessage(0);		// send Quit-message so the window closes
			return(0);

			break;
		}
		else
			break;

	case WM_KEYDOWN:	// was a key pressed?

		// Yes = Switch based on Key pressed
		switch (wParam)
		{
		case VK_ESCAPE:		// Escape has been pressed

			if (MessageBox(hWnd, TEXT("End Program?"), TEXT("Security Check"), MB_YESNO | MB_ICONQUESTION) == 6)	// if "yes" has been pressed
			{
				PostQuitMessage(0);		// send Quit-message so the window closes
				return(0);

				break;
			}
			else
				break;
		}

		break;

	}

	// The Message was not processed by us so let Windows process it
	return (DefWindowProc(hWnd, message, wParam, lParam));

}// WindowProc
Last edited on
The user can close an application window by clicking the Close button, or by using a keyboard shortcut such as ALT+F4. Any of these actions causes the window to receive a WM_CLOSE message. The WM_CLOSE message gives you an opportunity to prompt the user before closing the window. If you really do want to close the window, call the DestroyWindow function. Otherwise, simply return zero from the WM_CLOSE message, and the operating system will ignore the message and not destroy the window.
https://docs.microsoft.com/en-us/windows/win32/learnwin32/closing-the-window

There is an example on the linked page.

Note: return zero above means:
return a zero value from the window procedure without forwarding the WM_CLOSE message to DefWindowProc.
(If it gets a WM_CLOSE message, DefWindowProc would call DestroyWindow.)
That did it! Thank you! :-)

Here the changed code section:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

	case WM_CLOSE:	// close Window? (also Alt+F4)

		if (MessageBox(hWnd, TEXT("End Program?"), TEXT("Security Check"), MB_YESNO | MB_ICONQUESTION) == 6)	// if "yes" has been pressed
		{
			DestroyWindow(hWnd);	// destroy window

			PostQuitMessage(0);	// send Quit-message so the window closes
			return(0);

			break;
		}
		else
		{
			return 0;
			break;
		}
Last edited on
Topic archived. No new replies allowed.