【SunXin.VC++深入】
1.窗口(Windows)和句柄(HANDLE,handle):窗口句柄(HWND)图标句柄(HICON)、光标句柄(HCURSOR)和画刷句柄(HBRUSH)
2.消息,消息队列,消息循环,消息响应
.OS将操作包装成Message
.typedef struct MSG {
HWND hwnd; //窗口句柄,即标示消息所属的窗口
UINT message;//标示消息的类别,是鼠标还是键盘等 如鼠标左键按下消息是WM_LBUTTONDOWN,键盘按下消息是WM_KEYDOWN,字符消息是WM_CHAR
WPARAM wParam;//消息的附加信息
LPARAM lParam;//消息的附加信息
DWORD time;//消息投递到消息队列中的时间
POINT pt;//鼠标的当前位置
} MSG;
.消息队列,每一个Windows应用程序开始执行后,系统都会为该程序创建一个消息队列,这个消息队列用来存放该程序创建的窗口的消息
.进队消息(OS将产生的消息放在应用程序的消息队列中,让应用程序来处理)
不进队消息(OS直接调用窗口的处理过程)
.Windows应用程序的消息处理机制
while(GetMessage(&msg,NULL,0,0)){//接收到WM_QUIT消息时,才返回0
TranslateMessage(&msg);//对消息进行包装处理然后再以消息的形式投放到消息队列
DispatchMessage(&msg);//消息回传给操作系统,由操作系统调用窗口过程函数对消息进行处理
}
(1)操作系统接收到应用程序的窗口消息,将消息投递到该应用程序的消息队列中。
(2)应用程序在消息循环中调用GetMessage函数从消息队列中取出一条条的消息。取出后,以对消息进行一些预处理,如放弃对某些消息的响应,或者调用TranslateMessage产生新的消息
(3)应用程序调用DispatchMessage,将消息回传给操作系统。消息是由MSG结构体对象来表示的,其中就包含了接收消息的窗口的句柄。因此,DispatchMessage函数总能进行正确的传递。(4)系统利用WNDCLASS结构体的lpfnWndProc成员保存的窗口过程函数的指针调用窗口过程,对消息进行处理(即“系统给应用程序发送了消息”)。
.窗口过程函数
lresult callback windowproc(
hwnd hwnd, // 对应消息的窗口句柄
uint umsg, // 消息代码,区别消息的类型
wparam wparam, // 消息代码的附加参数1
lparam lparam // 消息代码的附加参数2
);
【蔡学镛.揭开消息循环的神秘面纱】
简单归纳如下:
讯息循环被封装进了 Application 类别的 Run() 静态方法中;Windows Procedure 被封装进了 NativeWindow 与 Control 类别中;
个别的讯息处理动作被封装进 Control 类别的 OnXyz()(例如 OnPaint())。我们可以覆盖(override)OnXyz(),来提供我们自己的程序。
也可以利用.NET的事件(event)机制,在 Xyz 事件上,加入我们的事件处理函式(Event Handler)。Control 类别的 OnXyz() 会主动呼叫 Xyz 事件的处理函式。
请注意,因为 Xyz 的事件处理函式是由 Control 类别的 OnXyz() 方法所呼叫的,所以当你覆写 OnXyz() 方法时,
不要忘了呼叫 Control 类别的 OnXyz()(除非你有特殊需求),否则 Xyz 事件处理函式将会没有作用。
只要呼叫 base.OnXyz(),就可以呼叫到 Control 类别的 OnXyz() 方法
1. 在 Main() 中,利用 Application.Run() 来将 Form1 窗口显示出来,并进入讯息循环。程序的执行过程中,Application.Run() 一直未结束。
2. OS 在此 Process 的讯息队列内放进一个 WM_PAINT 讯息,好让窗口被显示出来。
3. WM_PAINT 被 Application.Run() 内的讯息循环取出来,发派到 WndProc()。由于多型(Polymorphism)的因素,此次调用(invoke)到的 WndProc() 是属于 Form1 的 WndProc(),也就是上述程序中批注(comment)1 的地方,而不是调用到 Control.WndProc()。
4. 在 Form1.WndProc() 的最后,有调用 base.WndProc(),这实际上调用到 Control.WndProc()。
5. Control.WndProc() 从 Message 参数中得知此讯息是 WM_PAINT,于是调用 OnPaint()。由于多型的因素,此次调用到的 OnPaint() 是属于 Form1 的 OnPaint(),也就是上述程序中批注 2 的地方,而不是调用到 Control.OnPaint()。
6. 在 Form1.OnPaint() 的最后,有调用 base.OnPaint(),这实际上调用到 Control.OnPaint()。
7. 我们曾经在 Form1 的建构式(constructor)中将 Form1_Paint() 与 Form1_Paint2() 登记成为 Paint 事件处理函式(Event Handler)。Control.OnPaint() 会去依序去呼叫这两个函式,也就是上述程序中批注 3 与 4 的地方。
【.NET Windows Message】
1.Control--Button,Form……
protect vitrual WndProcess(ref Message);
调用private Wm_(ref Message);//具体某类消息
调用Oprotect virtual On_xx(EventArg e);//触发相关事件
2.解释事件冒泡:比如键盘消息可先由Form来处理,然后交由相关的Control来处理
3.解释FormPaint:窗口的移动,最小化,最大话都会引起窗口内容的重新Paint,OS产生一个相关消息发给应用程序的消息队列,应用程序得到并处理消息时先是Form依次经过Wn_Process,Wn_..,On_Paint,Form_Paint,之后Form中的每一个Control也会依次做重绘的工作