VC驿站

 找回密码
 加入驿站

QQ登录

只需一步,快速开始

搜索
查看: 140|回复: 0

[分享] 浅谈MFC框架内部结构 五

[复制链接]
08_avatar_middle
最佳答案
10 
在线会员 发表于 2022-4-4 22:55:42 | 显示全部楼层 |阅读模式
本帖最后由 SummerGull 于 2022-4-4 22:59 编辑

SID单文档是如何创建的
这里需要用到一个VS的插件叫做visual assist助手,因为VSF12(转到定义)并不能准确的到达指定函数过程中下断点,助手的alt+g 就可以过去。
InitInstance()下找到 单文档模板对象,并进入构造函数中下断点。
  1. CSingleDocTemplate* pDocTemplate;
  2.         pDocTemplate = new CSingleDocTemplate(
  3.                 IDR_MAINFRAME,
  4.                 RUNTIME_CLASS(CMFCApplication8Doc),
  5.                 RUNTIME_CLASS(CMainFrame),       // 主 SDI 框架窗口
  6.                 RUNTIME_CLASS(CMFCApplication8View));
复制代码
参数1、菜单资源ID
参数2、文档类对象
参数3、主框架窗口
参数4、视图窗口对象
浅谈MFC框架内部结构 五
F5开始调试断点停留在21行代码,进入父类CDocTemplate()的构造函数
  1. CDocTemplate::CDocTemplate(UINT nIDResource, CRuntimeClass* pDocClass,
  2.         CRuntimeClass* pFrameClass, CRuntimeClass* pViewClass)
  3. {
  4.         m_nIDResource = nIDResource;
  5.         m_pDocClass = pDocClass;
  6.         m_pFrameClass = pFrameClass;
  7.         m_pViewClass = pViewClass;
  8. m_bAutoDelete = TRUE;   // usually allocated on the heap
  9. LoadTemplate();
  10. }
复制代码
关键代码段当前this指针为*pDocTemplate
接着执行下面代码:
AddDocTemplate(pDocTemplate);
  1. void CWinApp::AddDocTemplate(CDocTemplate* pTemplate)
  2. {
  3.         if (m_pDocManager == NULL)
  4.                 m_pDocManager = new CDocManager;
  5. //m_pDocManager是 theApp的一个成员变量

  6.         m_pDocManager->AddDocTemplate(pTemplate);
  7. }
复制代码
  1. void CDocManager::AddDocTemplate(CDocTemplate* pTemplate)
  2. {
  3.         pTemplate->LoadTemplate();
  4.         m_templateList.AddTail(pTemplate);
  5. //这里的this指针是m_pDocManager
  6. }
复制代码
以上代码总结一下做了什么事情:
* pDocTemplate->
m_pOnlyDoc = NULL;
m_nIDResource = nIDResource;
                                m_pDocClass = pDocClass;
                                m_pFrameClass = pFrameClass;
                                m_pViewClass = pViewClass;
m_bAutoDelete = TRUE;
theApp->
m_pDocManager->AddDocTemplate(pTemplate);//就是上面的* pDocTemplate
->m_templateList.AddTail(pTemplate);
代码:ProcessShellCommand(cmdInfo)执行
  1. 以上代码总结一下做了什么事情:
  2. * pDocTemplate->
  3. m_pOnlyDoc = NULL;
  4. m_nIDResource = nIDResource;
  5.                                 m_pDocClass = pDocClass;
  6.                                 m_pFrameClass = pFrameClass;
  7.                                 m_pViewClass = pViewClass;
  8. m_bAutoDelete = TRUE;
  9. theApp->
  10. m_pDocManager->AddDocTemplate(pTemplate);//就是上面的* pDocTemplate
  11. ->m_templateList.AddTail(pTemplate);

  12. 代码:ProcessShellCommand(cmdInfo)执行
复制代码
AfxGetApp()->OnCmdMsg(ID_FILE_NEW, 0, NULL, NULL);
这条代码发送产生command消息从而执行该消息:
case AfxSigCmd_v:
                // normal command or control notification
                ASSERT(CN_COMMAND == 0);        // CN_COMMAND same as BN_CLICKED
                ASSERT(pExtra == NULL);
                (pTarget->*mmf.pfnCmd_v_v)();
                break;
