1.在MFC的源代码中查找入口函数WinMain().
 X:/Program Files/Microsoft Visual Studio/VC98/MFC/SRC

APPMODUL.CPP文件中
------------------------------------------------------------------------
extern "C" int WINAPI
_tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
 LPTSTR lpCmdLine, int nCmdShow)
{                                                            //Breakpoint1
 // call shared/exported WinMain
 return AfxWinMain(hInstance, hPrevInstance, lpCmdLine, nCmdShow);
}
-------------------------------------------------------------------------
TCHAR.H
------------------------------------------------------------------------
#define _tWinMain   WinMain
------------------------------------------------------------------------
Test.cpp
------------------------------------------------------------------------
CTestApp::CTestApp()
{                                                             //Breakpoint2
 // TODO: add construction code here,
 // Place all significant initialization in InitInstance
}
------------------------------------------------------------------------
RUNNING: Breakpoint2->Breakpoint1
首先进入CTestApp的构造函数,然后才到达_tWinMain()函数
Test.cpp
--------------------------------------------------------------------------
CTestApp theApp;  //全局对象                                 //Breakpoint3
--------------------------------------------------------------------------
RUNNING: Breakpoint3->Breakpoint2->Breakpoint1

2.在MFC程序中,通过产生一个应用程序类的对象来表示应用程序本身
   在X:/Program Files/Microsoft Visual Studio/VC98/MFC/SRC搜索WinApp
   得到:
   APPCORE.CPP
--------------------------------------------------------------------------
   CWinApp::CWinApp(LPCTSTR lpszAppName)                 //CWinApp的构造函数
   {
 if (lpszAppName != NULL)
  m_pszAppName = _tcsdup(lpszAppName);
 else
  m_pszAppName = NULL;

// initialize CWinThread state
 AFX_MODULE_STATE* pModuleState = _AFX_CMDTARGET_GETSTATE();
 AFX_MODULE_THREAD_STATE* pThreadState = pModuleState->m_thread;
 ASSERT(AfxGetThread() == NULL);
 pThreadState->m_pCurrentWinThread = this;   //this指针指向CTestApp对象(theApp)
                                                    //根据继承性的原理(使用程序测试)
 ASSERT(AfxGetThread() == this);
 m_hThread = ::GetCurrentThread();
 m_nThreadID = ::GetCurrentThreadId();

// initialize CWinApp state
 ASSERT(afxCurrentWinApp == NULL); // only one CWinApp object please
 pModuleState->m_pCurrentWinApp = this;
 ASSERT(AfxGetApp() == this);

// in non-running state until WinMain
 m_hInstance = NULL;
 m_pszHelpFilePath = NULL;
 m_pszProfileName = NULL;
 m_pszRegistryKey = NULL;
 m_pszExeName = NULL;
 m_pRecentFileList = NULL;
 m_pDocManager = NULL;
 m_atomApp = m_atomSystemTopic = NULL;
 m_lpCmdLine = NULL;
 m_pCmdInfo = NULL;

// initialize wait cursor state
 m_nWaitCursorCount = 0;
 m_hcurWaitCursorRestore = NULL;

// initialize current printer state
 m_hDevMode = NULL;
 m_hDevNames = NULL;
 m_nNumPreviewPages = 0;     // not specified (defaults to 1)

// initialize DAO state
 m_lpfnDaoTerm = NULL;   // will be set if AfxDaoInit called

// other initialization
 m_bHelpMode = FALSE;
 m_nSafetyPoolSize = 512;        // default size
   }
--------------------------------------------------------------------------------
CWinApp的构造函数带有参数LPCTSTR lpszAppName,而CTestApp的构造函数不带有任何参数.
在AFXWIN.H文件中
-----------------------------------------------------------------------------
class CWinApp : public CWinThread
{
 DECLARE_DYNAMIC(CWinApp)
public:

// Constructor
 CWinApp(LPCTSTR lpszAppName = NULL); //CWinApp的构造函数有缺省的参数   
 ..............................
}
------------------------------------------------------------------------------
3. 回到_tWinMain(...)函数
   查找AfxWinMain()函数,Afx表示应用程序框架类函数,相当于全局函数
