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

来源:互联网 发布:发那科机器人编程视频 编辑:程序博客网 时间:2024/05/26 19:15

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


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

2    对于全局对象或全局变量来说,在程序运行即WINMAIN函数加载的时候,已经为全局对象或全局变量分配了内存和赋初值。
所以:CTEApp 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()://主要是注册窗口类
BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs)
{
 if( !CFrameWnd::PreCreateWindow(cs) )
  return FALSE;
 return TRUE;
}
说明:
CFrameWnd::PreCreateWindow()函数所在文件:MFC|SRC|WINFRM.CPP
BOOL CFrameWnd::PreCreateWindow(CREATESTRUCT& cs)
{
 if (cs.lpszClass == NULL)
 {
  VERIFY(AfxDeferRegisterClass(AFX_WNDFRAMEORVIEW_REG));
   //判断AFX_WNDFRAMEORVIEW_REG型号窗口类是否注册,如果没有注册则注册
  cs.lpszClass = _afxWndFrameOrView;  // COLOR_WINDOW background
   //把注册后的窗口类名赋给cs.lpszClass
 }

 if ((cs.style & FWS_ADDTOTITLE) && afxData.bWin4)
  cs.style |= FWS_PREFIXTITLE;

 if (afxData.bWin4)
  cs.dwExStyle |= WS_EX_CLIENTEDGE;

 return TRUE;
}

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

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

CWnd::CreateEx()函数路径:MFC|SRC|WINCORE.CPP
BOOL CWnd::CreateEx(...){
 ...
 if (!PreCreateWindow(cs))//虚函数,如果子类有调用子类的。
 {
  PostNcDestroy();
  return FALSE;
 }
 ...
 HWND hWnd = ::CreateWindowEx(cs.dwExStyle, cs.lpszClass,
  cs.lpszName, cs.style, cs.x, cs.y, cs.cx, cs.cy,
  cs.hwndParent, cs.hMenu, cs.hInstance, cs.lpCreateParams);

 ...
}
说明:CreateWindowEx()函数与CREATESTRUCT结构体参数的对应关系,使我们在创建窗口之前通过可PreCreateWindow(cs)修改cs结构体成员来

修改所要的窗口外观。PreCreateWindow(cs))//是虚函数,如果子类有调用子类的。
HWND CreateWindowEx(
  DWORD dwExStyle,     
  LPCTSTR lpClassName, 
  LPCTSTR lpWindowName,
  DWORD dwStyle,       
  int x,               
  int y,               
  int nWidth,          
  int nHeight,         
  HWND hWndParent,     
  HMENU hMenu,         
  HINSTANCE hInstance, 
  LPVOID lpParam       
);
typedef struct tagCREATESTRUCT { // cs
    LPVOID    lpCreateParams;
    HINSTANCE hInstance;
    HMENU     hMenu;
    HWND      hwndParent;
    int       cy;
    int       cx;
    int       y;
    int       x;
    LONG      style;
    LPCTSTR   lpszName;
    LPCTSTR   lpszClass;
    DWORD     dwExStyle;
} CREATESTRUCT;

8  显示和更新窗口:
CTEApp类,TEApp.cpp中
m_pMainWnd->ShowWindow(SW_SHOW);//显示窗口,m_pMainWnd指向框架窗口
m_pMainWnd->UpdateWindow();//更新窗口
说明:
class CTEApp : public CWinApp{...}
class CWinApp : public CWinThread{...}
class CWinThread : public CCmdTarget
{
 ...
public:
 CWnd* m_pMainWnd;
 ...
...
}

9  消息循环:
int AFXAPI AfxWinMain()
{ ...
 // Perform specific initializations
 if (!pThread->InitInstance()){...}
 //完成窗口初始化工作,完成窗口的注册,完成窗口的创建,显示和更新。
 nReturnCode = pThread->Run();
 //继承基类Run()方法,调用CWinThread::Run()来完成消息循环
 ...
}
////////////////////////////////////////////////////////////////
CWinThread::Run()方法路径:MFC|SRC|THRDCORE.CPP
int CWinThread::Run()
{ ...
  // phase2: pump messages while available
  do//消息循环
  {
   // pump message, but quit on WM_QUIT
   if (!PumpMessage())//取消息并处理
    return ExitInstance();
   ...
  } while (::PeekMessage(&m_msgCur, NULL, NULL, NULL, PM_NOREMOVE));
 ...
}
说明:
BOOL PeekMessage(,,,,)函数说明
The PeekMessage function checks a thread message queue for a message and places the message (if any) in the specified

structure.
If a message is available, the return value is nonzero.
If no messages are available, the return value is zero.

/////////////////////////////////////////////////////////////
BOOL CWinThread::PumpMessage()
{
 ...
 if (!::GetMessage(&m_msgCur, NULL, NULL, NULL))//取消息
 {...}
 ...
 // process this message
 if (m_msgCur.message != WM_KICKIDLE && !PreTranslateMessage(&m_msgCur))
 {
  ::TranslateMessage(&m_msgCur);//进行消息(如键盘消息)转换
  ::DispatchMessage(&m_msgCur);//分派消息到窗口的回调函数处理(实际上分派的消息经过消息映射,交由消息响应函数进行处理。)
 }
 return TRUE;
}

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

10  文档类,视类,框架类的有机结合:
在CTEApp类CTEApp::InitInstance()函数中通过文档模板将文档类,视类,框架类的有机组织一起。
...
CSingleDocTemplate* pDocTemplate;
pDocTemplate = new CSingleDocTemplate(
 IDR_MAINFRAME,
 RUNTIME_CLASS(CTEDoc),
 RUNTIME_CLASS(CMainFrame),       // main SDI frame window
 RUNTIME_CLASS(CTEView));
AddDocTemplate(pDocTemplate);//增加到模板
...
  

原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 内倒窗户卡住了怎么办 支付宝存在安全风险怎么办 地铁车站空调坏了怎么办 面试防汛值班发生灾情你怎么办 怀孕上班路途太远怎么办 硕士错过校招应该怎么办 收银员收多了钱怎么办 商铺贷款批不了怎么办 铁路局的门面乱收房租怎么办 酒店夜审房费多过怎么办 夜审房价录多了怎么办 做工地拿不到钱怎么办 赢了官司拿不到钱怎么办 工地上拿不到钱怎么办 做了工拿不到钱怎么办 高速公路上车没油了怎么办 高铁乘务员年龄大了怎么办 总公司跑路了分公司怎么办 坐车久了耳朵懵怎么办 过完隧道耳朵疼怎么办 护照还在大使馆需要出国怎么办 护照在大使馆不返回怎么办 美国面签迟到了怎么办 成都美签迟到了怎么办 签证电调没人接怎么办 单位没有抬头纸怎么办在职证明 出国签证无银行流水怎么办 铁路职工得癌症后工作怎么办 去泰国不会泰语和英语怎么办 签证状态一直没有更新怎么办 简理财不能身份信息确认怎么办 德国领事馆没有收到预约邮件怎么办 父母一方带孩子英国签证怎么办 去韩国自由行签证怎么办 韩国自由行签证的该怎么办 法院离婚判决书没了怎么办 离婚判决书对方没收到怎么办 法院判离怎么办离婚证 判决书下来后没钱还怎么办 拿调解书怎么办离婚证 判决书生效后对方拒不履行怎么办