MFC方法

创建窗口过程:


1. AfxWinMain(hInstance, hPrevInstance, lpCmdLine, nCmdShow);     //MFC消息入口函数


2. AfxWinMain() 


3. if (!pThread->InitInstance()) 线程初始化 进去                             


4. pDocTemplate = new CSingleDocTemplate(
IDR_MAINFRAME,                   //单文档模板 ,1.菜单名称,2.文档,3框架,4视图
RUNTIME_CLASS(CDemoDoc),
RUNTIME_CLASS(CMainFrame),       // 主 SDI 框架窗口
RUNTIME_CLASS(CDemoView));


5. CDocTemplate::CDocTemplate 进去 然后按F11进基类的构造函数


6. LoadTemplate();  装载文档模板


7. void CDocTemplate::LoadTemplate() 跳出 逃到了第4步的继续


8. 现在在BOOL CDemoApp::InitInstance()里面 是第4步的继续 --> if (!ProcessShellCommand(cmdInfo)) 调度命令,相当于点击word打开 默认filenew新建  不让nothing  
====F1进去
   注册在这里!!


9. 在CWinApp::ProcessShellCommand(CCommandLineInfo& rCmdInfo)里面 找到 if (!AfxGetApp()->OnCmdMsg(ID_FILE_NEW, 0, NULL, NULL))
   这句话是发送一条消息,这条消息最终调用了OnFileNew();


10. void CWinApp::OnFileNew()  --> m_pDocManager->OnFileNew();进去


11. void CDocManager::OnFileNew()


12. pTemplate->OpenDocumentFile(NULL);  进去


