• 五、MFC视图窗口和文档


    一、视图窗口

            提供一个用于显示数据的窗口

    1、视图窗口相关类

            CView及其子类,父类为CWnd类,封装了关于视图窗口的各种操作,以及和文档类的数据交互

    2、视图窗口的使用

    (1)定义了一个自己的视图类(CMyView),派生自CView,并重写父类成员纯虚函数void OnDraw(CDC* pDC),可以用于绘图

    (2)其余框架类和应用类程序代码不变

    (3)处理框架的WM_CREATE消息时,定义CMyView类对象,并调用Create函数创建视图窗口,视图窗口的ID为 AFX_IDW_PANE_FIRST

    3、创建项目(MFCView)

    (1)创建项目

    (2)编写程序

    1. #include
    2. #include "resource.h"
    3. class CMyView:public CView
    4. {
    5. DECLARE_MESSAGE_MAP()
    6. public:
    7. virtual void OnDraw(CDC* pDC);
    8. afx_msg void OnPaint();
    9. afx_msg void OnNew();
    10. };
    11. BEGIN_MESSAGE_MAP(CMyView, CView)
    12. //ON_WM_PAINT()
    13. ON_COMMAND(ID_NEW, OnNew)
    14. END_MESSAGE_MAP()
    15. //父类处理绘图消息时会调用OnDraw,当本类由绘图消息处理,则OnDraw不会被调用
    16. void CMyView::OnDraw(CDC* pDC)
    17. {
    18. pDC->TextOut(100, 100, "CMyView::OnDraw");
    19. }
    20. void CMyView::OnPaint()
    21. {
    22. PAINTSTRUCT ps = {0};
    23. HDC hdc = ::BeginPaint(m_hWnd, &ps);
    24. ::TextOutA(hdc, 200, 200, "CMyView::OnPaint", strlen("CMyView::OnPaint"));
    25. ::EndPaint(m_hWnd, &ps);
    26. }
    27. void CMyView::OnNew()
    28. {
    29. AfxMessageBox("视图类处理了OnNew消息");
    30. }
    31. class CMyFrameWnd:public CFrameWnd
    32. {
    33. DECLARE_MESSAGE_MAP()
    34. public:
    35. afx_msg void OnPaint();
    36. afx_msg int OnCreate(LPCREATESTRUCT pcs);
    37. afx_msg void OnNew();
    38. };
    39. BEGIN_MESSAGE_MAP(CMyFrameWnd, CFrameWnd)
    40. ON_WM_CREATE()
    41. ON_WM_PAINT()
    42. ON_COMMAND(ID_NEW, OnNew)
    43. END_MESSAGE_MAP()
    44. int CMyFrameWnd::OnCreate(LPCREATESTRUCT pcs)
    45. {
    46. CMyView* pView = new CMyView;
    47. pView->Create(NULL, "MFCView", WS_CHILD|WS_VISIBLE|WS_BORDER, CRect(0, 0, 200, 200),
    48. this, AFX_IDW_PANE_FIRST); //AFX_IDW_PANE_FIRST 生成的视图窗口会平铺在框架窗口
    49. m_pViewActive = pView; //将窗口赋值给活动窗口
    50. return CFrameWnd::OnCreate(pcs);
    51. }
    52. void CMyFrameWnd::OnPaint()
    53. {
    54. PAINTSTRUCT ps = {0};
    55. HDC hdc = ::BeginPaint(m_hWnd, &ps);
    56. ::TextOutA(hdc, 100, 100, "框架窗口客户区", strlen("框架窗口客户区"));
    57. ::EndPaint(m_hWnd, &ps);
    58. }
    59. void CMyFrameWnd::OnNew()
    60. {
    61. AfxMessageBox("框架类处理了OnNew消息");
    62. }
    63. class CMyWinApp:public CWinApp
    64. {
    65. DECLARE_MESSAGE_MAP()
    66. public:
    67. virtual BOOL InitInstance();
    68. afx_msg void OnNew();
    69. };
    70. BEGIN_MESSAGE_MAP(CMyWinApp, CWinApp)
    71. ON_COMMAND(ID_NEW, OnNew)
    72. END_MESSAGE_MAP()
    73. void CMyWinApp::OnNew()
    74. {
    75. AfxMessageBox("框架类处理了OnNew消息");
    76. }
    77. BOOL CMyWinApp::InitInstance()
    78. {
    79. CMyFrameWnd* pFrame = new CMyFrameWnd;
    80. pFrame->Create(NULL, "MFCView", WS_OVERLAPPEDWINDOW, CFrameWnd::rectDefault,NULL,
    81. (char*)IDR_MENU1);
    82. m_pMainWnd = pFrame;
    83. pFrame->ShowWindow(SW_SHOW);
    84. pFrame->UpdateWindow();
    85. return TRUE;
    86. }
    87. CMyWinApp theApp;

    (3)命令消息处理顺序

            视图类 -》 框架类 -》 应用程序类

    (4)对象关系图

    1. theApp
    2. theApp->m_pMainWnd = pFrame
    3. pFrame->m_pViewActive = pView

    二、文档类

            相关类 CDocument,提供了用于管理数据的类,封装了关于数据的管理(数据提取,数据转换,数据存储等),并和视图类进行数据交互。

    1、创建项目

    (1)创建项目(MFCDoc)

    (2)编写程序

    1. #include
    2. #include
    3. #include "resource.h"
    4. class CMyDoc:public CDocument
    5. {
    6. };
    7. class CMyView:public CView
    8. {
    9. DECLARE_DYNCREATE(CMyView)
    10. DECLARE_MESSAGE_MAP()
    11. public:
    12. virtual void OnDraw(CDC* cDC);
    13. afx_msg int OnCreate(LPCREATESTRUCT pcs);
    14. };
    15. IMPLEMENT_DYNCREATE(CMyView, CView)
    16. BEGIN_MESSAGE_MAP(CMyView, CView)
    17. ON_WM_CREATE()
    18. END_MESSAGE_MAP()
    19. void CMyView::OnDraw(CDC* cDC)
    20. {
    21. cDC->TextOut(100, 100, "视图窗口");
    22. }
    23. int CMyView::OnCreate(LPCREATESTRUCT pcs)
    24. {
    25. return CView::OnCreate(pcs);
    26. }
    27. class CMyFrameWnd:public CFrameWnd
    28. {
    29. DECLARE_MESSAGE_MAP()
    30. afx_msg int OnCreate(LPCREATESTRUCT pcs);
    31. afx_msg void OnPaint();
    32. };
    33. BEGIN_MESSAGE_MAP(CMyFrameWnd, CFrameWnd)
    34. ON_WM_CREATE()
    35. ON_WM_PAINT()
    36. END_MESSAGE_MAP()
    37. int CMyFrameWnd::OnCreate(LPCREATESTRUCT pcs)
    38. {
    39. return CFrameWnd::OnCreate(pcs);
    40. }
    41. void CMyFrameWnd::OnPaint()
    42. {
    43. PAINTSTRUCT ps = {0};
    44. HDC hdc = ::BeginPaint(m_hWnd, &ps);
    45. ::TextOutA(hdc, 200, 200, "CMyFrameWnd::OnPaint", strlen("CMyFrameWnd::OnPaint"));
    46. ::EndPaint(m_hWnd, &ps);
    47. }
    48. class CMyWinApp:public CWinApp
    49. {
    50. public:
    51. virtual BOOL InitInstance();
    52. };
    53. BOOL CMyWinApp::InitInstance()
    54. {
    55. CMyFrameWnd* pFrame = new CMyFrameWnd;
    56. CCreateContext cct;
    57. CMyDoc* pDoc = new CMyDoc;
    58. cct.m_pNewViewClass = RUNTIME_CLASS(CMyView);
    59. cct.m_pCurrentDoc = pDoc;
    60. pFrame->LoadFrame(IDR_MENU1, WS_OVERLAPPEDWINDOW, NULL, &cct);
    61. m_pMainWnd = pFrame;
    62. pFrame->ShowWindow(SW_SHOW);
    63. pFrame->UpdateWindow();
    64. return TRUE;
    65. }
    66. CMyWinApp theApp;

    (3)创建过程

            利用框架类对象地址(pFrame)调用LoadFrame函数,创建框架窗口

            在处理框架窗口的WM_CREATE消息时,(父类CFrameWnd)动态创建视图类对象,并创建视图窗口

            在处理视图窗口的WM_CREATE消息时,(父类CView)将文档类和视图类对象见理关系

    2、创建流程

    1. CMyFrameWnd* pFrame = new CMyFrameWnd;
    2. CMyDoc* pDoc = new CMyDoc;
    3. CCreateContext cct;
    4. cct.m_pCurrentDoc = pDoc;//文档类对象地址
    5. cct.m_pNewViewClass = RUNTIME_CLASS(CMyView);//&CMyView::classCMyView
    6. pFrame->LoadFrame(... &cct)//函数内部this为pFrame
    7. {
    8. Create(...,&cct)//函数内部this为pFrame
    9. {
    10. CreateEx(...&cct)//函数内部this为pFrame
    11. {
    12. CREATESTRUCT cs;
    13. ....
    14. cs.lpCreateParams = &cct;
    15. ::CreateWindowEx(...,&cct);//创建主框架窗口
    16. }
    17. }
    18. }
    19. //处理框架窗口的WM_CREATE消息
    20. CFrameWnd::OnCreate( pcs )//函数内部this为pFrame,参数可以获取::CreateWindowEx的12个参数
    21. {
    22. CCreateContext* pContext = (CCreateContext*)pcs->lpCreateParams;//获取&cct
    23. OnCreateHelper(pcs, pContext)//函数内部this为pFrame,pContext===&cct
    24. {
    25. OnCreateClient(pcs, pContext)//函数内部this为pFrame,pContext===&cct
    26. {
    27. CreateView(pContext..)//函数内部this为pFrame,pContext===&cct
    28. {
    29. CWnd* pView = pContext->m_pNewViewClass->CreateObject();
    30. //动态创建视图类对象,并返回对象地址
    31. pView->Create(..,pContext)//函数内部this为pView,pContext===&cct
    32. {
    33. CreateEx(..,pContext)//函数内部this为pView,pContext===&cct
    34. {
    35. CREATESTRUCT cs;
    36. ....
    37. cs.lpCreateParams = pContext;//pContext===&cct
    38. ::CreateWindowEx(...,pContext);//创建视图窗口
    39. }
    40. }
    41. }
    42. }
    43. }
    44. }
    45. //处理视图窗口的WM_CREATE消息
    46. CView::OnCreate( pcs )//函数内部this为pView,参数可以获取::CreateWindowEx函数的12个参数
    47. {
    48. CCreateContext* pContext = (CCreateContext*)lpcs->lpCreateParams;//获取&cct
    49. pContext->m_pCurrentDoc->AddView(pView)//函数内部this为pDoc,参数为视图类对象地址
    50. {
    51. m_viewList.AddTail(pView);//文档类对象用一个链表成员变量,保存视图类对象地址
    52. pView->m_pDocument = this;//视图类对象用一个普通成员变量,保存文档类对象地址
    53. }
    54. }

    3、对象关系

    (1)文档类对象用一个链表成员变量,保存视图类对象地址

    (2)视图类对象用一个普通成员变量,保存文档类对象地址

            一个文档类对象可以对应多个视图类对象(视图窗口)

            一个视图类对象(视图窗口)只能对应一个文档类对象

    4、视图切分

    (1)相关类

    CSplitterWnd 不规则框架窗口类,分装了关于不规则框架窗口的操作

    (2)窗口切分的使用

    重写CFrameWnd类的成员虚函数OnCreateClient

            在虚函数中调用CSplitterWnd::CreateStatic创建不规则框架窗口

            在虚函数中调用CSplitterWnd::CreateView创建视图窗口

    (3)编写程序

    1. #include
    2. #include
    3. #include "resource.h"
    4. class CMyDoc:public CDocument
    5. {
    6. };
    7. class CMyView:public CView
    8. {
    9. DECLARE_DYNCREATE(CMyView)
    10. DECLARE_MESSAGE_MAP()
    11. public:
    12. virtual void OnDraw(CDC* cDC);
    13. afx_msg int OnCreate(LPCREATESTRUCT pcs);
    14. };
    15. IMPLEMENT_DYNCREATE(CMyView, CView)
    16. BEGIN_MESSAGE_MAP(CMyView, CView)
    17. ON_WM_CREATE()
    18. END_MESSAGE_MAP()
    19. void CMyView::OnDraw(CDC* cDC)
    20. {
    21. cDC->TextOut(100, 100, "视图窗口");
    22. }
    23. int CMyView::OnCreate(LPCREATESTRUCT pcs)
    24. {
    25. return CView::OnCreate(pcs);
    26. }
    27. class CMyFrameWnd:public CFrameWnd
    28. {
    29. DECLARE_MESSAGE_MAP()
    30. afx_msg int OnCreate(LPCREATESTRUCT pcs);
    31. afx_msg void OnPaint();
    32. virtual BOOL OnCreateClient(LPCREATESTRUCT lpcs, CCreateContext* pContext);
    33. private:
    34. CSplitterWnd m_split; //不规则框架窗口
    35. };
    36. BEGIN_MESSAGE_MAP(CMyFrameWnd, CFrameWnd)
    37. ON_WM_CREATE()
    38. ON_WM_PAINT()
    39. END_MESSAGE_MAP()
    40. int CMyFrameWnd::OnCreate(LPCREATESTRUCT pcs)
    41. {
    42. return CFrameWnd::OnCreate(pcs);
    43. }
    44. void CMyFrameWnd::OnPaint()
    45. {
    46. PAINTSTRUCT ps = {0};
    47. HDC hdc = ::BeginPaint(m_hWnd, &ps);
    48. ::TextOutA(hdc, 200, 200, "CMyFrameWnd::OnPaint", strlen("CMyFrameWnd::OnPaint"));
    49. ::EndPaint(m_hWnd, &ps);
    50. }
    51. BOOL CMyFrameWnd::OnCreateClient(LPCREATESTRUCT lpcs, CCreateContext* pContext)
    52. {
    53. //创建两个视图窗口
    54. m_split.CreateStatic(this, 1, 2);
    55. m_split.CreateView(0, 0, RUNTIME_CLASS(CMyView), CSize(100, 100), pContext);
    56. m_split.CreateView(0, 1, pContext->m_pNewViewClass, CSize(100, 100), pContext);
    57. m_pViewActive = (CView*)m_split.GetPane(0,0); //设置活动窗口
    58. return TRUE;
    59. }
    60. class CMyWinApp:public CWinApp
    61. {
    62. public:
    63. virtual BOOL InitInstance();
    64. };
    65. BOOL CMyWinApp::InitInstance()
    66. {
    67. CMyFrameWnd* pFrame = new CMyFrameWnd;
    68. CCreateContext cct;
    69. CMyDoc* pDoc = new CMyDoc;
    70. cct.m_pNewViewClass = RUNTIME_CLASS(CMyView);
    71. cct.m_pCurrentDoc = pDoc;
    72. pFrame->LoadFrame(IDR_MENU1, WS_OVERLAPPEDWINDOW, NULL, &cct);
    73. m_pMainWnd = pFrame;
    74. pFrame->ShowWindow(SW_SHOW);
    75. pFrame->UpdateWindow();
    76. return TRUE;
    77. }
    78. CMyWinApp theApp;

    三、命令消息(WM_COMMAND)处理顺序

            对象关系图

    1、编写程序

    1. #include
    2. #include
    3. #include "resource.h"
    4. class CMyDoc:public CDocument
    5. {
    6. DECLARE_MESSAGE_MAP()
    7. public:
    8. afx_msg void OnNew();
    9. };
    10. BEGIN_MESSAGE_MAP(CMyDoc, CDocument)
    11. //ON_COMMAND(ID_NEW, OnNew)
    12. END_MESSAGE_MAP()
    13. void CMyDoc::OnNew()
    14. {
    15. AfxMessageBox("CMyDoc::OnNew");
    16. }
    17. class CMyView:public CView
    18. {
    19. DECLARE_DYNCREATE(CMyView)
    20. DECLARE_MESSAGE_MAP()
    21. public:
    22. virtual void OnDraw(CDC* cDC);
    23. afx_msg int OnCreate(LPCREATESTRUCT pcs);
    24. afx_msg void OnNew();
    25. };
    26. IMPLEMENT_DYNCREATE(CMyView, CView)
    27. BEGIN_MESSAGE_MAP(CMyView, CView)
    28. ON_WM_CREATE()
    29. //ON_COMMAND(ID_NEW, OnNew)
    30. END_MESSAGE_MAP()
    31. void CMyView::OnDraw(CDC* cDC)
    32. {
    33. cDC->TextOut(100, 100, "视图窗口");
    34. }
    35. int CMyView::OnCreate(LPCREATESTRUCT pcs)
    36. {
    37. return CView::OnCreate(pcs);
    38. }
    39. void CMyView::OnNew()
    40. {
    41. AfxMessageBox("CMyView::OnNew");
    42. }
    43. class CMyFrameWnd:public CFrameWnd
    44. {
    45. DECLARE_MESSAGE_MAP()
    46. afx_msg int OnCreate(LPCREATESTRUCT pcs);
    47. afx_msg void OnPaint();
    48. virtual BOOL OnCreateClient(LPCREATESTRUCT lpcs, CCreateContext* pContext);
    49. afx_msg void OnNew();
    50. private:
    51. CSplitterWnd m_split; //不规则框架窗口
    52. };
    53. BEGIN_MESSAGE_MAP(CMyFrameWnd, CFrameWnd)
    54. ON_WM_CREATE()
    55. ON_WM_PAINT()
    56. ON_COMMAND(ID_NEW, OnNew)
    57. END_MESSAGE_MAP()
    58. int CMyFrameWnd::OnCreate(LPCREATESTRUCT pcs)
    59. {
    60. return CFrameWnd::OnCreate(pcs);
    61. }
    62. void CMyFrameWnd::OnPaint()
    63. {
    64. PAINTSTRUCT ps = {0};
    65. HDC hdc = ::BeginPaint(m_hWnd, &ps);
    66. ::TextOutA(hdc, 200, 200, "CMyFrameWnd::OnPaint", strlen("CMyFrameWnd::OnPaint"));
    67. ::EndPaint(m_hWnd, &ps);
    68. }
    69. BOOL CMyFrameWnd::OnCreateClient(LPCREATESTRUCT lpcs, CCreateContext* pContext)
    70. {
    71. //创建两个视图窗口
    72. m_split.CreateStatic(this, 1, 2);
    73. m_split.CreateView(0, 0, RUNTIME_CLASS(CMyView), CSize(100, 100), pContext);
    74. m_split.CreateView(0, 1, pContext->m_pNewViewClass, CSize(100, 100), pContext);
    75. m_pViewActive = (CView*)m_split.GetPane(0,0); //设置活动窗口
    76. return TRUE;
    77. }
    78. void CMyFrameWnd::OnNew()
    79. {
    80. AfxMessageBox("CMyFrameWnd::OnNew");
    81. }
    82. class CMyWinApp:public CWinApp
    83. {
    84. DECLARE_MESSAGE_MAP()
    85. public:
    86. virtual BOOL InitInstance();
    87. afx_msg void OnNew();
    88. };
    89. BEGIN_MESSAGE_MAP(CMyWinApp, CWinApp)
    90. ON_COMMAND(ID_NEW, OnNew)
    91. END_MESSAGE_MAP()
    92. void CMyWinApp::OnNew()
    93. {
    94. AfxMessageBox("CMyWinApp::OnNew");
    95. }
    96. BOOL CMyWinApp::InitInstance()
    97. {
    98. CMyFrameWnd* pFrame = new CMyFrameWnd;
    99. CCreateContext cct;
    100. CMyDoc* pDoc = new CMyDoc;
    101. cct.m_pNewViewClass = RUNTIME_CLASS(CMyView);
    102. cct.m_pCurrentDoc = pDoc;
    103. pFrame->LoadFrame(IDR_MENU1, WS_OVERLAPPEDWINDOW, NULL, &cct);
    104. m_pMainWnd = pFrame;
    105. pFrame->ShowWindow(SW_SHOW);
    106. pFrame->UpdateWindow();
    107. return TRUE;
    108. }
    109. CMyWinApp theApp;

    2、处理顺序

    视图类 -》文档类 -》框架列 -》 应用类

    3、消息执行流程

    1. //WM_COMMAND消息的路线
    2. OnCommand(wParam, lParam)//函数内部this为pFrame
    3. {
    4. CWnd::OnCommand(..)//函数内部this为pFrame
    5. {
    6. OnCmdMsg(...)//函数内部this为pFrame *****CFrameWnd::OnCmdMsg 起点
    7. {
    8. CView* pView = GetActiveView()//函数内部this为pFrame
    9. {
    10. return this->m_pViewActive;//活动视图窗口对象地址
    11. }对象
    12. pView->OnCmdMsg(..) ===>终点 CCmdTarget::OnCmdMsg 此函数内部this为pView
    13. m_pDocument->OnCmdMsg(.)==>终点CCmdTarget::OnCmdMsg 此函数内部this为文档类对象
    14. CWnd::OnCmdMsg(..)==>终点 CCmdTarget::OnCmdMsg 此函数内部this为pFrame
    15. CWinApp* pApp = AfxGetApp();//获取&theApp
    16. pApp->OnCmdMsg(..)==>终点 CCmdTarget::OnCmdMsg 此函数内部this为&theApp
    17. }
    18. }
    19. }

  • 相关阅读:
    简易磁盘自动监控服务
    Shopee店铺ID是什么?Shopee店铺id怎么看?——站斧浏览器
    【C语言】整形数据的存储
    亚马逊日本站坠落防护安全装备JIST8165标准怎么办理?
    代码随想录训练营二刷第三十二天 | 122.买卖股票的最佳时机II 55. 跳跃游戏 45.跳跃游戏II
    如何写一个中间件的springboot的starter?
    Win11 22H2如何创建开始菜单文件夹?
    哪些偏门项目可以做到?自媒体做到月赚一万以上很难吗?
    RS485和RS232有什么区别?工业网关能用吗?
    【学习笔记】CF1817F Entangled Substrings(基本子串结构)
  • 原文地址:https://blog.csdn.net/liutit/article/details/125983373