一、消息分类
Windows消息类型可以分为:1.系统定义消息 2.用户自定义消息
消息的总个数为UINT mMessage,范围为0x0000 - 0xFFFF(0 - 65535)
- 系统定义消息:范围:从0x0000 - 0x03FF(0x03FF相当于WM_USER-1范围),应用程序不能用这些值作为自己的自定义消息
- 用户自定义消息:范围从0x0400(数值WM_USER)到0x7FFF的值是为用户保留的,应用程序能用这些值作为自己的自定义消息。
- 队列消息:基本是用户输入的结果,如按键(WM_KEYDOWN、WM_KEYUP消息)、按键产生的字符(WM_CHAR)、鼠标移动(WM_MOUSEMOVE)和鼠标按钮(WM_LBUTTONDOWN)的形式给出,另外还包括定时器消息(WM_TIMER)、绘图消息(WM_PAINT)和退出消息(WM_QUIT)
- 非队列消息:一般有 Windows 特定函数调用产生。
调用 CreateWindow 时,Windows 将建立窗口并在处理中给窗口消息处理程序发送一个WM_CREATE 消息。
调用ShowWindow 时,Windows将给窗口消息处理程序发送WM_SIZE和WM_SHOWWINDOW消息。
调用 UpdateWindow 时,Windows 将给窗口消息处理程序发送 WM_PAINT 消息。
任何情况下,窗口消息处理程序都将获得窗口所有的消息–包括队列和非队列化的消息
二、系统常用消息
1.WM_CREATE消息
通过调用CreateWindow函数或CreateWindowEx函数时发送
注意:WM_CREATE是不进队列消息。也就是说不是从消息队列中取出
原因:CreateWindow直接调用WndProc
case WM_CREATE:
{
CREATESTRUCT* lpcs = (CREATESTRUCT*)lParam;
SetWindowText(hWnd, L"这是窗口创建消息");
break;
}
窗口创建消息 ,由CreateWindow或者CreateWindowEx 发出这个消息 ,发出的时间非常早,在窗口还没创建好就已经发出来了
传过来的都是CreateWindow的函数的参数 除了最后一个拓展风格是CreateWindowEx的参数
2.WM_ClOSE消息
窗口关闭消息(注意:此时的窗口并没有被真正销毁,还可以还原)
case WM_CLOSE:
{
int result = MessageBox(hWnd, L"您确定要关闭吗?", L"提示", MB_YESNO);
if (IDYES == result)
break; //表示退出switch去响应最后的默认窗口处理函数 此时就会发出 WM_DESTROY
else if (IDNO == result)
{
//ShowWindow(hWnd, SW_MAXIMIZE);
return 1;//返回真,表示我自己已经处理了,系统不要在处理了
//return 0; //返回假, 表示我自己没有处理, 系统也不会处理
}
break;
}
3.WM_DESTROY消息
窗口销毁消息,主要实现一些清理工作,窗口要退出去的时候, 窗口子控件已经被销毁
case WM_DESTROY:
PostQuitMessage(0); //与之前讲过的消息循环的0对应 消息循环返回值是0时退出
break;
WM_CREATE发出的最早 WM_CLOSE在点击关闭时执行,此时可以阻止进程退出 WM_DESTROY释放内存或清理此时就无力回天
4.WM_LBUTTONDOWN消息
鼠标左键按下消息
case WM_LBUTTONDOWN:
{
//LPARAM 四个字节 双字 long型
int x = LOWORD(lParam);
int y = HIWORD(lParam);
TCHAR szInfo[256];
wsprintf(szInfo, L"坐标:(%d,%d)", x, y);
if (wParam & MK_CONTROL)
wcscat(szInfo, L"按下了Ctrl键");
if (wParam & MK_LBUTTON)
wcscat(szInfo, L"按下了左键");
if (wParam & MK_MBUTTON)
wcscat(szInfo, L"按下了鼠标中间键;");
if (wParam & MK_RBUTTON)
wcscat(szInfo, L"按下了鼠标右键;");
if (wParam & MK_SHIFT)
wcscat(szInfo, L"按下了Shift键;");
//设置窗口标题
SetWindowText(hWnd, szInfo);
break;
}
WPARAM:表示按键的状态值
LPARAM:表示鼠标点击的坐标
5.WM_RBUTTONDOWN消息
鼠标右键按下消息,类似鼠标左键按下消息
6.WM_RBUTTONUP消息
鼠标右键抬起消息
7.WM_MOUSEMOVE消息
鼠标移动消息
case WM_MOUSEMOVE:
{
//LPARAM 四个字节 双字
//
int x = LOWORD(lParam);
int y = HIWORD(lParam);
TCHAR szInfo[256];
wsprintf(szInfo, L"鼠标移动坐标:(%d, %d)", x, y);
SetWindowText(hWnd, szInfo);
break;
}
8.WM_KEYDOWN消息
键盘按下消息
WPARAM:表示虚拟键键值
LPARAM:表示具体按键具体包含的32位
case WM_KEYDOWN://键盘按下
switch (wParam)
{
case VK_SPACE://空格
MessageBox(hWnd, L"按下空格键", L"提示", MB_OK);
break;
case VK_SHIFT://Shitf
MessageBox(hWnd, L"按下Shift键", L"提示", MB_OK);
break;
case VK_RETURN://回车
MessageBox(hWnd, L"按下回车键", L"提示", MB_OK);
break;
case VK_ESCAPE://ESC
MessageBox(hWnd, L"按下ESC键", L"提示", MB_OK);
break;
case VK_TAB://Tab
MessageBox(hWnd, L"按下Tab键", L"提示", MB_OK);
break;
case VK_F1://F1
MessageBox(hWnd, L"按下F1键", L"提示", MB_OK);
break;
case VK_LEFT://左
break;
case VK_RIGHT://右
break;
case VK_UP://上
break;
case VK_DOWN://下
break;
case 0x30://0
SetWindowText(hWnd, L"正上方的0");
break;
case VK_NUMPAD0://0
SetWindowText(hWnd, L"右边的0");
break;
case 0x41://A
SetWindowText(hWnd, L"按了A");
break;
}
break;
9.WM_KEYUP消息
键盘抬起消息
10.WM_CHAR消息
字符消息
WPARAM:表示字符值
LPARAM:表示具体按键具体包含的32位
产生:由一次按下消息WM_KEYDOWN和抬起消息 WM_KEYUP组合
case WM_CHAR:
{
TCHAR ch = (TCHAR)wParam;
TCHAR szInfo[256];
wsprintf(szInfo, L"字符:%c", ch);
SetWindowText(hWnd, szInfo);
break;
}
11.WM_PAINT消息
客户区绘图消息
case WM_PAINT:
{
PAINTSTRUCT ps;
HDC hDC = BeginPaint(hWnd, &ps);
//绘图
Rectangle(hDC, 0, 0, 100, 100);
//圆
//Ellipse(hDC, 10, 10, 200, 100);
EndPaint(hWnd, &ps);
break;
}
12.WM_TIMER消息
定时器消息,一般在CreateWindow时开启定时器:SetTimer(hWnd, TIME_ID, 1000, NULL) 关闭则KillTimer(hWnd, TIME_ID);
case WM_TIMER:
{
int nTimerID = wParam;
switch (nTimerID)
{
case TIME_ID:
//获取当前时间
//返回当前时间的时间戳 1970 ,1-1 0,0,0 到现在的秒数
//第一种用法
time_t tt = time(NULL);
//第二种用法
//time_t tt;
//time(&tt);
tm* t = localtime(&tt);
TCHAR szInfo[256];
wsprintf(szInfo, L"北京时间:%d-%02d-%02d %02d:%02d:%02d", t->tm_year+1900, t->tm_mon+1, t->tm_mday, t->tm_hour, t->tm_min, t->tm_sec);
SetWindowText(hWnd, szInfo);
break;
}
}
break;
}
三、发送常用消息
SendMessage 和 PostMessage
区别:
1、SendMessage 是阻塞函数、PostMessage 非阻塞函数;
2、返回值区别:
SendMessage返回一个消息的处理结果
PostMessage返回的是一个发送成功或失败,不管那边有没有处理完
3、跨进程,最好是用PostMessage
四、用户自定义消息
#define WM_TEST WM_USER+1
case UM_TEST:
{
int x = wParam;
int y = lParam;
int result = x + y;
TCHAR szInfo[256];
wsprintf(szInfo, L"这是我的自定义消息,result=%d", result);
SetWindowText(hWnd, szInfo);
break;
}
用户自定义消息可以放在键盘消息中,如按下Enter则发出测试消息
case VK_RETURN://回车
{
SendMessage(hWnd, UM_TEST, 10, 96);
break;
}
五、出现的一些新的类型
UINT | unsigned int |
LONG | long |
WCHAR | wchar_t |
WNDPROC | typedef LRESULT (CALLBACK* WNDPROC)(HWND, UINT, WPARAM, LPARAM); 函数指针类型 |
WPARAM | UINT_PTR -> UINT -> unsigned int |
LPARAM | LONG_PTR -> LONG -> long |
HICON | 结构体指针 |
HCURSOR | 结构体指针 |
HBRUSH | 结构体指针 |
LPCTSTR | LPCWSTR -> CONST WCHAR * -> const wchar_t* |
ATOM | WORD(字) -> unsigned short |
DWORD | 双字 double word -> unsigned long |
MAKEINTRESOURCE | #define MAKEINTRESOURCEW(i) ((LPWSTR)((ULONG_PTR)((WORD)(i)))) |