13. CDocument* CSingleDocTemplate::OpenDocumentFile(LPCTSTR lpszPathName,


14. pDocument = CreateNewDocument();  创建了文档!!  以后有用


15. pFrame = CreateNewFrame(pDocument, NULL);  创建框架  进去


16. 在CDocTemplate::CreateNewFrame(CDocument* pDoc, CFrameWnd* pOther)里面
CFrameWnd* pFrame = (CFrameWnd*)m_pFrameClass->CreateObject();创建框架类对象 进入构造函数


17. CFrameWnd::CFrameWnd() 出去
    CMainFrame::CMainFrame() 我们可以确定在16里面创建的是CMainFrame这个对象,然后出去


18. 在CDocTemplate::CreateNewFrame(里面找到代码,其实是16的继续
if (!pFrame->LoadFrame(m_nIDResource,WS_OVERLAPPEDWINDOW | FWS_ADDTOTITLE,  NULL, &context))  进去


19. BOOL CFrameWnd::LoadFrame(UINT nIDResource, DWORD dwDefaultStyle,CWnd* pParentWnd, CCreateContext* pContext)


20. LPCTSTR lpszClass = GetIconWndClass(dwDefaultStyle, nIDResource);  进去  作用:在这个函数里面注册了窗口类,然后把窗口类的名称返回


21. HICON hIcon = ::LoadIcon(hInst, ATL_MAKEINTRESOURCE(nIDResource)); 加载图标


22. PreCreateWindow(cs);  因为这个方法是个虚函数,所以我们得根据this是谁才能判断调用的是哪个函数 现在的this是CMainFrame


23. BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs)  将来我们可以在这个函数里面设置窗口类的属性  很重要!!!  


24. BOOL CFrameWnd::PreCreateWindow(CREATESTRUCT& cs)  在这个函数里面设置了默认的样式,然后跳出,然后跳出,回到了第20步的继续


25. 在LPCTSTR CFrameWnd::GetIconWndClass(DWORD dwDefaultStyle,里面有代码 -->
WNDCLASS wndcls;
看这里:AfxCtxGetClassInfo(AfxGetInstanceHandle(), cs.lpszClass, &wndcls) && 判断类是否存在  进去找了一遍,没有发现注册的代码,继续往下走


26. 看这里:AfxRegisterWndClass(wndcls.style,wndcls.hCursor, wndcls.hbrBackground, hIcon);  


27. LPCTSTR AFXAPI AfxRegisterWndClass(UINT nClassStyle,
HCURSOR hCursor, HBRUSH hbrBackground, HICON hIcon)


28. if (::AfxCtxGetClassInfo(hInst, lpszName, &wndcls)) 制作窗口类的类名


29. 窗口注册的代码!! 终于找到了
wndcls.style = nClassStyle;
wndcls.lpfnWndProc = DefWindowProc;
wndcls.cbClsExtra = wndcls.cbWndExtra = 0;
wndcls.hInstance = hInst;
wndcls.hIcon = hIcon;
wndcls.hCursor = hCursor;
wndcls.hbrBackground = hbrBackground;
wndcls.lpszMenuName = NULL;
wndcls.lpszClassName = lpszName;


30. if (!AfxRegisterClass(&wndcls))  进去


31. BOOL AFXAPI AfxRegisterClass(WNDCLASS* lpWndClass)


32. if (!::AfxCtxRegisterClass(lpWndClass))  注册窗口类
   这里的注册跟win32里面的注册有一些区别!!!   终于找到了窗口类的注册的全部代码


33. 注册成功,开始穿越(穿越的时候把窗口类的名字带回去了)
BOOL CFrameWnd::LoadFrame(UINT nIDResource, DWORD dwDefaultStyle,
CWnd* pParentWnd, CCreateContext* pContext)
LPCTSTR lpszClass = GetIconWndClass(dwDefaultStyle, nIDResource);
------------------------------------------------------------------------------------------------------------------


34. if (!Create(lpszClass, strTitle, dwDefaultStyle, rectDefault,
  pParentWnd, ATL_MAKEINTRESOURCE(nIDResource), 0L, pContext))    进去看窗口创建的过程


35. BOOL CFrameWnd::Create(LPCTSTR lpszClassName,  


36. if (!CreateEx(dwExStyle, lpszClassName, lpszWindowName, dwStyle,    进去


37. BOOL CWnd::CreateEx(DWORD dwExStyle, LPCTSTR lpszClassName,        //创建工具菜单状态条之类的


38. CREATESTRUCT cs;
cs.dwExStyle = dwExStyle;
cs.lpszClass = lpszClassName;
cs.lpszName = lpszWindowName;
cs.style = dwStyle;
cs.x = x;
cs.y = y;
cs.cx = nWidth;
cs.cy = nHeight;
cs.hwndParent = hWndParent;
cs.hMenu = nIDorHMenu;
cs.hInstance = AfxGetInstanceHandle();
cs.lpCreateParams = lpParam;
这里的信息是用于创建窗口的!!!


39. if (!PreCreateWindow(cs))  第2次调用了CMainFrame::PreCreateWindow 为什么要两次调用PreCreateWindow?  //预创造窗口
       第一次调用: cs用于窗口类注册
       第二次调用: cs用于改变窗口风格调用一次




39.  AfxHookWindowCreate(this); 在这里下了窗口的钩子,最后把窗口的消息都钩到了AfxWndProc里面去处理了


40.  HWND hWnd = ::AfxCtxCreateWindowEx(cs.dwExStyle, cs.lpszClass,
窗口已经创建成功!!!!
重要:cs参数包含了窗口注册和窗口创建的基本信息
























消息走向:
1.  AfxWndProc(HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lParam)   MFC消息的入口点


2.  CWnd* pWnd = CWnd::FromHandlePermanent(hWnd);   把句柄变成对象


3.  AfxCallWndProc(pWnd, hWnd, nMsg, wParam, lParam);  调用处理函数


4.  LRESULT AFXAPI AfxCallWndProc(CWnd* pWnd, HWND hWnd, UINT nMsg,


5.  lResult = pWnd->WindowProc(nMsg, wParam, lParam);  消息从这里开始就面向对象了


6.  LRESULT CWnd::WindowProc(UINT message, WPARAM wParam, LPARAM lParam)


7.  if (!OnWndMsg(message, wParam, lParam, &lResult))


8.  BOOL CWnd::OnWndMsg(UINT message, WPARAM wParam, LPARAM lParam, LRESULT* pResult)


9.  if (message == WM_COMMAND)


10. if (message == WM_NOTIFY)


11. 标准消息怎么办  while(){for(){}}






命令传递
1.  if (OnCommand(wParam, lParam))


2.  BOOL CWnd::OnCommand(WPARAM wParam, LPARAM lParam)  命令消息都会走这个,命令消息的对象可能是FrameWnd


3.  OnCmdMsg(nID, CN_UPDATE_COMMAND_UI, &state, NULL);  这个方法是一个虚函数,他会调用谁了


4.  BOOL CFrameWnd::OnCmdMsg(UINT nID, int nCode, void* pExtra,  首先走了CFrameWnd::OnCmdMsg


5.  有三个分支
    5.1 CView* pView = GetActiveView();  View
    5.2 if (CWnd::OnCmdMsg(nID, nCode, pExtra, pHandlerInfo))  --> CCmdTarget::OnCmdMsg
    5.3 if (pApp != NULL && pApp->OnCmdMsg(nID, nCode, pExtra, pHandlerInfo))


6.  走CView::OnCmdMsg  有两个分支
    6.1 if (CWnd::OnCmdMsg(nID, nCode, pExtra, pHandlerInfo))  自己
    6.2 return m_pDocument->OnCmdMsg(nID, nCode, pExtra, pHandlerInfo);


7.  走CDocument::OnCmdMsg  有两个分支
    7.1 if (CCmdTarget::OnCmdMsg(nID, nCode, pExtra, pHandlerInfo)) 自己
    7.2 m_pDocTemplate->OnCmdMsg(nID, nCode, pExtra, pHandlerInfo))




命令消息的传递过程:   CView  -->  CDocument  -->  CDocTemplate  -->  CFrameWnd  -->  CWinApp
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
很经典的MFC教程。 目 录 译者序 前言 第一部分 基础知识 第1章 窗口 2 1.1 窗口和API环境 2 1.1.1 三种类型窗口 2 1.1.2 客户区和非客户区 3 1.2 窗口和MFC环境 4 1.3 怎样应用MFC创建一个窗口 5 1.4 怎样使用MFC销毁一个窗口 9 1.4.1 捆绑到一个已有的窗口 9 1.4.2 窗口类 10 1.4.3 窗口进程 10 1.5 怎样使用MFC创建一个窗口类 11 1.5.1 使用AfxRegisterWndClass () 函数注册一个窗口类 11 1.5.2 使用AfxRegisterClass ()函数 创建一个窗口类 12 1.6 怎样销毁一个MFC窗口类 14 1.7 厂商安装的窗口类 14 1.8 其他类型窗口 15 1.9 桌面窗口 16 1.10 小结 16 第2章 类 18 2.1 基类 18 2.1.1 CObject 18 2.1.2 CCmdTarget 19 2.1.3 CWnd 19 2.2 应用程序、框架、文档和视图类 19 2.2.1 CWinApp(O/C/W) 20 2.2.2 CView (O/C/W) 21 2.3 其他用户界面类 22 2.3.1 通用控件类 23 2.3.2 菜单类 23 2.3.3 对话框类 24 2.3.4 控制条类 24 2.3.5 属性类 25 2.4 绘图类 25 2.4.1 设备环境类 25 2.4.2 图形对象类 25 2.5 文件类 26 2.6 数据库类 26 2.6.1 ODBC类 26 2.6.2 DAO类 27 2.7 数据集类 27 2.8 其他数据类 27 2.9 通信类 28 2.10 其他类 29 2.11 小结 31 第3章 消息处理 32 3.1 发送或寄送一个消息 32 3.1.1 发送一个消息 32 3.1.2 寄送一个消息 32 3.1.3 发送一个消息与寄送一个消息 的比较 32 3.2 怎样使用MFC发送一个消息 33 3.3 怎样用MFC寄送一个消息 33 3.4 三种类型的消息 34 3.4.1 窗口消息 34 3.4.2 命令消息 34 3.4.3 控件通知 34 3.5 MFC怎样接收一个寄送的消息 36 3.6 MFC怎样处理一个接收到的消息 36 3.7 处理用户界面的对象 44 3.8 创建自定义窗口消息 45 3.8.1 静态分配的窗口消息 45 3.8.2 动态分配的窗口消息 46 3.9 重定向消息 47 3.9.1 子分类和超分类 47 3.9.2 用MFC子分类窗口 48 3.9.3 重载OnCmdMsg ( ) 49 3.9.4 使用SetWindowsHookEx ( ) 49 3.9.5 使用SetCapture ( ) 49 3.9.6 专有的消息泵 50 3.10 小结 50 第4章 绘图 51 4.1 设备环境 51 4.2 在MFC环境中创建一个设备环境 52 4.2.1 屏幕 52 4.2.2 打印机 53 4.2.3 内存 54 4.2.4 信息 54 4.3 绘图例程 55 4.3.1 画点 55 4.3.2 画线 55 4.3.3 画形状 55 4.3.4 形状填充和翻转 55 4.3.5 滚动 56 4.3.6 绘制文本 56 4.3.7 绘制位图和图标 56 4.4 绘图属性 56 4.4.1 设备环境属性 57 4.4.2 画线属性 58 4.4.3 形状填充属性 58 4.4.4 文本绘制属性 58 4.4.5 映像模式 59 4.4.6 调色板属性 62 4.4.7 混合属性 62 4.4.8 剪裁属性 63 4.4.9 位图绘制属性 64 4.5 元文件和路径 65 4.5.1 元文件 65 4.5.2 路径 66 4.6 颜色和调色板 66 4.6.1 抖动色 67 4.6.2 未经抖动色 67 4.6.3 系统调色板 67 4.6.4 使用系统调色板 68 4.6.5 动画色 71 4.7 控制什么时候在哪里绘图 71 4.7.1 处理WM_PAINT 71 4.7.2 只绘制被无效化的区域 72 4.7.3
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值