MFC框架流程深入全面剖析和TLS系统的详细概述

来源:互联网 发布:策略模式 java学生成绩 编辑:程序博客网 时间:2024/06/08 07:00

       很多书上对于MFC流程的转换于SDK32的极其模糊的界面分析只是介绍大概,好多文章都是转载自别人的。本文详细论述一下MFC的本质。


      MFC的基础对话框也就是VS.net里面的后来的WINFORM 窗体架构的APPLICATION FRAMWORK框架的基础。win32C++ 编程把整个窗体分成了几大部分,分别如下:


       1.窗体的注册

       2.窗体的创建

       3.窗体的显示和更新

       4.窗体的消息循环【重要】

       5.窗体的回调函数【重要】

    

      一:程序的主线路  


     上面的其中的4,5是后来MFC封装的重点,MFC的入口点来源于InitInstance整个 来自于CWinThread类的一个函数重载。他是整个程序的起源,这是针对于当前基础对话框的整体而言,然实质上我们都知道C++的入口函数winMain()或者是Main()入口点。研究发现在WINMAIN.CPP MFC源文件当中有AfxWinMain函数里面调用了对话框重载的InitInstance.源码为:if (!pThread->InitInstance())。继续追踪在APPMODULE.CPP当中发现了调用AfxWinMain函数的C++/MFC整个程序入口点_tWinMain。函数原型如下:extern "C" int WINAPI_tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,LPTSTR lpCmdLine, int nCmdShow)。继续追踪发现_tWinMain的定义在TCHAR.H中宏定义为 #define _tWinMain   WinMain刚好对应上了win32sdk中的入口函数一模一样,丝毫没变。至此程序从入口点WinMain-》AfxWinMain->InitInstance(虚函数重载)。


    二:程序的消息循环


      消息循环为整个win32程序的源头于活水,只有源源不断的活水流进,整个程序才能呈现出生机。MFC的源头活水在InitInstance程序主线初始化之后开始进行的,有DoModal()函数调用CWnd类的在WINCORE.CPP中RunModalLoop

实现消息循环。这个函数通过一个无限循环的for (;;)循环控制两个满足于某个两个不同特殊条件的while 进行整个过消息循环。此处基础对话框的消息维持是:::PeekMessage(pMsg, NULL, NULL, NULL, PM_NOREMOVE)。其中由函数空隙时间IsIdleMessage和函数真正的分配消息PumpMessage。PumpMessage调用了PreTranslateMessage预处理消息,来进行必要的消息过滤。所以此处可以看做是MFC对于windows message的一个检测,如果符合MFC的设计理念则进行下一步操作,不符合则舍弃【所谓MFC理念,sendMessage发送的对于本线程的消息完全不经过PreTranslateMessage,所以MFC无法响应。PostMessage则是正宗的MFC PeekMessage 检测的重点(消息队列)】。注意此处极其重要的一点就是如果基础对话窗体上面有别的控件的话,会导致窗体不能够响应WM_CHAR,WM_KEYDOWN,WM_KEYUP等三个消息。经过PreTranslateMessage的消息是完全干净绿色消息,是完整的没有经过任何预处理过的消息。解决此类方法的就是通过派生得到的基础窗体来重载PreTranslateMessage来响应以上三个消息。


     三:消息的回调函数


      研究发现所有的MFC窗口过程函数都是默认的API窗体调用函数,DefWndProc。这个导致一个问题就是无法让消息处理流经MFC自定义的所谓的预处理PreTranslateMessage函数上来,因为他直接流向了默认的处理函数。为了解决这个问题,MFC 运用了HOOK技术来实现让MFC  的实际窗体处理函数指向他自己定义窗口过程函数afxWndProc。上面说过InitInstance是整个程序的主线贯穿始终,所以对于钩子的调用当然也是在InitInstance里面进行的。具体如下InitInstance调用DoModal(),DoModal()调用了AfxHookWindowCreate();实现了他原有的默认的DefWndProc的改变。这个改变其实并非想象中的简单,首先在窗体创建的时候如果直接调用SetWindowLong来改变窗口过程函数,很可能会漏掉许多消息,诸如VM_CREATE等等,所以此处必须用训练钩子来确保每一个消息都在MFC框架的掌控之内。可以让WH_CBT 的code参数辨认当前窗体的行程过程,当CODE==HCBT_CREATEWND的时候就开始HOOK钩子,当窗体创建的时候就开始对对回调地址进行直接改变。如此便可实现所谓的钩子MFC自定义回调过程,而不用默认的DefWndProc.默认的可以用来处理某些不需要设置的或者拦截的方法,作为一个默认实现。


      m_pMainWnd,AfxFindResourceHandle,afxinitwinmain

    

       未完,明天续....

          

     

0 0
原创粉丝点击