一、消息的相关函数:
1 GetMessage - 从系统中获取消息,将消息从系统中移除,它是一个阻塞函数。当系统无消息时,GetMessage会等候下一条消息。
2 PeekMessage - 以查看的方式从系统获取消息,可以不将消息从系统中移除,是一个非阻塞函数,当系统无消息时,返回false,继续执行后续代码。
3 SendMessage - 发送消息,会直接把消息发送给窗口处理函数,而不经过消息队列和消息循环,会等候消息处理结果。
4 PostMessage - 投递消息,把消息投递到消息队列中,由消息循环完成消息的处理,消息发出后立刻返回,不等候消息执行结果。
二、消息队列类型:
1 系统消息队列 - 由系统维护的消息队列,存放系统产生的消息,例如键盘、鼠标等。
2 程序消息队列 - 属于每一个应用程序(线程)的消息队列,由应用程序(线程)维护。
三、从消息队列中获取消息的次序:
1 在程序(线程)消息队列中查找消息,如果队列有消息,检查消息是否满足指定条件,不满足条件就不会取出消息,否则从程序消息队列中取出消息返回。
2 如果程序(线程)消息队列中没有消息,向系统消息队列中获取属于本程序的消息,如果系统队列的当前消息属于本程序,系统会将消息转发到程序消息队列中,并取得返回。
扫描二维码关注公众号,回复: 1898909 查看本文章3 如果系统消息队列也没有消息,检查当前窗口需要重新绘制的区域,如果发现有需要绘制的区域,产生WM_PAINT消息,取得消息返回处理。
4 如果没有重新绘制区域,检查定时器如果有到时的定时器,产生WM_TIMER,返回处理执行。
5 如果没有到时间的定时器,整理程序的资源、内存等。GetMessage()函数会继续等候下一条消息,而PeekMessage()函数会返回FALSE,交出程序的使用权。
四、绘图消息WM_PAINT:
1 程序收到WM_PAINT消息,不使用这个消息的两个附加参数WPARAM和LPARAM。
2 绘图的步骤:
a、开始绘图处理
HDC BeginPaint(
HWND hwnd, // 绘图窗口
LPPAINTSTRUCT lpPaint // 绘图参数的BUFF
);返回绘图设备句柄HDC
b、绘图
c、结束绘图处理
BOOL EndPaint(
HWND hWnd, // 绘图窗口
CONST PAINTSTRUCT *lpPaint // 绘图参数的指针BeginPaint返回
);
五、键盘消息:
WM_KEYDOWN - 按键被按下时产生
WM_KEYUP - 按键被放开时产生
WM_CHAR - 字符消息(不是按键直接产生,是由TranslateMessage函数翻译按键消息产生)
按键消息(键盘按键被按下或弹起时,所带的附加参数说明):
WPARAM - 按键的Virtual Key
LPARAM - 按键的参数,例如按下次数
WM_CHAR消息(按下某键通过TranslateMessage函数翻译之后生成的WM_CHAR消息的附加参数说明):
WPARAM - 输入的字符
LPARAM - 按键的相关参数
附加以上总结的代码案例:
/*
功能:
1 点击关闭按钮,弹框提示
2 在WIN32程序中调用控制台的使用(AllocConsole)
3 自定义消息的使用
4 绘图消息WM_PAINT的使用
5 键盘消息的使用WM_KEYDOWN、WM_KEYUP、WM_CHAR
6 通过使用键盘上下左右按键移动自绘制的图形
*/
#include <Windows.h>
#include <stdio.h>
#include <tchar.h>
HINSTANCE g_hInstance;
HANDLE hOutHandle;
int n_xPos = 100,n_yPos =100;
//自定义消息
#define WM_MYMESSAGE WM_USER + 1
void OnPaint(HWND hWnd)
{
PAINTSTRUCT ps;
HDC hDC = BeginPaint(hWnd,&ps);
//TextOut(hDC,100,100,__TEXT("miao miao"),lstrlen(__TEXT("miao miao")));
TextOut(hDC,n_xPos,n_yPos,__TEXT("miao miao"),lstrlen(__TEXT("miao miao")));
EndPaint(hWnd,&ps);
}
void OnKeyDown(HWND hWnd,WPARAM wParam)
{
if (VK_UP == wParam)
{
n_yPos-= 4;
InvalidateRect(hWnd,NULL,TRUE);
}
if (VK_DOWN == wParam)
{
n_yPos+= 4;
InvalidateRect(hWnd,NULL,TRUE);
}
if (VK_LEFT == wParam)
{
n_xPos-= 4;
InvalidateRect(hWnd,NULL,TRUE);
}
if (VK_RIGHT == wParam)
{
n_xPos+= 4;
InvalidateRect(hWnd,NULL,TRUE);
}
}
void OnKeyUp()
{
//为验证WM_KEYUP和WM_CHAR消息,打开一个控制台,当收到消息时在控制台中显示相应内容
TCHAR szText[256] = {0};
lstrcpy(szText,__TEXT("WM_KEYUP\n"));
WriteConsole(hOutHandle,szText,lstrlen(szText),NULL,NULL);
}
void OnKeyChar(WPARAM wParam)
{
TCHAR szText[256] = {0};
_stprintf_s(szText,256,__TEXT("char:%08X\n"),wParam);
WriteConsole(hOutHandle,szText,lstrlen(szText),NULL,NULL);
}
LRESULT CALLBACK MyProc(HWND hWnd,UINT nMsg,WPARAM wParam,LPARAM lParam)
{
switch(nMsg)
{
//键盘消息验证
case WM_KEYDOWN:
OnKeyDown(hWnd,wParam);
break;
case WM_KEYUP:
OnKeyUp();
break;
case WM_CHAR:
OnKeyChar(wParam);
break;
//绘图消息验证
case WM_PAINT:
OnPaint(hWnd);
break;
//通过WM_CREATE发送自定义消息来验证自定义消息
case WM_MYMESSAGE:
MessageBox(hWnd,__TEXT("WM_MYMESSAGE is called"),__TEXT("提示"),MB_OK);
break;
case WM_CREATE:
SendMessage(hWnd,WM_MYMESSAGE,NULL,NULL);
break;
case WM_SYSCOMMAND:
if (wParam == SC_CLOSE)
{
if(IDYES == MessageBox(hWnd,__TEXT("确定要关闭窗口"),__TEXT("提示"),MB_YESNO))
PostQuitMessage(0);
else
return 0;
}
break;
}
return DefWindowProc(hWnd,nMsg,wParam,lParam);
}
ATOM Register(LPCWSTR className)
{
WNDCLASSEX wc = {0};
wc.cbClsExtra = 0;
wc.cbSize = sizeof(WNDCLASSEX);
wc.cbWndExtra = 0;
wc.hbrBackground = (HBRUSH)COLOR_WINDOW;
wc.hCursor = NULL;
wc.hIcon = NULL;
wc.hIconSm = NULL;
wc.hInstance = g_hInstance;
wc.lpfnWndProc = MyProc;
wc.lpszClassName = className;
wc.lpszMenuName = NULL;
wc.style = CS_VREDRAW | CS_HREDRAW;
return RegisterClassEx(&wc);
}
HWND Create(LPCWSTR className,LPCWSTR windowName)
{
return CreateWindowEx(0,className,windowName,WS_OVERLAPPEDWINDOW,100,100,600,600,NULL,NULL,g_hInstance,NULL);
}
void Show(HWND hWnd)
{
ShowWindow(hWnd,SW_SHOW);
UpdateWindow(hWnd);
}
void Message()
{
MSG ms = {0};
while (GetMessage(&ms,NULL,0,0))
{
TranslateMessage(&ms);
DispatchMessage(&ms);
}
}
int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nShowCmd)
{
//打开控制台
AllocConsole();
hOutHandle = GetStdHandle(STD_OUTPUT_HANDLE);
g_hInstance = hInstance;
Register(__TEXT("Main"));
HWND hWnd = Create(__TEXT("Main"),__TEXT("This is test"));
Show(hWnd);
Message();
return 0;
}