随笔 - 47, 文章 - 10, 评论 - 8, 引用 - 0
数据加载中……

孙鑫VC++讲座笔记-(3)MFC程序框架的剖析

1,寻找WinMain人口:
在安装目录下找到MFC文件夹下的SRC文件夹,SRC下是MFC源代码。
路径:MFC|SRC|APPMODUL.CPP:
1_tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
2 LPTSTR lpCmdLine, int nCmdShow)
3{
4 // call shared/exported WinMain
5 return AfxWinMain(hInstance, hPrevInstance, lpCmdLine, nCmdShow);
6}

7
注意:(#define _tWinMain   WinMain)
2,对于全局对象或全局变量来说,在程序运行即WINMAIN函数加载的时候,已经为全局对象或全局变量分配了内存和赋初值。
所以:
1CTEApp theApp;->CTEApp ::CTEApp(){}->_tWinMain(){}

说明:每一个MFC程序,有且只有一个从WinApp类派生的类(应用程序类),也只有一个从应用程序类所事例化的对象,表示应用程序本身。在WIN32程序当中,表示应用程序是通过WINMAIN入口函数来表示的(通过一个应用程序的一个事例号这一个标识来表示的)。在基于MFC应用程序中,是通过产生一个应用程序对象,用它来唯一的表示了应用程序。

3,通过构造应用程序对象过程中调用基类CWinApp的构造函数,在CWinApp的构造函数中对程序包括运行时一些初始化工作完成了。
CWinApp构造函数:MFC|SRC|APPCORE.CPP
CWinApp::CWinApp(LPCTSTR lpszAppName){...}//带参数,而CTEApp构造函数没有显式向父类传参,难道CWinApp()有默认参数?见下:
(在CWinApp类定义中, CWinApp(LPCTSTR lpszAppName = NULL); )
注意:CWinApp()函数中:
pThreadState->m_pCurrentWinThread = this;
pModuleState->m_pCurrentWinApp = this
(this指向的是派生类CTEApp对象,即theApp)
调试:CWinApp::CWinApp();->CTEApp theApp;(->CTEApp ::CTEApp())->CWinApp::CWinApp()->CTEApp ::CTEApp()->_tWinMain(){}

4,_tWinMain函数中通过调用AfxWinMain()函数来完成它要完成的功能。(Afx*前缀代表这是应用程序框架函数,是一些全局函数,应用程序框架是一套辅助生成应用程序的框架模型,把一些类做一些有机的集成,我们可根据这些类函数来设计自己的应用程序)。
AfxWinMain()函数路径:MFC|SRC|WINMAIN.CPP:
在AfxWinMain()函数中:
CWinApp* pApp = AfxGetApp();
说明:pApp存储的是指向WinApp派生类对象(theApp)的指针。
//_AFXWIN_INLINE CWinApp* AFXAPI AfxGetApp()
// { return afxCurrentWinApp; }

调用pThread->InitInstance()
说明:pThread也指向theApp,由于基类中virtual BOOL InitApplication()定义为虚函数,所以调用pThread->InitInstance()时候,调用的是派生类CTEApp的InitInstance()函数。

nReturnCode = pThread->Run();
说明:pThread->Run()完成了消息循环。

5,注册窗口类:AfxEndDeferRegisterClass();
AfxEndDeferRegisterClass()函数所在文件:MFC|SRC|APPCORE.CPP
BOOL AFXAPI AfxEndDeferRegisterClass(LONG fToRegister){...}
说明:设计窗口类:在MFC中事先设计好了几种缺省的窗口类,根据不同的应用程序的选择,调用AfxEndDeferRegisterClass()函数注册所选择的窗口类。
调试:CWinApp::CWinApp();->CTEApp theApp;(->CTEApp ::CTEApp())->CWinApp::CWinApp()->CTEApp ::CTEApp()->_tWinMain(){}//进入程序
->AfxWinMain();->pApp->InitApplication();->pThread->InitInstance()//父类InitInstance虚函数;->CTEApp::InitInstance()//子类实现函数;->AfxEndDeferRegisterClass(LONG fToRegister)//注册所选择的窗口类(出于文档管理,注册提前,正常的应在PreCreateWindow中进行注册)//之后进入创建窗口阶段(以下再不做调试)

6,PreCreateWindow()://主要是注册窗口类

1BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs)
2{
3 if!CFrameWnd::PreCreateWindow(cs) )
4  return FALSE;
5 return TRUE;
6}

