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