-------------------------------------------------------------------------------
   int AFXAPI AfxWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
 LPTSTR lpCmdLine, int nCmdShow)
   {
 ASSERT(hPrevInstance == NULL);

int nReturnCode = -1;
 CWinThread* pThread = AfxGetThread(); //线程的指针,也是指向子类
 CWinApp* pApp = AfxGetApp(); //获得指针,这里pApp指向派生类的指针(theApp)

// AFX internal initialization
 if (!AfxWinInit(hInstance, hPrevInstance, lpCmdLine, nCmdShow))
  goto InitFailure;

// App global initializations (rare)
 if (pApp != NULL && !pApp->InitApplication())//pApp->InitApplication()MFC内部
                                              //管理的函数
  goto InitFailure;

// Perform specific initializations
 if (!pThread->InitInstance())  //pThread->InitInstance()       //Breakpoint4
                                //在AFXWIN.H中
           //virtual BOOL InitInstance();
           //InitInstance是一个虚函数
           //此时调用的InitInstance函数是
           //CTestApp::InitInstance()

{
  if (pThread->m_pMainWnd != NULL)
  {
   TRACE0("Warning: Destroying non-NULL m_pMainWnd/n");
   pThread->m_pMainWnd->DestroyWindow();
  }
  nReturnCode = pThread->ExitInstance();
  goto InitFailure;
 }
 nReturnCode = pThread->Run();//Run()方法完成我们的消息循环

InitFailure:
#ifdef _DEBUG
 // Check for missing AfxLockTempMap calls
 if (AfxGetModuleThreadState()->m_nTempMapLock != 0)
 {
  TRACE1("Warning: Temp map lock count non-zero (%ld)./n",
   AfxGetModuleThreadState()->m_nTempMapLock);
 }
 AfxLockTempMaps();
 AfxUnlockTempMaps(-1);
#endif

AfxWinTerm();
 return nReturnCode;
   }
------------------------------------------------------------------------------------
4.在CTestApp的InitInstance()函数设置断点
------------------------------------------------------------------------------------
   BOOL CTestApp::InitInstance()
   {                                                      //Breakpoint5
 AfxEnableControlContainer();
        .............
   }
-------------------------------------------------------------------------------------
RUNNING:<1> 定义全局对象  CTestApp theApp;    (Breakpoint3)
        <2> 构造全局对象  CTestApp::CTestApp()(Breakpoint2)
 <3> 构造基类对象 
 <4> 进入_tWinMain函数                 (Breakpoint1)
 <5> 到达AfxWinMain函数
     if (!pThread->InitInstance())     (Breakpoint4)
 <6> 到达CTestApp::InitInstance()      (Breakpoint5)
5.注册窗口类
  AfxEndDeferRegisterClass函数
  WINCORE.CPP中                       (注册窗口类应该在PreCreateWindow中调用)
  由于是单文档应用程序的原因,事先调用AfxEndDeferRegisterClass函数注册窗口                     
-------------------------------------------------------------------------------------
BOOL AFXAPI AfxEndDeferRegisterClass(LONG fToRegister)
{                                                                  // Breakpoint6
 // mask off all classes that are already registered
 AFX_MODULE_STATE* pModuleState = AfxGetModuleState();
 fToRegister &= ~pModuleState->m_fRegisteredClasses;
 if (fToRegister == 0)
  return TRUE;

LONG fRegisteredClasses = 0;
 ........................
 wndcls.lpfnWndProc = DefWindowProc;       
}
-------------------------------------------------------------------------------------
BOOL AFXAPI AfxRegisterClass(WNDCLASS* lpWndClass)
{
 WNDCLASS wndcls;
 if (GetClassInfo(lpWndClass->hInstance, lpWndClass->lpszClassName,
  &wndcls))                  //判断窗口是否注册
 {
  // class already registered
  return TRUE;
 }

if (!::RegisterClass(lpWndClass))              //调用RegisterClass,API函数
 {
  TRACE1("Can't register window class named %s/n",
   lpWndClass->lpszClassName);
  return FALSE;
 }
 .................................................
}
-------------------------------------------------------------------------------------
        <7> 注册窗口类
    BOOL AFXAPI AfxEndDeferRegisterClass(LONG fToRegister)  (Breakpoint6)
6.产生窗口
 CMainFrm.CPP
