2.Windows窗口和消息

来源:互联网 发布:java 延时队列 编辑:程序博客网 时间:2024/05/02 02:12

1.Windows内部运行机制

设计窗口类 -> 注册窗口类 -> 创建窗口 -> 显示更新窗口 -> 消息循环 -> 处理消息

                      注册公司  -> 创建公司 –> 公司开张   -> 接收业务往来 -> 办理业务

 

2.Windows窗口消息(windows程序设计3.2.2)

1.进队消息

       进队的消息是由Windows放入程序消息队列中的,在程序消息循环过程中,重新返回并分配给窗口过程。

不进队消息在Windows调用窗口时直接发送给窗口过程。

       也就是说,不进队消息发送给消息队列,不进队消息直接发送给窗口过程。多数情况下,进队消息来自于 用户的输入结果,如:一般由用户操作产生的消息,如:鼠标单击、键盘单击、窗口重画消息等;       进队消息还包括时钟消息,刷新消息和退出消息。

2.不进队消息

       多数情况下,不进队消息来自调用特定的Windows函数。例如CreateWindowEx函数内部会发送WM_CREATE消息,GetWindowText函数会发送WM_GETTEXT消息获取标题内容。当调用ShowWindow时,将产生WM_SIZE和WM_SHOWWINDOW消息、当调用UpdateWindow时创建的WM_PAINT消息(注意,并不是某个类型是进队消息就永远是进队消息,如WM_PAINT有进队的,也有不进队的)、还有其他进队消息也有可能在不进队消息中出现,整个处理过程是复杂的,但由于Windows已经解决大部分的问题,因此我们可以认为我们获得的消息是有序的、同步的。


3.Windows消息循环示意图

 


4.SendMessage()和PostMessage()

 先来看看Send与Post这两个英文单词的意思:Send有发送的意思,而Post具有投寄的意思。
      联想一下现实生活中我们写信(很久很久以前。。。。)来记就很简单了:
      Send: 相当于邮寄员,他会将快件亲手交给收件人,并且需要收件人签字,他才闪人。而在消息机制中,就是说,系统(邮寄员)会将收到的消息(邮局分发)直接发送到某个窗口的窗口过程(收件人),并且需要该窗口作出处理(收件人签字)才返回。 这东东就是SendMessage
      Post: 相当于邮局、邮筒等等,我们写好信好,会将信交给邮局,或投寄到邮筒里,而什么时候发送,发送到哪里都由邮局来处理,我们投寄信件的时候,是不会等候这封信件到达收件人手里,然后才回家的。 而在消息机制中,就是说,系统(我们)将收到的消息(信件)投寄到应用程序的消息循环(相当于邮筒)中,然后就闪人,具体啥时候处理这条消息(啥时候发送邮件),那就得看“办事效率”了。
           区别很明显,SendMessage的消息是不进队列的,而PostMessage进队。 
           但,值得说明的是:虽然一个要进队,一个不进队,但是最终处理消息的地方都一样:都是系统调用窗口过程进行处理(收件人作出反应)

与此类似的还有一队函数,GetMessage()和PeekMessage()这里顺便再总结一下

 

5.GetMessage()和PeekMessage()的区别

相同点:

两函数都用于检查线程消息队列,有消息时取得消息并放入指定的结构。

返回值:

GetMessage()   TRUE:有消息且消息不为WM_QUIT

                       FALSE:有消息且该消息为WM_QUIT

 

PeekMessage()  TURE:有消息        FALSE:没有消息

不同点:

     从上面可以看出,GetMessage()无论返回何值队列中都有消息,也就是说在队列有消息时,函数返回,如果队列中没有消息,刚函数会一直等待,真到有消息出现才返回。(在函数等待时间内,应用程序不能执行任何指令。

Peek的意思为“看一眼,一瞥”。同时从上面的返回值可以看出,无论消息队列中是否有消息,PeekMessage()都立即返回,程序得以继续执行后面的语句(无消息则执行其它指令,有消息时一般要将消息派发出去,再执行其它指令)。

 

6.PreTraslateMessage()

Send和Post是否可以预处理?答案是否定的:

比如你要从A寄信到B,那么有两种方法:1、自己带着信跑到B,2、将信放到邮局,由邮局分发。
     第1 种情况下,就是SendMessage了,这个时候,还有谁能预处理你的信呢?
    第2种情况下,就是PostMessage了,这个时候,嘿嘿,万一运气不好,被邮局给用PreTranslateMessage给截了.....
    所以说,用SendMessage发送的消息是不能用PreTranslateMessage来预处理的。而Post的就可以,因为它要经过“第三者”嘛。


应用实例:

#include"tchar.h"#include<windows.h>LRESULT CALLBACK WindowProc( HWND hwnd,      // handle to window UINT uMsg,      // message identifier                                                WPARAM wParam,  // first message parameter                                                  LPARAM lParam   // second message parameter ){switch(uMsg){case WM_CLOSE:{::DestroyWindow(hwnd);}break;case WM_DESTROY:{::PostQuitMessage(0);}break;}return DefWindowProc(hwnd,uMsg,wParam,lParam);}int WINAPI WinMain(HINSTANCE hInstance,      // handle to current instance   HINSTANCE hPrevInstance,  // handle to previous instance   LPSTR lpCmdLine,          // command line   int nCmdShow)            //_tWinMain兼容不同字符集{const TCHAR* pszClassName=_T("lsfreeing");WNDCLASSEX wcex;wcex.cbSize=sizeof(WNDCLASSEX);wcex.cbClsExtra=0;wcex.cbWndExtra=0;wcex.hbrBackground=(HBRUSH)::GetStockObject(BLACK_BRUSH);wcex.hCursor=(HCURSOR)::LoadCursor(NULL,IDI_QUESTION);wcex.hIcon=(HICON)::LoadIcon(NULL,IDI_APPLICATION);wcex.hIconSm=NULL;wcex.hInstance=hInstance;wcex.lpfnWndProc=WindowProc;wcex.lpszClassName=pszClassName;wcex.lpszMenuName=NULL;wcex.style=CS_HREDRAW | CS_VREDRAW;BOOL flag=::RegisterClassEx(&wcex);if(flag==FALSE){MessageBox(NULL,_T("注册失败"),_T("lsfreeing"),MB_YESNOCANCEL);return FALSE;}HWND hwnd=::CreateWindowEx(0,pszClassName,_T("ls"),WS_VISIBLE|WS_OVERLAPPEDWINDOW,CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,NULL,NULL,hInstance,NULL);//创建窗口if(hwnd==NULL){MessageBox(NULL,_T("创建失败"),_T("ls"),MB_YESNOCANCEL);return FALSE;}::ShowWindow (hwnd,SW_SHOW);     //显示::UpdateWindow(hwnd); //更新MSG msg;while(GetMessage(&msg,NULL,NULL,NULL))  //第二个参数为NULL 因为消息循环接收所有窗口的消息{//消息循环::TranslateMessage(&msg);::DispatchMessage(&msg);}return TRUE;}


      

0 0
原创粉丝点击