Windows程序设计(消息机制)

    句柄是Windows程序设计的基础,而消息机制又是Windows程序设计的核心。
    众所皆知,Windows是一个事件驱动,基于消息的操作系统。Windows强调的是事件触发,并且事件之间是无序的。在DOS下,代码的执行都是井然有序的,也就是说你在执行这个程序的时候不能执行另一个程序,单任务。而在强大的Windows下,能同时执行几个或者几十个程序。那么什么是触发事件?我们点一下鼠标、移动一下鼠标、按一下键盘按键,这些都会产生响应的事件,Windows在接收到这些事件之后就会把它们转化成对应的消息,然后放入系统的消息队列里。
    Windows为当前执行的每个Windows程序维护一个消息队列。在发生输入事件之后,Windows将事件转换为一个消息并将消息放入程序的消息队列中。程序通过执行一块称之为消息循环的程序代码从消息队列中取出消息,然后根据不同的消息做出相应的响应。
    

     依旧用之前的代码来分析:
 
/* -------------------------------------------------------------------
                        MyWindows.c --   
                Windows SDK                    
--------------------------------------------------------------------*/
#include  <windows.h>
LRESULT  CALLBACK  WndProc ( HWND ,  UINT ,  WPARAM ,  LPARAM ) ;        //
int  WINAPI  WinMain ( HINSTANCE  hInstance ,  HINSTANCE  hPrevInstance ,  PSTR  szCmdLine ,  int  iCmdShow )
{
     static  TCHAR  szAppName [ ]  =  TEXT ( "MyWindows" ) ;        //
     HWND  hwnd ;       //
     MSG  msg ;         //
     WNDCLASS  wndclass ;       //
     wndclass . style  =  CS_HREDRAW |  CS_VREDRAW ;        //
     wndclass . lpfnWndProc  =  WndProc ;                  //
     wndclass . cbClsExtra  =  0 ;                         //
     wndclass . cbWndExtra  =  0 ;                         //
     wndclass . hInstance  =  hInstance ;                  //
     wndclass . hIcon  =  LoadIcon ( NULL ,  IDI_APPLICATION ) ;        //
     wndclass . hCursor  =  LoadCursor ( NULL ,  IDC_ARROW ) ;          //
     wndclass . hbrBackground  =  ( HBRUSH ) GetStockObject ( WHITE_BRUSH ) ;        //
     wndclass . lpszMenuName  =  NULL ;            //
     wndclass . lpszClassName  =  szAppName ;      //,
     if  ( ! RegisterClass ( & wndclass ))       //
     {
         MessageBox ( NULL ,  TEXT ( " Windows NT " ) ,  szAppName ,  MB_ICONERROR ) ;
         return  0 ;
     }
     hwnd  =  CreateWindow (         //
         szAppName ,               //,
         TEXT ( "" ) ,      //,
         WS_OVERLAPPEDWINDOW ,     //
         CW_USEDEFAULT ,           //
         CW_USEDEFAULT ,           //
         CW_USEDEFAULT ,           //
         CW_USEDEFAULT ,           //
         NULL ,                    //
         NULL ,                    //
         hInstance ,               //
         NULL ) ;                   //
    
     ShowWindow ( hwnd ,  iCmdShow ) ;  //
     UpdateWindow ( hwnd ) ;          //
     while  ( GetMessage ( & msg ,  NULL ,  0 ,  0 ))     //msg
     {
         TranslateMessage ( & msg ) ;      //
         DispatchMessage ( & msg ) ;       //
     }
     return  msg . wParam ;
}
LRESULT  CALLBACK  WndProc ( HWND  hwnd ,  UINT  message ,  WPARAM  wParam ,  LPARAM  lParam )
{
     HDC  hdc ;
     PAINTSTRUCT  ps ;
     RECT  rect ;
     switch  ( message )
     {
     case  WM_PAINT :
         hdc  =  BeginPaint ( hwnd ,  & ps ) ;
         GetClientRect ( hwnd ,  & rect ) ;
         DrawText ( hdc ,  TEXT ( "" ) ,  -1 ,  & rect ,
              DT_SINGLELINE |  DT_CENTER |  DT_VCENTER ) ;
         EndPaint ( hwnd ,  & ps ) ;
         return  0 ;
     case  WM_DESTROY :
         PostQuitMessage ( 0 ) ;
         return  0 ;
     }
     return  DefWindowProc ( hwnd ,  message ,  wParam ,  lParam ) ;
}
 
     在程序中,消息是用MSG消息结构来表示的,我们在程序一开始就定义了一个消息结构。在窗口类的注册、创建、显示、更新时,我们找不到任何有关msg执行的代码,只有在后面GetMessage的时候才能看到。
    

    这个循环就是处理消息的,GetMessage函数负责从消息队列中获取一个消息传给指定的结构(msg)。如果函数取得WM_QUIT之外的其他消息,返回非零值。如果函数取得WM_QUIT消息,返回值是零。如果返回非零值,就执行循环体,循环体是两个函数,一个是TranslateMessage,用于将虚拟键消息转换成字符消息,字符消息被寄送到调用线程的消息队列里。DispatchMessage则是将一个消息给窗口程序。就是在执行这个函数的时候,系统调用了回调函数。函数中利用switch-case的方式,判断是不是我们“感兴趣”的消息,如果是该怎么响应,若遇到有些我们“不感兴趣”的消息,我们就直接return DefWindowsProc···交给这个函数进行默认的处理。

关于消息机制的补充:

--消息队列是FIFO的形式,也就是先进先出。先进入的队列会最先出,跟栈的形式刚好相反吧。

--WM_PAINT,WM_TIMER和WM_QUIT这三个队列属于特例,操作系统会把它们时刻放在消息队列的最后。只有当消息队列里面其他东西都执行完了,才去执行这三个。

--消息分为非队列消息和队列消息,非队列消息能开G,能插队,是Windows直接放给窗口过程的。


    若想了解一下MSG结构或者其他的一些结构、API,可以鱼C一下,点我~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值