win32 API编程之常用消息详解
一、发送消息的函数
- sendmessage
- postmessage
- postthreadmessage:向消息队列添加一个消息
实例代码:
#include<windows.h> #include<stdio.h> //自定义消息 #define WM_AAA WM_USER+1 HWND hWnd; HWND hWnd2; //自定义的窗口过程 LRESULT CALLBACK MyWindowProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam) { switch (Msg) { case WM_DESTROY: PostQuitMessage(0);//可以使GetMessage返回0 return 0; case WM_AAA: MessageBoxA(NULL, "窗口过程:WM_AAA", "测试", MB_OK); return 0; } return DefWindowProc(hWnd, Msg, wParam, lParam); } int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd) { //1.注册窗口类 WNDCLASS wnd; wnd.cbClsExtra = 0; wnd.cbWndExtra = 0; wnd.hbrBackground = (HBRUSH)(GetStockObject(GRAY_BRUSH));//背景色 wnd.hCursor = LoadCursor(NULL, IDC_ARROW);//光标 wnd.hIcon = LoadIcon(NULL, IDI_APPLICATION);//图标 //wnd.lpfnWndProc = DefWindowProc;//默认窗口过程函数,用于处理消息 wnd.lpfnWndProc = MyWindowProc;//自定义的窗口过程函数 wnd.lpszClassName = L"MrHuang";//窗口类名 wnd.lpszMenuName = NULL;//菜单资源名称 wnd.style = CS_HREDRAW;//窗口类、样式 wnd.hInstance = hInstance;//实例句柄 RegisterClass(&wnd); //创建窗口(返回之前发送WM_CREATE) hWnd = CreateWindow(L"MrHuang", L"第一个窗口程序", WS_OVERLAPPEDWINDOW, 100, 100, 300, 300, NULL, NULL, hInstance, NULL); //显示窗口 ShowWindow(hWnd, nShowCmd); //更新窗口(发送WM_PAINT) UpdateWindow(hWnd); //创建窗口2(返回之前发送WM_CREATE) hWnd2 = CreateWindow(L"MrHuang", L"第二个窗口程序", WS_OVERLAPPEDWINDOW, 100, 500, 300, 300, NULL, NULL, hInstance, NULL); //显示窗口 ShowWindow(hWnd2, nShowCmd); //更新窗口(发送WM_PAINT) UpdateWindow(hWnd2);
//消息循环(收到WM_QUIT消息退出) MSG msg; while (GetMessage(&msg, NULL, 0, 0)) { //说明两个窗口公用一个消息循环和线程消息队列 if (msg.message == WM_LBUTTONDOWN) { //char str[64]; //sprintf(str,"窗口句柄:%p", msg.hwnd); //MessageBoxA(NULL, str,"测试", MB_OK); //SendMessage直接发给窗口过程函数,并且阻塞,除非被窗口过程处理才返回 //SendMessage(hWnd, WM_AAA, 0, 0); //PostMessage放到线程消息队列里,并且立即返回,通过消息循环到窗口过程处理 //PostMessage(hWnd, WM_AAA, 0, 0); //PostThreadMessage放到线程消息队列里,不进入窗口过程 //PostThreadMessage(GetCurrentThreadId(), WM_AAA, 0, 0); //PostThreadMessage(GetCurrentThreadId(), WM_QUIT, 0, 0); PostQuitMessage(0);//等价于上面的一行调用 int a = 100; } if (msg.message == WM_AAA) { MessageBoxA(NULL, "消息循环:WM_AAA","测试", MB_OK); } TranslateMessage(&msg);//翻译消息 DispatchMessage(&msg);//分发消息到窗口过程 } }
二、windows各种消息
- 标准消息:所有以WM开头的消息,WM_COMMAND除外。为了避免系统消息与用户定义的消息冲突,微软定义了一个宏WM_USER,小于WM_USER的ID被系统使用,大于的被用户使用。
- 命令消息:来自菜单、工具栏按钮或者加速键的消息,以WM_COMMAND呈现。
- 通告消息:由控件产生的消息。
三、响应窗口创建和删除
代码实例
#include<windows.h> #include<stdio.h> //自定义的窗口过程 LRESULT CALLBACK MyWindowProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam) { switch (Msg) { ///////////////////////////创建窗口/////////////////////////////// case WM_NCCREATE: SetWindowTextA(hWnd, "改变标题"); char str[64]; sprintf(str, "WM_NCCREATE消息:%p!\n", hWnd); OutputDebugStringA(str); return true;//这里必须返回true,否则不会发WM_CREATE消息,CreateWindow返回NULL case WM_CREATE: { CREATESTRUCT *p = (CREATESTRUCT*)lParam; sprintf(str, "WM_CREATE消息:%p!\n", hWnd); OutputDebugStringA(str); return true; } ///////////////////////////销毁窗口/////////////////////////////// case WM_CLOSE: sprintf(str, "WM_CLOSE消息:%p!\n", hWnd); OutputDebugStringA(str); DestroyWindow(hWnd);//销毁窗口,发出WM_DESTROY消息 return 0; case WM_DESTROY: sprintf(str, "WM_DESTROY消息:%p!\n", hWnd); OutputDebugStringA(str); PostQuitMessage(0);//可以使GetMessage返回0 return 0; case WM_NCDESTROY: sprintf(str, "WM_NCDESTROY消息:%p!\n", hWnd); OutputDebugStringA(str); return 0; } return DefWindowProc(hWnd, Msg, wParam, lParam); } int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd) { //1.注册窗口类 WNDCLASS wnd; wnd.cbClsExtra = 0; wnd.cbWndExtra = 0; wnd.hbrBackground = (HBRUSH)(GetStockObject(GRAY_BRUSH));//背景色 wnd.hCursor = LoadCursor(NULL, IDC_ARROW);//光标 wnd.hIcon = LoadIcon(NULL, IDI_APPLICATION);//图标 //wnd.lpfnWndProc = DefWindowProc;//默认窗口过程函数,用于处理消息 wnd.lpfnWndProc = MyWindowProc;//自定义的窗口过程函数 wnd.lpszClassName = L"MrHuang";//窗口类名 wnd.lpszMenuName = NULL;//菜单资源名称 wnd.style = CS_HREDRAW | CS_DBLCLKS;//窗口类、样式 wnd.hInstance = hInstance;//实例句柄 RegisterClass(&wnd); //创建窗口(返回之前发送WM_CREATE) HWND hWnd = CreateWindow(L"MrHuang", L"第一个窗口程序", WS_OVERLAPPEDWINDOW, 100, 100, 300, 300, NULL, NULL, hInstance, NULL); char str[64]; sprintf(str, "CreateWindow返回:%p!\n", hWnd); OutputDebugStringA(str); //显示窗口 ShowWindow(hWnd, nShowCmd); //更新窗口(发送WM_PAINT) UpdateWindow(hWnd); //消息循环(收到WM_QUIT消息退出) MSG msg; while (GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg);//翻译消息 DispatchMessage(&msg);//分发消息到窗口过程 } }
四、WM_PAINT消息
1)以下操作会触发WM_PAINT消息
注:
代码实例:
#include<windows.h> #include<stdio.h> //自定义的窗口过程 LRESULT CALLBACK MyWindowProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam) { switch (Msg) { case WM_DESTROY: PostQuitMessage(0);//可以使GetMessage返回0 return 0; case WM_ERASEBKGND: { static int j = 0; char str[64]; sprintf(str, "第%d次产生WM_ERASEBKGND!\n", ++j); OutputDebugStringA(str);//在输出窗口打印信息 return 1; } case WM_PAINT: { PAINTSTRUCT ps; HDC hdc = BeginPaint(hWnd, &ps);//使无效区域变得有效 static int i = 0; char str[64]; sprintf(str, "第%d次产生WM_PAINT!\n", ++i); OutputDebugStringA(str);//在输出窗口打印信息 EndPaint(hWnd, &ps); return 0; } case WM_LBUTTONDOWN: //InvalidateRect(hWnd, NULL, true);//添加更新区域 //UpdateWindow(hWnd);//更新区域不为空,则马上发出WM_PAINT消息 //不管窗口的任何部分是否无效,都会导致WM_PAINT消息被发布到窗口。 RedrawWindow(hWnd, NULL, NULL, RDW_INTERNALPAINT); break; case WM_NCPAINT://自定义绘制非客户区 HDC hdc = GetWindowDC(hWnd); RECT r; r.left = 0; r.top = 0; r.right = 300; r.bottom = 30; HBRUSH brh = CreateSolidBrush(RGB(255, 0, 0)); FillRect(hdc, &r, brh); SetBkMode(hdc, TRANSPARENT); TextOutA(hdc, 5, 5, "自定义窗口标题", 14);//最后一个参数为字符串长度 DeleteObject(brh); ReleaseDC(hWnd, hdc); return true; //break; } return DefWindowProc(hWnd, Msg, wParam, lParam); } int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd) { //1.注册窗口类 WNDCLASS wnd; wnd.cbClsExtra = 0; wnd.cbWndExtra = 0; wnd.hbrBackground = (HBRUSH)(GetStockObject(GRAY_BRUSH));//背景色 wnd.hCursor = LoadCursor(NULL, IDC_ARROW);//光标 wnd.hIcon = LoadIcon(NULL, IDI_APPLICATION);//图标 //wnd.lpfnWndProc = DefWindowProc;//默认窗口过程函数,用于处理消息 wnd.lpfnWndProc = MyWindowProc;//自定义的窗口过程函数 wnd.lpszClassName = L"MrHuang";//窗口类名 wnd.lpszMenuName = NULL;//菜单资源名称 wnd.style = CS_HREDRAW | CS_DBLCLKS;//窗口类、样式 wnd.hInstance = hInstance;//实例句柄 RegisterClass(&wnd); //创建窗口(返回之前发送WM_CREATE) HWND hWnd = CreateWindow(L"MrHuang", L"第一个窗口程序", WS_OVERLAPPEDWINDOW, 100, 100, 300, 300, NULL, NULL, hInstance, NULL); //显示窗口 ShowWindow(hWnd, nShowCmd); //更新窗口(发送WM_PAINT) UpdateWindow(hWnd); //消息循环(收到WM_QUIT消息退出) MSG msg; while (GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg);//翻译消息 DispatchMessage(&msg);//分发消息到窗口过程 } }
五、WM_ERASEBKGND消息
代码实例:见上面WM_PAINT的代码实例。
六、更新窗口的函数
代码实例:见上面WM_PAINT的代码实例。
七、WM_NCPAINT消息
代码实例:见上面WM_PAINT的代码实例。
八、窗口鼠标键盘消息
代码实例:
#include<windows.h> #include<stdio.h> //自定义的窗口过程 LRESULT CALLBACK MyWindowProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam) { switch (Msg) { case WM_DESTROY: PostQuitMessage(0);//可以使GetMessage返回0 return 0; //鼠标消息 case WM_LBUTTONDOWN: char str[64]; sprintf(str, "鼠标左键按下: %d, %d\n", LOWORD(lParam), HIWORD(lParam)); OutputDebugStringA(str); break; case WM_LBUTTONUP: sprintf(str, "鼠标左键弹起: %d, %d\n", LOWORD(lParam), HIWORD(lParam)); OutputDebugStringA(str); break; case WM_MOUSEMOVE: sprintf(str, "鼠标移动: %d, %d\n", LOWORD(lParam), HIWORD(lParam)); OutputDebugStringA(str); break; case WM_LBUTTONDBLCLK: sprintf(str, "鼠标左键双击: %d, %d\n", LOWORD(lParam), HIWORD(lParam)); OutputDebugStringA(str); break; //键盘消息 case WM_KEYDOWN: sprintf(str, "键盘按下: %X, %c\n", wParam , wParam); OutputDebugStringA(str); break; case WM_CHAR: sprintf(str, "字符消息: %X, %c\n", wParam, wParam); OutputDebugStringA(str); break; case WM_KEYUP: sprintf(str, "键盘弹起: %X, %c\n", wParam, wParam); OutputDebugStringA(str); break; case WM_SYSKEYDOWN: //alt同时按下的键 sprintf(str, "系统按键按下: %X, %c\n", wParam, wParam); OutputDebugStringA(str); break; case WM_SYSCHAR: sprintf(str, "系统字符: %X, %c\n", wParam, wParam); OutputDebugStringA(str); break; case WM_SYSKEYUP: sprintf(str, "系统按键弹起: %X, %c\n", wParam, wParam); OutputDebugStringA(str); break; } return DefWindowProc(hWnd, Msg, wParam, lParam); } int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd) { //1.注册窗口类 WNDCLASS wnd; wnd.cbClsExtra = 0; wnd.cbWndExtra = 0; wnd.hbrBackground = (HBRUSH)(GetStockObject(GRAY_BRUSH));//背景色 wnd.hCursor = LoadCursor(NULL, IDC_ARROW);//光标 wnd.hIcon = LoadIcon(NULL, IDI_APPLICATION);//图标 //wnd.lpfnWndProc = DefWindowProc;//默认窗口过程函数,用于处理消息 wnd.lpfnWndProc = MyWindowProc;//自定义的窗口过程函数 wnd.lpszClassName = L"MrHuang";//窗口类名 wnd.lpszMenuName = NULL;//菜单资源名称 wnd.style = CS_HREDRAW | CS_DBLCLKS;//窗口类、样式,只有添加CS_DBLCLKS才能响应双击消息 wnd.hInstance = hInstance;//实例句柄 RegisterClass(&wnd); //创建窗口(返回之前发送WM_CREATE) HWND hWnd = CreateWindow(L"MrHuang", L"第一个窗口程序", WS_OVERLAPPEDWINDOW, 100, 100, 300, 300, NULL, NULL, hInstance, NULL); //显示窗口 ShowWindow(hWnd, nShowCmd); //更新窗口(发送WM_PAINT) UpdateWindow(hWnd);
//消息循环(收到WM_QUIT消息退出) MSG msg; while (GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg);//翻译消息 DispatchMessage(&msg);//分发消息到窗口过程 } }
注:wnd.style = CS_HREDRAW | CS_DBLCLKS;//窗口类、样式,只有添加CS_DBLCLKS才能响应双击消息