7

说明:
 1CFrameWnd::PreCreateWindow() //函数所在文件:MFC|SRC|WINFRM.CPP
 2BOOL CFrameWnd::PreCreateWindow(CREATESTRUCT& cs)
 3{
 4 if (cs.lpszClass == NULL)
 5 {
 6  VERIFY(AfxDeferRegisterClass(AFX_WNDFRAMEORVIEW_REG));
 7   //判断AFX_WNDFRAMEORVIEW_REG型号窗口类是否注册,如果没有注册则注册
 8  cs.lpszClass = _afxWndFrameOrView;  // COLOR_WINDOW background
 9   //把注册后的窗口类名赋给cs.lpszClass
10 }

11 if ((cs.style & FWS_ADDTOTITLE) && afxData.bWin4)
12  cs.style |= FWS_PREFIXTITLE;
13
14 if (afxData.bWin4)
15  cs.dwExStyle |= WS_EX_CLIENTEDGE;
16
17 return TRUE;
18}

其中:

1virtual BOOL PreCreateWindow(CREATESTRUCT& cs);//PreCreateWindow()是个虚函数,如果子类有则调用子类的。
2#define VERIFY(f)          ASSERT(f)
3#define AfxDeferRegisterClass(fClass) AfxEndDeferRegisterClass(fClass)
4define AFX_WNDFRAMEORVIEW_REG          0x00008
5const TCHAR _afxWndFrameOrView[] = AFX_WNDFRAMEORVIEW;//WINCORE.CPP文件中,定义为全局数组。
6//#define AFX_WNDFRAMEORVIEW  AFX_WNDCLASS("FrameOrView")

7,创建窗口:
Create()函数路径:MFC|SRC|WINFRM.CPP:
 1CFrameWnd::Create(){
 2 
 3 CreateEx();//从父类继承来的,调用CWnd::CreateEx().
 4 
 5}

 6
 7CWnd::CreateEx()//函数路径:MFC|SRC|WINCORE.CPP
 8BOOL CWnd::CreateEx(){
 9 
10 if (!PreCreateWindow(cs))//虚函数,如果子类有调用子类的。
11 {
12  PostNcDestroy();
13  return FALSE;
14 }

15 
16 HWND hWnd = ::CreateWindowEx(cs.dwExStyle, cs.lpszClass,
17  cs.lpszName, cs.style, cs.x, cs.y, cs.cx, cs.cy,
18  cs.hwndParent, cs.hMenu, cs.hInstance, cs.lpCreateParams);
19
20 
21}

22说明:CreateWindowEx()//函数与CREATESTRUCT结构体参数的对应关系,使我们在创建窗口之前通过可PreCreateWindow(cs)修改cs结构体成员来修改所要的窗口外观。P
23reCreateWindow(cs))//是虚函数,如果子类有调用子类的。
24HWND CreateWindowEx(
25  DWORD dwExStyle,      
26  LPCTSTR lpClassName,  
27  LPCTSTR lpWindowName, 
28  DWORD dwStyle,        
29  int x,                
30  int y,                
31  int nWidth,           
32  int nHeight,          
33  HWND hWndParent,      
34  HMENU hMenu,          
35  HINSTANCE hInstance,  
36  LPVOID lpParam        
37);
38typedef struct tagCREATESTRUCT // cs 
39    LPVOID    lpCreateParams; 
40    HINSTANCE hInstance; 
41    HMENU     hMenu; 
42    HWND      hwndParent; 
43    int       cy; 
44    int       cx; 
45    int       y; 
46    int       x; 
47    LONG      style; 
48    LPCTSTR   lpszName; 
49    LPCTSTR   lpszClass; 
50    DWORD     dwExStyle; 
51}
 CREATESTRUCT; 
