Windows线程和消息队列

一、桌面窗口
    启动windows系统,登录用户拥有一个会话(Sessions),一个会话拥有一个私有对象命名空间(\BaseNamedObjects),也拥有多个窗口站(WindowsStation),其中只有一个窗口站是交互式的,其他窗口站是非交互的。这个交互式窗口站至少拥有三个桌面:默认桌面、登录桌面、屏保桌面。默认桌面是系统定义的桌口,这个窗口绘制屏幕的背景,作为windows应用程序显示窗口的基础。所有window应用程序窗口都与该默认桌面窗口绑定。应用程序窗口都是用来显示输出和从用户得到输入,完成与登录用户交互。

二、消息队列

Windows系统维护一个系统消息队列,同时windows系统为每个GUI线程创建消息队列。对于非GUI线程,为了节省资源开支,windows不会创建消息队列。为了处理每个GUI线程的消息队列中消息,windows应用程序启动消息环,要用函数GetMessage和DispatchMessagey来创建消息环。
    消息处理过程如下:登录用户移动鼠标或敲击键盘,鼠标或键盘的设备驱动器都把输入转换消息,并把该消息投放到系统消息队列中。Windows会从系统消息队列中每次移走一个消息,先确定目的窗口,再把该消息投递到创建目的窗口的线程的消息队列。线程消息队列接收所有该线程创建的窗口的鼠标和键盘消息。每个GUI线程从它的消息队列中移走消息并指导windows系统将消息发送到相应窗口过程进行处理。

三、窗口过程

窗口过程是一个函数,用来接受和处理所有发送到该窗口的消息,每个窗口类都有一个窗口过程,同一窗口类所创建的窗口共同使用一个窗口过程来响应消息。

窗口过程一般情况会处理每一条消息,如果它不处理某条消息,它必须把该条消息传给系统进行默认处理,该默认处理函数是:DefWindowProc。如:
    LONG APIENTRY MainWndProc(HWND hwnd,UINT uMsg,UINT wParam,LONG    lParam)

{

   switch(uMsg)

   {

   case WM_CREATE:
           …

       Break:
       case WM_CLOSE:

        If(MessageBox(hwnd,szConfirm,szAppName,MB_YESNOCANCEL) ==IDYES)

        DestroyWindow(hwndmain);

       break;
case WM_DESTROY:

          poseQuitMessage(0);

         return 0;

   default:

         return DefWindowProc(hwnd,uMsg,wParam,lParam);
                

  

}

四、投递和发送消息

投递消息是通过把消息复制到消息队列,具体情况:PostMessge为消息创建一个MSG结构并把消息复制到消息队列中,最后由应用程序的消息环检取这条消息再把它发送到相应的窗口过程函数。

发送消息则通过把消息数据作为窗口过程的参数来处理消息,具体情况:SendMessage把消息发送到与给定窗口相应的窗口过程函数,SendMesage要等待窗口过程函数完成处理并返回结果。

  

五、窗口子类
    为了特殊功能,要为一个窗口的实例建子类,需要调用函数SetWindowLong并指定GWL_WND_PROC标记,要建子类的窗口的句柄和子类过程的指针。SetWindowLong 返回原窗口过程的指针;通过该函数指针来调用原窗口过程。

   WNDPROC wpOrigEditProc
   LRESULT ANIENTRY DlgProc(hwndDlg,uMsg,wparam,laPram)
   {

        HWND hwndEdit ;

        Switch(uMsg)

        {

        Case WM_INITDIALOG:

             hwndEdit = GetDlgItem(hwndDlg,ID_EDIT) ;
             wpOrigEditProc = (WNDPROC)SetWindowLong(hwndEdit,GWL_WNDPROC,(LONG)EditSubClassProc);

           break ;

        case WM_DESTROY:
           SetWindowLong(hwndEdit,GWL_WNDPROC,(LONG)wpOrigEditProc);

           break ;

}

}

 LRESULT APIENTRY EditSubClassProc(hwnd,uMsg,wParam,lParam)
{

   ….

   Return CallWindowProc(wpOrigEditProc,hwnd,uMsg,wParam,lParam);

}

上一篇:如何在手机端上抓包?


下一篇:OSS 实践篇-C SDK 安装