VC驿站

 找回密码
 加入驿站

QQ登录

只需一步,快速开始

搜索
查看: 432|回复: 0

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

[复制链接]
08_avatar_middle
最佳答案
10 
在线会员 发表于 2022-4-2 21:22:30 | 显示全部楼层 |阅读模式
本帖最后由 SummerGull 于 2022-4-2 21:39 编辑
  1. int AFXAPI AfxWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
  2.         _In_ LPTSTR lpCmdLine, int nCmdShow)
  3. {
  4.         CWinThread* pThread = AfxGetThread();//获取this指针呢 就是theApp
  5.         CWinApp* pApp = AfxGetApp();//获取this指针呢 就是theApp
  6. //上面有这两个函数的解释

  7. pApp->InitApplication();//初始化程序
  8. pThread->InitInstance();//这是个虚函数,初始化程序 进入我们自己重写的函数
  9. //上面两句代码执行失败都是走 goto InitFailure;

  10. nReturnCode = pThread->Run();//这里其实是消息循环
  11. return nReturnCode;
  12. }
复制代码


创建窗口
接着从下面函数继续执行

pThread->InitInstance();
进入自己重写的虚函数
  1. pThread->InitInstance()
  2. {
  3. MyWnd* pFrame = new MyWnd();
  4.         m_pMainWnd = pFrame;
  5. //这里是 theApp 成员变量 赋值 也就是主窗口交给成员变量

  6.         pFrame->Create(NULL, "Window");
  7. //执行的是 CFrameWnd::Create()
  8. //又执行了CreateEx 也是CFraneWnd的函数
  9. //提取代码看有用的信息

  10.         pFrame->ShowWindow(SW_SHOW);
  11.         pFrame->UpdateWindow();
  12.         return TRUE;
  13. }
复制代码


CFrameWnd::Create()函数
  1. BOOL CFrameWnd::Create(LPCTSTR lpszClassName,
  2.         LPCTSTR lpszWindowName,
  3.         DWORD dwStyle,
  4.         const RECT& rect,
  5.         CWnd* pParentWnd,
  6.         LPCTSTR lpszMenuName,
  7.         DWORD dwExStyle,
  8.         CCreateContext* pContext)
  9. {
  10.         m_strTitle = lpszWindowName;    // save title for later

  11.         if (!CreateEx(dwExStyle, lpszClassName, lpszWindowName, dwStyle,
  12.                 rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top,
  13.                 pParentWnd->GetSafeHwnd(), hMenu, (LPVOID)pContext))
  14.         {
  15.                 TRACE(traceAppMsg, 0, "Warning: failed to create CFrameWnd.\n");
  16.                 if (hMenu != NULL)
  17.                         DestroyMenu(hMenu);
  18.                 return FALSE;
  19.         }

  20.         return TRUE;
  21. }
复制代码

