1、MFC 中是如何来对应传统的 windows 程序?
首先在 CXXXApp 中会定义一个全局变量 CXXXApp theApp
我们知道,在 C/C++ 中,编译器会在进入 main/WinMain 函数之前会给全局变量分配内存空间,所以在 MFC 中,首先会为 theAPP分配内存空间, 并调用 CXXXApp 类的构造函数 CXXXApp() 。
在 VC++ 的安装目录下面, Microsoft Visual Studio/VC98/MFC/SRC 中存放了 MFC 的部分源代码。其中在 APPMODUL.cpp 中包含了 _tWinMain 的一个宏函数,且
#define _tWinMain WinMain
其中在 MFC 的 _tWinMain 的宏函数中又调用了 AfxWinMain 函数。
这个 AfxWinMain 函数在 WINMAIN.cpp 中,其中调用了 pThread- > InitInstance () ,但是由于 InitInstance () 是虚函数,根据多态性,调用的其实是派生类 CXXXApp 中的 InitInstance () 。
注册窗口类用了 AfxEndDeferRefisterClass 函数,在 WINCORE.CPP 中。当然, MFC 已经根据不同的窗口类型,如 ToolBar,StatusBar 会默认指定窗口类型。在 AfxEndDeferRefisterClass() 真正调用了 AfxRegisterClass(), 进一步在 AfxRegisterClass() 调用了 Win32 的 API 函数 ::RegisterClass() 函数。
接着就是产生窗口,窗口都是继承 CWnd 类,都有一个 PreCreateWindow() 函数,且都调用了 CFrameWnd::PreCreateWindow, 这个里面会有 VERIFY(AfxDeferRefisterClass()) ,确认是否已经注册窗口类。这个 AfxDeferRefisterClass 其实就是宏函数,在 AFXIMPL.H 中有
#define AfxDeferRefisterClass(class) AfxEndDeferRefisterClass(class)
当然上面的注册窗口,在单文档程序中,是在调用派生类 CXXXApp 中的 InitInstance () 中的
ProcessShellCommand() 中提前注册了。
创建窗口
CWnd::CreateEx 函数 ( 这个不是虚函数 ) ,这个函数被 CFrameWnd::Create() 调用。在 CWnd::CreateEx 又再一次调用了 PreCreateWindow ,且这个 PreCreateWindow 是虚函数,在这边设置这个函数的好处就是给用户一个机会在窗口产生之前可以修改窗口的类型。 PreCreateWindow(CREATESTRUCT &cs), 这边用了引用,所以在派生中的修改可以影响到基类。
下面就是在 CXXXApp 中的 InitInstance () 中的 ShowWindow 和 UpdateWindow 函数。
最后就是消息循环。
在 CWinThread::Run(), 在 threadcore.cpp ,这里面又调用了 PumpMessage(), 在这个函数的最后我们可以看到。
::TranslateMessgae()
::DispatchMessgae()
当然对于传统的回调函数, MFC 中用了消息映射的机制,具体的消息由消息响应函数来处理。
2、单文档程序如何将 CXXXApp,CMainFrame,CXXXView,CXXXDoc 组织起来?
数据的加载由文档类完成,数据的显示由 View 类完成。在 CXXXApp 的 InitInstance () 中利用文档模板组织起来。
CsingleDocTemplate* pDocTemplate;
pDocTemplate=new CsingleDocTemplate(
IDR_MAINFRAME,
RUNTIME_CLASS(CXXXDoc),
RUNTIME_CLASS(CMainFrame),
RUNTIME_CLASS(CXXXView));
AddDocTemplate(pDocTemplate);
3、窗口类和窗口的关系。
MFC 的类维护了窗口,一般的 MFC 类在析构函数中都会销毁窗口。所以,当 MFC 的类生命周期到的时候,窗口的生命周期就到了。但是,反过来,当窗口的生命周期到的时候,相应的类的生命周期就不一定了,类还是可以使用的。
4、窗口显示的两种方法。
可以在窗口类型中加了 WS_VISIBLE
CButton m_btn;
m_btn.Create(..,WS_VISIBLE,...)
或者
CButton m_btn;
m_btn.Create(..,,...)
m_btn.ShowWindow(SW_SHOWNORMAL);