-------------------------------------------------------------------------------------
BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs)
{                                                                   (Breakpoint7)
 if( !CFrameWnd::PreCreateWindow(cs) )  //函数调用
  return FALSE;
 // TODO: Modify the Window class or styles here by modifying
 //  the CREATESTRUCT cs

return TRUE;
}
-------------------------------------------------------------------------------------
 <8>BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs)        (Breakpoint7)
WINFRM.CPP
-------------------------------------------------------------------------------------
BOOL CFrameWnd::PreCreateWindow(CREATESTRUCT& cs)
{                                                                    (Breakpoint8)
 if (cs.lpszClass == NULL)
 {
  VERIFY(AfxDeferRegisterClass(AFX_WNDFRAMEORVIEW_REG));
  //AfxDeferRegisterClass(AFX_WNDFRAMEORVIEW_REG)判断当前的窗口类有没有
  //注册,没有就注册
  cs.lpszClass = _afxWndFrameOrView;  // COLOR_WINDOW background
 }

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

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

return TRUE;
}
-------------------------------------------------------------------------------------
AFXIMPL.h
-------------------------------------------------------------------------------------
#define AfxDeferRegisterClass(fClass) AfxEndDeferRegisterClass(fClass)
-------------------------------------------------------------------------------------
 <9> BOOL CFrameWnd::PreCreateWindow(CREATESTRUCT& cs)         (Breakpoint8)

WINCORE.cpp
-------------------------------------------------------------------------------------
BOOL CWnd::CreateEx(DWORD dwExStyle, LPCTSTR lpszClassName,
 LPCTSTR lpszWindowName, DWORD dwStyle,
 int x, int y, int nWidth, int nHeight,
 HWND hWndParent, HMENU nIDorHMenu, LPVOID lpParam)
{                                                                      (Breakpoint9)
 // allow modification of several common create parameters
 CREATESTRUCT cs;
 cs.dwExStyle = dwExStyle;
 cs.lpszClass = lpszClassName;
 ..............................
 if (!PreCreateWindow(cs))      //PreCreateWindow是一个虚函数
 {
  PostNcDestroy();
  return FALSE;
 }
 ...............................
}
-------------------------------------------------------------------------------------
BOOL CWnd::CreateEx(DWORD dwExStyle, LPCTSTR lpszClassName,
  LPCTSTR lpszWindowName, DWORD dwStyle,
  const RECT& rect, CWnd* pParentWnd, UINT nID,
  LPVOID lpParam /* = NULL */)     //调用上面的CreateEx函数
{                                                                      (Breakpoint10)
 return CreateEx(dwExStyle, lpszClassName, lpszWindowName, dwStyle,
  rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top,
  pParentWnd->GetSafeHwnd(), (HMENU)nID, lpParam);
}
-------------------------------------------------------------------------------------

WINFRM.CPP
-------------------------------------------------------------------------------------
BOOL CFrameWnd::Create(LPCTSTR lpszClassName,
 LPCTSTR lpszWindowName,
 DWORD dwStyle,
 const RECT& rect,
 CWnd* pParentWnd,
 LPCTSTR lpszMenuName,
 DWORD dwExStyle,
 CCreateContext* pContext)
{                                                                  (Breakpoint11)         
 ..........................
 if (!CreateEx(dwExStyle, lpszClassName, lpszWindowName, dwStyle,
  rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top,
  pParentWnd->GetSafeHwnd(), hMenu, (LPVOID)pContext)) //调用上面的
 {                                                            //CreateEx函数
  TRACE0("Warning: failed to create CFrameWnd./n");
  if (hMenu != NULL)
   DestroyMenu(hMenu);
  return FALSE;
 }
 ....................................................
}
-----------------------------------------------------------------------------------
7.显示更新窗口
  Test.CPP
-----------------------------------------------------------------------------------
 m_pMainWnd->ShowWindow(SW_SHOW);
 m_pMainWnd->UpdateWindow();      //m_pMainWnd指向框架窗口对象的指针
-----------------------------------------------------------------------------------