CWnd::CreateEx()函数
  1. BOOL CWnd::CreateEx(DWORD dwExStyle, LPCTSTR lpszClassName,
  2.         LPCTSTR lpszWindowName, DWORD dwStyle,
  3.         int x, int y, int nWidth, int nHeight,
  4.         HWND hWndParent, HMENU nIDorHMenu, LPVOID lpParam)
  5. {
  6.         
  7.         CREATESTRUCT cs;
  8.         cs.dwExStyle = dwExStyle;
  9.         cs.lpszClass = lpszClassName;
  10.         cs.lpszName = lpszWindowName;
  11.         cs.style = dwStyle;
  12.         cs.x = x;
  13.         cs.y = y;
  14.         cs.cx = nWidth;
  15.         cs.cy = nHeight;
  16.         cs.hwndParent = hWndParent;
  17.         cs.hMenu = nIDorHMenu;
  18.         cs.hInstance = AfxGetInstanceHandle();
  19. //这里的AfxGetInstanceHandle() == afxCurrentInstanceHandle
  20. //afxCurrentInstanceHandle == AfxGetModuleState()->m_hCurrentInstanceHandle
  21.         cs.lpCreateParams = lpParam;

  22. //CREATESTRUCT 这个结构 里面有个lpszClassName是为空的。但是这是不允许的。
  23. //下面的CreateWindowEx就快要创建窗口了 如果 lpszClassName为空肯定会出错
  24. //也就是说 下面的 PreCreateWindow(cs) 或 AfxHookWindowCreate(this);
  25. //一定会把 lpszClassName补上。
  26. //但是AfxHookWindowCreate(this); 没有cs参数,PreCreateWindow(cs)带了
  27. //执行步骤在这里总结为:
  28. //1、PreCreateWindow(cs) 进入下面函数
  29. //2、VERIFY(AfxDeferRegisterClass(AFX_WNDFRAMEORVIEW_REG));//注册窗口类
  30. //3、上面函数 注册窗口类时wndcls.lpfnWndProc = DefWindowProc;会带来问题。
  31. //4、AfxRegisterWithIcon()函数协助上面函数注册窗口类
  32. //5、上面函数使用API注册窗口
  33. //6、cs.lpszClass = _afxWndFrameOrView;//注册完赋值,这个就是类名 上个函数注册的
  34. //7、使用 AfxHookWindowCreate(this); 解决问题 消息处理过程HOOK为 MFC提供的
  35. //需要在该函数文档中搜索_AfxCbtFilterHook() 函数并下断点
  36. //8、产生窗口CreateWindowEx函数调用API创建窗口
  37. //创建完毕立马跳转_AfxCbtFilterHook()函数过程中
  38. //9、跳转HOOK函数_AfxCbtFilterHook()执行代码

  39.         if (!PreCreateWindow(cs))//下面有函数展开信息 这个也是个虚函数
  40.         {
  41.                 PostNcDestroy();
  42.                 return FALSE;
  43.         }

  44.         AfxHookWindowCreate(this);
  45. //这个函数将解决 wndcls.lpfnWndProc = DefWindowProc;带来的问题。
  46.         HWND hWnd = CreateWindowEx(cs.dwExStyle, cs.lpszClass,
  47.                         cs.lpszName, cs.style, cs.x, cs.y, cs.cx, cs.cy,
  48.                         cs.hwndParent, cs.hMenu, cs.hInstance, cs.lpCreateParams);

  49. #ifdef _DEBUG
  50.         if (hWnd == NULL)
  51.         {
  52.                 TRACE(traceAppMsg, 0, "Warning: Window creation failed: GetLastError returns 0x%8.8X\n",
  53.                         GetLastError());
  54.         }
  55. #endif

  56.         if (!AfxUnhookWindowCreate())
  57.                 PostNcDestroy();        // cleanup if CreateWindowEx fails too soon

  58.         if (hWnd == NULL)
  59.                 return FALSE;
  60.         ASSERT(hWnd == m_hWnd); // should have been set in send msg hook
  61.         return TRUE;
  62. }
复制代码

CFrameWnd::PreCreateWindow
  1. BOOL CFrameWnd::PreCreateWindow(CREATESTRUCT& cs)
  2. {
  3.         if (cs.lpszClass == NULL)
  4.         {
  5.                 VERIFY(AfxDeferRegisterClass(AFX_WNDFRAMEORVIEW_REG));
  6. //这个函数里面是注册窗口类的
  7.                 cs.lpszClass = _afxWndFrameOrView;  // COLOR_WINDOW background
  8. //这个赋值是关键 把窗口类名赋值给了 cs里面的 类名称
  9.         }

  10.         if (cs.style & FWS_ADDTOTITLE)
  11.                 cs.style |= FWS_PREFIXTITLE;

  12.         cs.dwExStyle |= WS_EX_CLIENTEDGE;

  13.         return TRUE;
  14. }
复制代码

