1.消息的产生与处理流程:
如上图,我们在创建窗口程序中详细介绍了这张图。比如,我们点击某个窗口的时候就会产生消息,操作系统会先判断这个消息是点在了哪个窗口,找到窗口后,会根据窗口对象中的一个成员找到窗口是属于哪个线程的。找到后就会把他封装好的消息放到一个结构体中,然后存到消息队列中,那么我们的GetMessage()就会不停地把消息队列中的消息取出。
在之前我们创建窗口程序的代码中有(我是截取的)
MSG msg;
GetMessage(&msg, NULL, 0, 0)
我们知道取出的消息放到了msg中.我们转到定义看看MSG
注意:能产生消息的四种情况:1.鼠标 2.键盘 3.其他应用程序 4.操作系统的内核程序
那么这么多消息操作系统怎么处理呢?操作系统会把他们分成不同类别,每种不同的消息给他们一个唯一的编号。下面介绍参数
UINT message
这个参数是UINT型,它给每个消息类型一个编号,比如我点一下鼠标就会有个唯一类型的编号。
HWND hwnd
句柄,消息是基于窗口的,任何消息都是某一个窗口的消息。
WPARAM wParam;
LPARAM lParam;
这两个成员是描述你的消息是什么样的
DWORD time
消息什么时候产生的
POINT pt
你的消息什么位置产生的
那么我们取出消息放到msg中为什么不直接处理呢?其实之前的学习中我们也提过了。现在我们再看一下MSG,通过我们只能知道,是哪个窗口什么类型的。我们得到的仅仅是一个索引,我们不知道窗口回调也就是窗口处理函数是什么,所以把得到的message传给DispatchMessage()它拿着消息和HWND,进入内核,内核会根据句柄找到窗口对象找到窗口处理函数,再由内核发起调用执行窗口过程(处理)函数。
经过上面的介绍我们现在知道消息处理函数中的四个参数是从哪里来的了。
这是窗口过程的四个参数
_In_ HWND hwnd,
_In_ UINT uMsg,
_In_ WPARAM wParam,
_In_ LPARAM lParam
我们通过GetMessage得到消息,这四个参数全在MSG中,然后把MSG(消息)通过DispatchMessage()传到内核,内核在调用窗口过程的时候又会把这四个参数传回来(详细可看最上面的那张图).所以窗口过程函数中的四个参数就是MSG中的四个成员。
那么我们尝试输出消息类型(就是MSG中的第二个参数)那么我们输出WindowProc中的uMSG即可。示例代码如下
#include "framework.h"
#include "WindowsProject1.h"
LRESULT CALLBACK WindowProc(
_In_ HWND hwnd,
_In_ UINT uMsg,
_In_ WPARAM wParam,
_In_ LPARAM lParam
)
{
char szOutBuff[0x80];
sprintf(szOutBuff, "消息类型: %x \n", uMsg);
OutputDebugStringA(szOutBuff);
return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
int APIENTRY wWinMain(_In_ HINSTANCE hInstance,
_In_opt_ HINSTANCE hPrevInstance,
_In_ LPWSTR lpCmdLine,
_In_ int nCmdShow)
{
char szOutBuff[0x80];
//1.第一步:定义你的窗口是什么样的
TCHAR className[] = TEXT("My First Window");
WNDCLASS wndclass = { 0 };
wndclass.hbrBackground = (HBRUSH)COLOR_BACKGROUND;
wndclass.lpszClassName = className;
wndclass.hInstance = hInstance;
wndclass.lpfnWndProc = WindowProc;//不是调用函数,只是告诉函数名操作系统会来调用
RegisterClass(&wndclass);
//第二部:创建并显示窗口
HWND hwnd = CreateWindow(
className,
TEXT("我的第一个窗口"),
WS_OVERLAPPEDWINDOW,
10,
10,
600,
300,
NULL,
NULL,