执行函数名:OnFileNew();
m_pDocManager->OnFileNew();//属于theApp的文档管理类成员变量
继续执行:CDocTemplate* pTemplate = (CDocTemplate*)m_templateList.GetHead();
theApp->m_pDocManager->m_templateList//因为只有一条链表 获取head = tail
执行代码:pTemplate->OpenDocumentFile(NULL);
执行代码:return OpenDocumentFile(lpszPathName, TRUE, bMakeVisible);
  1. OpenDocumentFile(LPCTSTR lpszPathName, BOOL bAddToMRU, BOOL bMakeVisible)
  2. {
  3. CDocument* pDocument = NULL;
  4.         CFrameWnd* pFrame = NULL;

  5.         BOOL bCreated = FALSE;      // => doc and frame created
  6. BOOL bWasModified = FALSE;

  7. pDocument = CreateNewDocument();
  8. {
  9. CDocument* pDocument = (CDocument*)m_pDocClass->CreateObject();
  10. //这里的m_pDocClass是* pDocTemplate的成员变量

  11. AddDocument(CDocument* pDocument)
  12. {
  13. CDocTemplate::AddDocument(pDocument);
  14. {
  15. pDocument->m_pDocTemplate = this;
  16. }
  17.         m_pOnlyDoc = pDocument;
  18. //* pDocTemplate->m_pOnlyDoc = pDocument;
  19. }
  20. return pDocument;
  21. }
  22. bCreated = TRUE;
  23. //上面是创建了一份 pDocument 的对象

  24. pFrame = CreateNewFrame(pDocument, NULL);//创建一个主框架
  25. {//参数:CDocument* pDoc, CFrameWnd* pOther

  26. //下面结构体是关键
  27. CCreateContext context;
  28.                 context.m_pCurrentFrame = pOther;
  29.                 context.m_pCurrentDoc = pDoc;
  30.                 context.m_pNewViewClass = m_pViewClass;
  31. context.m_pNewDocTemplate = this;
  32. CFrameWnd* pFrame = (CFrameWnd*)m_pFrameClass->CreateObject();
  33. //* pDocTemplate->
  34. pFrame->LoadFrame(m_nIDResource,WS_OVERLAPPEDWINDOW | FWS_ADDTOTITLE,NULL, &context);//LoadFrame会通过 context去完成一些自动创建的工作
  35. {
  36. Create(lpszClass, strTitle, dwDefaultStyle, rectDefault,pParentWnd, ATL_MAKEINTRESOURCE(nIDResource), 0L, pContext)
  37. {
  38. CreateEx(.........., pContext)//立即发送Frame的WM_CREATE消息
  39. //该消息为取出 CCreateContext* pContext参数
  40. //CWnd* pView = pContext->m_pNewViewClass->CreateObject();
  41. //动态创建 视图窗口
  42. // pView->Create(..,pContext)
  43. //立即发送 视图WM_CREATE消息
  44. //CCreateContext* pContext = (CCreateContext*)lpcs->lpCreateParams;
  45. //视图WM_CREATE消息获取 指针
  46. //m_viewList.AddTail(pView);pDoc保存视图
  47. //pView->m_pDocument = this;视图变量保存 pDoc对象地址
  48. }
  49. }
  50. }
  51. }
复制代码
结束,以上是单文档程序的流程

HDCCDC/HWNDCWnd 都是如何关联的
  1. CWnd* pWndInit = pThreadState->m_pWndInit;
  2. //取得主窗口指针

  3. pWndInit->Attach(hWnd);//开始双向绑定
  4. {
  5. CHandleMap* pMap = afxMapHWND(TRUE); //MFC的映射类。无需关注
  6. pMap->SetPermanent(m_hWnd = hWnd, permOb);
  7. //这里的m_hWnd是类里面成员函数绑定窗口句柄
  8. {
  9. BOOL bEnable = AfxEnableMemoryTracking(FALSE);
  10.         m_permanentMap[(LPVOID)hWnd] = permOb;//permOb这个是主窗口类
  11. //这里的this指针就是 CHandleMap 映射类的
  12. //这里用句柄的值作为下标 显然是重载了[]符号
  13. //这样就形成了映射了
  14.         AfxEnableMemoryTracking(bEnable);
  15. }
  16. }
复制代码






上一篇:浅谈MFC框架内部结构 四
下一篇:正在阅读《Windows图形编程》

本帖被以下淘专辑推荐:

您需要登录后才可以回帖 登录 | 加入驿站 qq_login

本版积分规则

×【发帖 友情提示】
1、请回复有意义的内容,请勿恶意灌水;
2、纯数字、字母、表情等无意义的内容系统将自动删除;
3、若正常回复后帖子被自动删除,为系统误删的情况,请重新回复其他正常内容或等待管理员审核通过后会自动发布;
4、感谢您对VC驿站一如既往的支持,谢谢合作!

关闭

站长提醒上一条 /2 下一条

QQ|小黑屋|手机版|VC驿站 ( 辽ICP备09019393号-4 )|网站地图wx_jqr

GMT+8, 2022-5-18 17:22

Powered by CcTry.CoM

© 2009-2021 cctry.com

快速回复 返回顶部 返回列表