52
53
54

8,显示和更新窗口:
 1CTEApp类,TEApp.cpp中
 2m_pMainWnd->ShowWindow(SW_SHOW);//显示窗口,m_pMainWnd指向框架窗口
 3m_pMainWnd->UpdateWindow();//更新窗口
 4说明:
 5class CTEApp : public CWinApp{}
 6class CWinApp : public CWinThread{}
 7class CWinThread : public CCmdTarget
 8{
 9 
10public:
11 CWnd* m_pMainWnd;
12 
13
14}

9,消息循环:
 1int AFXAPI AfxWinMain()
 2
 3 // Perform specific initializations
 4 if (!pThread->InitInstance()){}
 5 //完成窗口初始化工作,完成窗口的注册,完成窗口的创建,显示和更新。
 6 nReturnCode = pThread->Run();
 7 //继承基类Run()方法,调用CWinThread::Run()来完成消息循环
 8 
 9}

10////////////////////////////////////////////////////////////////
11CWinThread::Run()方法路径:MFC|SRC|THRDCORE.CPP
12int CWinThread::Run()
13
14  // phase2: pump messages while available
15  do//消息循环
16  {
17   // pump message, but quit on WM_QUIT
18   if (!PumpMessage())//取消息并处理
19    return ExitInstance();
20   
21  }
 while (::PeekMessage(&m_msgCur, NULL, NULL, NULL, PM_NOREMOVE));
22 
23}

24说明:
25BOOL PeekMessage(,,,,)函数说明
26The PeekMessage function checks a thread message queue for a message and places the message (if any) in the specified structure.
27If a message is available, the return value is nonzero.
28If no messages are available, the return value is zero. 
29
30/////////////////////////////////////////////////////////////
31BOOL CWinThread::PumpMessage()
32{
33 
34 if (!::GetMessage(&m_msgCur, NULL, NULL, NULL))//取消息
35 {}
36 
37 // process this message
38 if (m_msgCur.message != WM_KICKIDLE && !PreTranslateMessage(&m_msgCur))
39 {
40  ::TranslateMessage(&m_msgCur);//进行消息(如键盘消息)转换
41  ::DispatchMessage(&m_msgCur);//分派消息到窗口的回调函数处理(实际上分派的消息经过消息映射,交由消息响应函数进行处理。)
42 }

43 return TRUE;
44}

45
46

9,文档与视结构:
可以认为View类窗口是CMainFram类窗口的子窗口。
DOCument类是文档类。
DOC-VIEW结构将数据本身与它的显示分离开。
文档类:数据的存储,加载
视类:数据的显示,修改

10,文档类,视类,框架类的有机结合:
在CTEApp类CTEApp::InitInstance()函数中通过文档模板将文档类,视类,框架类的有机组织一起。

1
2CSingleDocTemplate* pDocTemplate;
3pDocTemplate = new CSingleDocTemplate(
4 IDR_MAINFRAME,
5 RUNTIME_CLASS(CTEDoc),
6 RUNTIME_CLASS(CMainFrame),       // main SDI frame window
7 RUNTIME_CLASS(CTEView));
8AddDocTemplate(pDocTemplate);//增加到模板
9


posted on 2006-04-04 11:07 编程之道 阅读(110) 评论(0)  编辑 收藏 引用 所属分类: C/C++


只有注册用户登录后才能发表评论。
【推荐】超50万行VC++源码: 大型组态工控、电力仿真CAD与GIS源码库
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理