8.消息循环
THRDCORE.CPP
-----------------------------------------------------------------------------------
int CWinThread::Run()
{
 ASSERT_VALID(this);

// for tracking the idle time state
 BOOL bIdle = TRUE;
 LONG lIdleCount = 0;

// acquire and dispatch messages until a WM_QUIT message is received.
 for (;;)
 {
  // phase1: check to see if we can do idle work
  while (bIdle &&
   !::PeekMessage(&m_msgCur, NULL, NULL, NULL, PM_NOREMOVE))
  {
   // call OnIdle while in bIdle state
   if (!OnIdle(lIdleCount++))
    bIdle = FALSE; // assume "no idle" state
  }

// phase2: pump messages while available
  do
  {
   // pump message, but quit on WM_QUIT
   if (!PumpMessage())
    return ExitInstance();

// reset "no idle" state after pumping "normal" message
   if (IsIdleMessage(&m_msgCur))
   {
    bIdle = TRUE;
    lIdleCount = 0;
   }

} while (::PeekMessage(&m_msgCur, NULL, NULL, NULL, PM_NOREMOVE));
 }

ASSERT(FALSE);  // not reachable
}
------------------------------------------------------------------------------------
BOOL CWinThread::PumpMessage()
{
 ASSERT_VALID(this);

if (!::GetMessage(&m_msgCur, NULL, NULL, NULL))
 {
#ifdef _DEBUG
  if (afxTraceFlags & traceAppMsg)
   TRACE0("CWinThread::PumpMessage - Received WM_QUIT./n");
  m_nDisablePumpCount++; // application must die
   // Note: prevents calling message loop things in 'ExitInstance'
   // will never be decremented
#endif
  return FALSE;
 }

#ifdef _DEBUG
 if (m_nDisablePumpCount != 0)
 {
  TRACE0("Error: CWinThread::PumpMessage called when not permitted./n");
  ASSERT(FALSE);
 }
#endif

#ifdef _DEBUG
 if (afxTraceFlags & traceAppMsg)
  _AfxTraceMsg(_T("PumpMessage"), &m_msgCur);
#endif

// process this message

if (m_msgCur.message != WM_KICKIDLE && !PreTranslateMessage(&m_msgCur))
 {
  ::TranslateMessage(&m_msgCur);
  ::DispatchMessage(&m_msgCur);
 }
 return TRUE;
}
----------------------------------------------------------------------------------

9.窗口过程 (在AfxEndDeferRegisterClass函数中设置)
 wndcls.lpfnWndProc = DefWindowProc;   //缺省的窗口过程

10.在MFC如何整合CMainFrm类,CTestView类,CTestDoc类?
   在
 BOOL CTestApp::InitInstance()中:
------------------------------------------------------------------------------------
CSingleDocTemplate* pDocTemplate;     //定义一个单文档的类模板
 pDocTemplate = new CSingleDocTemplate(
  IDR_MAINFRAME,
  RUNTIME_CLASS(CTestDoc),       //通过单文档的模板组合在一起
  RUNTIME_CLASS(CMainFrame),       // main SDI frame window
  RUNTIME_CLASS(CTestView));
 AddDocTemplate(pDocTemplate);           //增加到文档模板中
-------------------------------------------------------------------------------------

11.窗口与C++类的关系

窗口销毁,C++的对象不一定销毁,窗口与C++窗口类的关系只不过是窗口类保存了窗口的句柄.
12.CButton
   m_btn.Create("维新",WS_CHILD | WS_VISIBLE | BS_AUTO3STATE,
  CRect(0,0,100,100),/*GetParent(),*/this,123);
   CButton的窗口风格 WS_CHILD | WS_VISIBLE | BS_AUTO3STATE
   CTestView的父窗口是CMainFrm,在CTestView里面使用GetParent()函数,得到CMainFrm对象的
   指针.