AfxEndDeferRegisterClass
  1. BOOL AFXAPI AfxEndDeferRegisterClass(LONG fToRegister)
  2. {
  3. AFX_MODULE_STATE* pModuleState = AfxGetModuleState();
  4.         fToRegister &= ~pModuleState->m_fRegisteredClasses;
  5.         if (fToRegister == 0)
  6.                 return TRUE;

  7.         LONG fRegisteredClasses = 0;

  8.         // common initialization
  9.         WNDCLASS wndcls;
  10.         memset(&wndcls, 0, sizeof(WNDCLASS));   // start with NULL defaults
  11.         wndcls.lpfnWndProc = DefWindowProc;
  12. //这里也有一个问题,为什么要给 默认窗口处理函数处理
  13. //MFC的窗口处理函数没有来处理!!!
  14.         wndcls.hInstance = AfxGetInstanceHandle();
  15.         wndcls.hCursor = afxData.hcurArrow;

  16. wndcls.style = CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW;
  17.         wndcls.hbrBackground = (HBRUSH) (COLOR_WINDOW + 1);

  18.         if (_AfxRegisterWithIcon(&wndcls, _afxWndFrameOrView, AFX_IDI_STD_FRAME))
  19. //第二个参数就是 MFC帮定义好的 类名
  20.                 fRegisteredClasses |= AFX_WNDFRAMEORVIEW_REG;
  21. }
复制代码

_AfxRegisterWithIcon()函数
  1. AFX_STATIC BOOL AFXAPI _AfxRegisterWithIcon(WNDCLASS* pWndCls,
  2.         LPCTSTR lpszClassName, UINT nIDIcon)
  3. {
  4.         pWndCls->lpszClassName = lpszClassName;
  5. //这里的窗口类名赋值了
  6.         HINSTANCE hInst = AfxFindResourceHandle(
  7.                 ATL_MAKEINTRESOURCE(nIDIcon), ATL_RT_GROUP_ICON);
  8.         if ((pWndCls->hIcon = ::LoadIconW(hInst, ATL_MAKEINTRESOURCEW(nIDIcon))) == NULL)
  9.         {
  10.                 // use default icon
  11.                 pWndCls->hIcon = ::LoadIcon(NULL, IDI_APPLICATION);
  12.         }
  13.         return AfxRegisterClass(pWndCls);
  14. //这个函数执行RegisterClass(lpWndClass) 在执行 API注册函数 注册类
  15. }
复制代码

AfxHookWindowCreate()函数
_AfxCbtFilterHook()钩子函数
  1. void AFXAPI AfxHookWindowCreate(CWnd* pWnd)
  2. {
  3.         SetWindowsHookEx(WH_CBT,
  4.                         _AfxCbtFilterHook, NULL, ::GetCurrentThreadId());
  5. //HOOK 窗口的创建过程。
  6. //也就是说窗口创建完毕后直接跳转_AfxCbtFilterHook()函数!!
  7. pThreadState->m_pWndInit = pWnd;
  8. //_module_thread 保存窗口对象指针
  9. }


  10. _AfxCbtFilterHook(int code, WPARAM wParam, LPARAM lParam)
  11. {
  12. WNDPROC afxWndProc = AfxGetAfxWndProc();// ==  &AfxWndProc
  13.         oldWndProc = (WNDPROC)SetWindowLongPtr(hWnd, GWLP_WNDPROC,(DWORD_PTR)afxWndProc);
  14. }

  15. NDPROC AFXAPI AfxGetAfxWndProc()
  16. {
  17. #ifdef _AFXDLL
  18.         return AfxGetModuleState()->m_pfnAfxWndProc;
  19. #else
  20.         return &AfxWndProc;
  21. #endif
  22. }
复制代码


nReturnCode = pThread->Run();//这里其实是消息循环
接下来是MFC的消息映射原理。




上一篇:浅谈MFC框架内部结构 一
下一篇:浅谈MFC框架内部结构 三

本帖被以下淘专辑推荐:

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

本版积分规则

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

关闭

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

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

GMT+8, 2023-9-29 16:40

Powered by CcTry.CoM

© 2009-2021 cctry.com

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