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);
}