孙鑫VC学习笔记:第三讲 MFC应用程序框架相关推荐

  1. 孙鑫VC++学习笔记(转载至程序员之家--虎非龙)[11--15] .

    第11课 1.创建4个菜单,为其添加消息响应,用成员变量保存绘画类型.添加LButtonDown和Up消息. 2.当窗口重绘时,如果想再显示原先画的数据,则需要保存数据.为此创建一个新类来记录绘画类型 ...

  2. 孙鑫VC++学习笔记(转载至程序员之家--虎非龙)[11--15]

    第11课 1.创建4个菜单,为其添加消息响应,用成员变量保存绘画类型.添加LButtonDown和Up消息. 2.当窗口重绘时,如果想再显示原先画的数据,则需要保存数据.为此创建一个新类来记录绘画类型 ...

  3. 孙鑫VC学习笔记:第七讲

    七.对话框 2006年8月5日 14:25 因为笔记是用OneNote做的,上传以后为看不到图片,于是我截图放到相册上面, 相册地址为:http://photo.163.com/photos/good ...

  4. mfc编程 孙鑫_孙鑫VC++视频教程笔记-(3)MFC程序框架的剖析 附1-SDI程序流程图

    1,寻找WinMain人口: 在安装目录下找到MFC文件夹下的SRC文件夹,SRC下是MFC源代码. 路径:MFC|SRC|APPMODUL.CPP: _tWinMain(HINSTANCE hIns ...

  5. 孙鑫VC学习系列教程

    教程简介 1.循序渐进 从Win32SDK编程开始讲解,帮助大家理解掌握Windows编程的核心 -- 消息循环机制. 2.通俗易懂 编程语言枯燥难懂,然而通过孙鑫老师形象化的讲解,Windows和M ...

  6. 孙鑫VC++讲座笔记-(6)菜单编程

    1,弹出菜单(Pop-up)是不能用来作命令响应的. 2,MFC中菜单项消息如果利用ClassWizard来对菜单项消息分别在上述四个类中进行响应,则菜单消息传递顺序:View类--Doc类--CMa ...

  7. 孙鑫VC++深入详解第三章学习笔记

    第三章 3.1创建MFC AppWizard 如何利用vs2019创建MFC应用见参考文献[1] 需要注意的地方有 [1] 创建MFC单文档应用程序 [2]开启类视图窗口 3.2基于MFC的程序框架剖 ...

  8. 孙鑫VC++深入详解第二章学习笔记

    第二章 掌握C++ 2.1 从结构到类 2.1.1 结构体的定义 C++相比于C的特性:封装性.继承性.多态性: 对象具有状态和行为,状态保存在成员变量中,行为通过函数实现: 标准输入输出流对象:ci ...

  9. 孙鑫VC++深入详解第一章学习笔记

    第一章 Windows程序内部运行机制 1.1 API和SDK API:Windows操作系统提供给应用程序编程的接口. SDK(软件开发包):用于开发的所有资源的集合. 1.2 窗口和句柄 窗口 句 ...

  10. VC学习笔记:简单绘图

    VC学习笔记:简单绘图 SkySeraph Oct.29th 2009  HQU Email-zgzhaobo@gmail.com  QQ-452728574 Latest Modified Date ...

最新文章

  1. Spring5源码 - 11 Spring事件监听机制_源码篇
  2. mysql 5.7 速度很快_MySQL5.7速度比MySQL5.6快3倍
  3. [Servlet]研究ServletContext对象
  4. 国内首家,腾讯云云开发“全家桶”来了
  5. ROS与Android的通信
  6. NTT通信公司在大阪开通运营容灾数据中心
  7. win7如何安装mysql5.7_Win7下安装MySQL5.7.16过程记录
  8. JavaWeb项目实战一(Servlet+Jsp项目项目搭建及登录界面)
  9. 中兴威武3android驱动,中兴威武3
  10. 信息系统管理——项目立项管理(详细可行性研究的结构)
  11. 程序人生 | 文艺程序员使用代码发展诗歌
  12. 解决Android手机开发者选项经常自动关闭的问题
  13. 中英文切换_值得收藏|不重装软件实现ArcGIS中英文版本之间切换
  14. 吐血整理公众号推文制作技巧
  15. 趋势跟踪系统的形成历程
  16. 2020上半年数据分析人才及CDA持证人行业报告
  17. IOS 调用第三方地图APP导航
  18. 年终思路梳理(三)——工业互联网
  19. 机器学习中的置信区间与置信度
  20. 什么是堆、栈?堆和栈的区别

热门文章

  1. 中小企业应该将云存储用于主数据吗?
  2. 《Android程序设计》一3.8 Android应用打包:.apk文件
  3. Pywinauto在Windows Twain Driver自动化测试中的应用研究
  4. 经典中的博弈:第一章 C++的Hello,World!
  5. Android学习笔记--项目框架介绍
  6. Wordle是优秀的信息可视化吗?如何真正使用Wordle?
  7. .NET应用服务器(中间件)来到
  8. c++ string字符串翻转
  9. Kafka+Spark Streaming+Redis实时系统实践
  10. 解决Android 4.0以上版本中OptionsMenu菜单不显示ICON图标的问题