window api编程 关闭窗口程序未退出的原因和解决方案

代码示例
#include <Windows.h>

int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PWSTR szCmd, int nShow);
LRESULT CALLBACK MainProc(HWND, UINT, WPARAM, LPARAM);
void prompt(LPCWSTR lpText);

int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PWSTR szCmd, int nShow) {

	WNDCLASS winClass = {0,};
	HWND hwnd = 0;
	MSG msg = { 0, };
	BOOL bRet = 0;

	winClass.lpfnWndProc = MainProc;
	winClass.lpszClassName = TEXT("MainWindow");
	winClass.hCursor = LoadCursor(0, IDC_ARROW);
	winClass.hbrBackground = (HBRUSH)COLOR_APPWORKSPACE;
	winClass.style = CS_VREDRAW | CS_HREDRAW;

	if (!RegisterClass(&winClass)) {
		prompt(TEXT("RegisterClass failed"));
		return 0;
	}

	hwnd = CreateWindow(TEXT("MainWindow"),
		TEXT("弹出菜单"),
		WS_OVERLAPPEDWINDOW,
		CW_USEDEFAULT,
		CW_USEDEFAULT,
		CW_USEDEFAULT,
		CW_USEDEFAULT,
		0, 0,
		hInstance,
		0
	);

	if (!hwnd) {
		prompt(TEXT("CreateWindow failed"));
		return 0;
	}

	ShowWindow(hwnd, nShow);
	UpdateWindow(hwnd);

	while (GetMessage(&msg,hwnd, 0, 0)) {
		
		TranslateMessage(&msg);
		DispatchMessageW(&msg);
	}

	return 0;
}

LRESULT CALLBACK MainProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) {

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

void prompt( LPCWSTR lpText) {
	MessageBox(NULL, lpText, TEXT(""), MB_OK);
}

上面的代码关闭窗口是无法退出程序的,关键在GetMessage的第二个参数,这个参数填的是窗口的句柄,表示只过滤当前窗口的消息,而PostQuitMessage没有指定窗口,自然也不会被GetMessage接收到

那么我们只要发送WM_QUIT消息时指定窗口,不就行了

尝试
#include <Windows.h>

int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PWSTR szCmd, int nShow);
LRESULT CALLBACK MainProc(HWND, UINT, WPARAM, LPARAM);
void prompt(LPCWSTR lpText);

int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PWSTR szCmd, int nShow) {

	WNDCLASS winClass = {0,};
	HWND hwnd = 0;
	MSG msg = { 0, };
	BOOL bRet = 0;

	winClass.lpfnWndProc = MainProc;
	winClass.lpszClassName = TEXT("MainWindow");
	winClass.hCursor = LoadCursor(0, IDC_ARROW);
	winClass.hbrBackground = (HBRUSH)COLOR_APPWORKSPACE;
	winClass.style = CS_VREDRAW | CS_HREDRAW;

	if (!RegisterClass(&winClass)) {
		prompt(TEXT("RegisterClass failed"));
		return 0;
	}

	hwnd = CreateWindow(TEXT("MainWindow"),
		TEXT("弹出菜单"),
		WS_OVERLAPPEDWINDOW,
		CW_USEDEFAULT,
		CW_USEDEFAULT,
		CW_USEDEFAULT,
		CW_USEDEFAULT,
		0, 0,
		hInstance,
		0
	);

	if (!hwnd) {
		prompt(TEXT("CreateWindow failed"));
		return 0;
	}

	ShowWindow(hwnd, nShow);
	UpdateWindow(hwnd);

	while ((bRet = GetMessage(&msg,hwnd, 0, 0))&& bRet != -1) {
		
		TranslateMessage(&msg);
		DispatchMessageW(&msg);
	}

	return 0;
}

LRESULT CALLBACK MainProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) {

	switch (msg) {
		
		case WM_DESTROY:
			PostMessage(hwnd, WM_QUIT, 0, 0);
			return 0;
	}
	return DefWindowProc(hwnd, msg, wParam, lParam);
}

void prompt( LPCWSTR lpText) {
	MessageBox(NULL, lpText, TEXT(""), MB_OK);
}

但是还是不行,因为当你关闭窗口时,该窗口实例就被销毁了,对GetMessage来说,这是一个无效句柄的消息,自然也就不会接收了

解决方案一

只要把GetMessage的第二个参数置NULL就行了,这样所有窗口的消息都会被接收

解决方案二

但是有时候就是需要过滤不同的窗口消息怎么办呢?

hWnd是无效的窗口句柄或lpMsg是无效的指针,函数返回-1,也就是说当GetMessage监听的窗口失效,它就会返回-1

所以我们只要加上当GetMessage返回-1时,退出消息循环即可

#include <Windows.h>

int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PWSTR szCmd, int nShow);
LRESULT CALLBACK MainProc(HWND, UINT, WPARAM, LPARAM);
void prompt(LPCWSTR lpText);

int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PWSTR szCmd, int nShow) {

	WNDCLASS winClass = {0,};
	HWND hwnd = 0;
	MSG msg = { 0, };
	BOOL bRet = 0;

	winClass.lpfnWndProc = MainProc;
	winClass.lpszClassName = TEXT("MainWindow");
	winClass.hCursor = LoadCursor(0, IDC_ARROW);
	winClass.hbrBackground = (HBRUSH)COLOR_APPWORKSPACE;
	winClass.style = CS_VREDRAW | CS_HREDRAW;

	if (!RegisterClass(&winClass)) {
		prompt(TEXT("RegisterClass failed"));
		return 0;
	}

	hwnd = CreateWindow(TEXT("MainWindow"),
		TEXT("弹出菜单"),
		WS_OVERLAPPEDWINDOW,
		CW_USEDEFAULT,
		CW_USEDEFAULT,
		CW_USEDEFAULT,
		CW_USEDEFAULT,
		0, 0,
		hInstance,
		0
	);

	if (!hwnd) {
		prompt(TEXT("CreateWindow failed"));
		return 0;
	}

	ShowWindow(hwnd, nShow);
	UpdateWindow(hwnd);

	while ((bRet = GetMessage(&msg,hwnd, 0, 0))) {
		if (bRet == -1)
			break;
		TranslateMessage(&msg);
		DispatchMessageW(&msg);
	}

	return 0;
}

LRESULT CALLBACK MainProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) {

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

void prompt( LPCWSTR lpText) {
	MessageBox(NULL, lpText, TEXT(""), MB_OK);
}
posted @ 2022-06-30 11:27  乘舟凉  阅读(263)  评论(0编辑  收藏  举报