vs2019 MFC實現(xiàn)office界面的畫圖小項目(超超級詳細)

      網(wǎng)友投稿 1419 2025-04-02

      這是針對于博客vs2019安裝和使用教程(詳細)的MFC實現(xiàn)office界面的畫圖小項目的新建示例


      目錄

      一、創(chuàng)建項目

      二、進入多個文檔的控件界面

      三、編寫畫圖小程序(先從畫矩形開始)

      四、我們還可以再多畫一些,例如箭頭、直線和三角

      五、圖形的輪廓填充和內(nèi)部填充(為了方便,都是統(tǒng)一更改顏色,一個一個改代碼很麻煩)

      六、序列化保存和讀取文件

      七、自己寫一個導(dǎo)出文件的按鈕

      八、總結(jié)

      vs2019安裝MFC看這里:vs2019 安裝MFC

      一、創(chuàng)建項目

      1.點擊文件-->新建-->項目,選擇MFC應(yīng)用,點擊下一步

      2.項目名稱為Draw,點擊創(chuàng)建

      3.可以看到有很多內(nèi)容

      4.應(yīng)用程序類型有:

      單個文檔

      多個文檔

      基于對話框

      多個頂層文檔

      5.項目樣式有:

      MFC standard

      Windows Explorer

      Visual Studio

      Office

      6.這里應(yīng)用程序類型選擇多個文檔,項目樣式選擇Office。

      視覺樣式和顏色選擇默認的Office 2007(Blue theme)即可。

      值得注意的是:Office會比默認選擇的項目樣式多一個Ribbon框,后面會說到~

      7.點擊下一步,我們來到文檔模板屬性,可以看到主框架描述和文檔類型名稱等內(nèi)容,這里可以默認不用修改

      8.下一步,來到用戶界面功能,可以看到Command bar里有三個選項,這里我們選擇默認的使用功能區(qū)(ribbon)

      9.下一步,來到高級功能,可以直接默認跳過

      10.點擊下一步來到最后一步——生成的類,可以看到生成的類和類名,我們選擇默認的App即可,這樣我們的頭文件和.cpp文件就是以項目名稱命名

      11.點擊完成,之后看到左側(cè)的解決方案資源管理器,這里包含了5個內(nèi)容:

      引用

      外部依賴項

      頭文件

      源文件

      資源文件

      其中,我們可以在頭文件和源文件里看到生成的.h和.cpp文件

      二、進入多個文檔的控件界面

      1.因為是基于多個文檔,所以我們需要了解如何在對話框上如何添加控件。因此我們可以雙擊?項目名稱.rc2,進入資源視圖;

      當(dāng)然,我們也可以直接點擊系統(tǒng)默認打開的底下的資源視圖選項(注意:不能resource.h文件同時打開!!!)

      在這里喲~

      如果不小心關(guān)閉了,也可以在菜單欄里?視圖->資源視圖里重新打開該視圖

      2.這里比較重要的是Menu部分,因為有很多MFC已經(jīng)內(nèi)置好的功能,例如主框架IDR_MAINFRAME里就有文件下拉菜單等選項,我們想要添加一個新的下拉菜單,只需要在右邊的“請在此鍵入”輸入內(nèi)容,并且編寫對應(yīng)的代碼即可。但這里博主并不在這里添加畫圖的功能。

      3.博主這里要在Ribbon里添加畫圖的功能

      4.點擊右邊的工具箱(豎著的,治療頸椎~)

      然后點擊Ribbon編輯器,可以看到有很多種類的控件

      三、編寫畫圖小程序(先從畫矩形開始)

      1.我們點擊面板,然后拖動到窗口面板的右邊,可以看到多了一個面板1

      2.我們點擊這個面板,在屬性窗口中的外觀下面,修改Caption,把面板1改為圖形,這就算給這個面板改了名字

      3.我們再選擇Ribbon工具箱里的按鈕,同樣拖動,至圖形面板,如下,名字為button1

      4.修改這個按鈕的屬性中雜項的ID,改為ID_RECTANGLE

      這里指的注意的就是這個ID,這個在MFC編程中十分重要,因為我們往往需要獲取控件的ID號來對該控件進行函數(shù)編寫、消息處理等操作!!!

      5.既然是按鈕,那就得有觸發(fā)這個按鈕所要執(zhí)行的操作,右鍵這個按鈕,我們選擇添加事件處理程序

      6.彈出以下框

      7.類列表我們選擇CDrawView,點擊確定

      8.我們可以看到在DrawView.cpp中生成的命令函數(shù)

      我們也可以看到在前面的代碼中多了一個ON_COMMAND函數(shù),說明我們確實添加了這樣的一個按鈕命令(注意:ID_RECTANGLE這個ID號就是對應(yīng)的按鈕的編號,&CDrawView::OnRectangle表示這個ID的按鈕實現(xiàn)的命令函數(shù))

      這里的紅波浪線提示沒有這個ID,其實我們是添加了這個按鈕的,可以在Resource.h中看到(注意打開Resource.h再去看資源試圖是打不開的,會報錯,因此需要先關(guān)掉Resource.h再去訪問資源試圖!!!!!)

      #define ID_RECTANGLE 32771

      這個IDE編輯器的小問題,我們可以選擇重啟vs2019打開就不會顯示未定義ID了,如下,沒有紅色波浪線了

      9.現(xiàn)在的問題就是如何畫圖的問題:畫矩形,則定義一個矩形類,寫方法,在消息函數(shù)里新建對象即可;但是我們?nèi)绻粷M足只畫矩形呢?畫箭頭、三角可不可以?這個時候我們就應(yīng)該想到繼承,即建一個抽象類graph,然后派生幾個子類去完成這個功能。因此我們應(yīng)該先新建一個graph抽象類:

      我們右鍵頭文件,選擇添加-->新建項,彈出如下界面;

      選擇頭文件(.h),名稱為graph.h,點擊確定

      10.如下

      11.添加如下代碼:

      graph.h

      class graph :

      public CObject

      {

      protected:

      //邊框

      DECLARE_SERIAL(graph)

      int left, up, right, down;

      //選中狀態(tài)

      unsigned int state;

      int sx, sy;

      int f_width = 5;

      int fcolor = 0xffffff, bcolor = 0;

      public:

      graph() :graph(50, 50, 100, 100) {

      }

      graph(int l, int u, int r, int d);

      void Offset(int cx, int cy);

      void onPress(int x, int y); // 鼠標(biāo)按下

      int onMove(int cx, int cy); // 鼠標(biāo)移動

      void onRelease(int x, int y); // 鼠標(biāo)釋放

      virtual void onDraw(CDC* pDC);

      virtual int getGraphID() { return 0; }

      virtual void Serialize(CArchive& ar);

      void SetFillColor(int color);

      void SetBorderColor(int color);

      ~graph();

      };

      結(jié)果報了一堆錯誤,事實是因為我們新建的graph并沒有和MFC本身的類關(guān)聯(lián)起來

      我們可以這樣做:打開framework.h(vs2017里是stdafx.h),我們在這里include一下我們的graph抽象類

      如下(注意自己寫的頭文件要使用引號“”)

      #include "graph.h"

      我們再回過頭看graph.h,發(fā)現(xiàn)已經(jīng)沒有錯誤了

      12.寫了頭文件,還要寫對應(yīng)的源文件:

      我們右鍵頭文件,選擇添加-->新建項,彈出如下界面;

      選擇C++文件(.cpp),名稱為graph.cpp,點擊確定

      13.如下

      14.填寫如下代碼

      graph.cpp

      #include "framework.h"

      IMPLEMENT_SERIAL(graph, CObject, 1)

      graph::graph(int l, int u, int r, int d)

      {

      left = l;

      up = u;

      right = r;

      down = d;

      state = 0;

      fcolor = 0xffffff;

      }

      void graph::Offset(int cx, int cy)

      {

      left += cx;

      right += cx;

      up += cy;

      down += cy;

      }

      void graph::onPress(int x, int y)

      {

      sx = x; sy = y;

      state = 0;

      //選中圖形

      if (left < x && x < right &&

      up < y && y < down) {

      state = 1;

      return;

      }

      if (left - f_width / 2 < x && x < left + f_width / 2) state |= 2; // 選中左邊

      if (up - f_width / 2 < y && y < up + f_width / 2) state |= 4;//選中上邊

      if (right - f_width / 2 < x && x < right + f_width / 2) state |= 8;//選中右邊

      if (down - f_width / 2 < y && y < down + f_width / 2) state |= 16; // 選中下邊

      }

      void graph::onRelease(int x, int y)

      {

      state = 0;

      }

      void graph::SetBorderColor(int color)

      {

      fcolor = color;

      }

      void graph::SetFillColor(int color)

      {

      bcolor = color;

      }

      int graph::onMove(int x, int y)

      {

      int cx, cy;

      cx = x - sx; cy = y - sy;

      sx = x; sy = y;

      if (state == 1) {

      Offset(cx, cy); // 位移量cx,cy

      }

      if (2 == (state & 2)) {

      left = x;

      }

      if (4 == (state & 4)) {

      up = y;

      }

      if (8 == (state & 8)) {

      right = x;

      }

      if (16 == (state & 16)) {

      down = y;

      }

      return state == 0 ? 0 : 1;

      }

      void graph::Serialize(CArchive & ar)

      {

      CObject::Serialize(ar);

      if (ar.IsLoading()) {

      ar >> left >> right >> up >> down >> f_width >> fcolor >> bcolor;

      }

      else

      {

      ar << left << right << up << down << f_width << fcolor << bcolor;

      }

      }

      graph::~graph()

      {

      }

      void graph::onDraw(CDC * pDC) {

      CBrush b(fcolor);

      pDC->SelectObject(&b);

      CRect r(left, up, right, down);

      pDC->FillRect(&r, &b);

      CPen p(PS_SOLID, 1, bcolor);

      pDC->SelectObject(&p);

      pDC->Rectangle(left, up, right, down);

      pDC->MoveTo(left, up);

      pDC->DrawText(_T("空圖形"), -1, new CRect(left, up, right, down), DT_CENTER | DT_VCENTER | DT_SINGLELINE);

      }

      15.根據(jù)上面的步驟,同樣地,我們再新建一個矩形Rectangle類。這里直接列出頭文件和源文件

      rectangle.h

      #pragma once

      #include "graph.h"

      class rectangle :

      public graph

      {

      public:

      //DECLARE_SERIAL(graph)

      //void Serialize(CArchive& ar);

      rectangle() :graph(50, 50, 100, 100) {}

      rectangle(int l, int u, int r, int d);

      void onDraw(CDC* pDC);

      int getGraphID() { return 2; }

      ~rectangle();

      };

      rectangle.cpp

      #include "framework.h"

      rectangle::rectangle(int l, int u, int r, int d) :graph(l, u, r, d)

      {

      state = 0;

      fcolor = 0xffffff;

      }

      void rectangle::onDraw(CDC* pDC)

      {

      CBrush b(fcolor);

      pDC->SelectObject(&b);

      CRect r(left, up, right, down);

      pDC->FillRect(&r, &b);

      CPen p(PS_SOLID, 1, bcolor);

      pDC->SelectObject(&p);

      pDC->Rectangle(left, up, right, down);

      pDC->MoveTo(left, up);

      }

      rectangle::~rectangle()

      {

      }

      注意framework.h不要忘了加上:

      #include "rectangle.h"

      16.由于我們需要可以添加多個圖形,因此一個以graph對象構(gòu)成的list是必不可少的。我們在DrawDoc.h文檔頭文件添加這個list,可以添加//操作下面

      17.如下,可以看到又報錯了:

      std::list graphList;

      還是一樣的,把list的頭文件加到framework.h中

      #include

      再回去看DrawDoc.h,發(fā)現(xiàn)沒有錯誤

      18.我們再回到DrawView.cpp,填寫矩形Rectangle的消息處理程序,如下。代碼解釋為每點擊一次矩形按鈕,添加一個矩形:

      void CDrawView::OnRectangle()

      {

      // TODO: 在此添加命令處理程序代碼

      CDrawDoc* pDoc = GetDocument();

      ASSERT_VALID(pDoc);

      if (!pDoc)

      return;

      pDoc->graphList.push_front(new rectangle(50, 50, 100, 100));

      Invalidate();

      }

      19.我們還需要修改DrawView.cpp里的繪圖代碼部分

      添加如下代碼(CDC* 后面的pDC取消注釋)

      // CDrawView 繪圖

      void CDrawView::OnDraw(CDC* pDC)

      {

      CDrawDoc* pDoc = GetDocument();

      ASSERT_VALID(pDoc);

      if (!pDoc)

      return;

      // TODO: 在此處為本機數(shù)據(jù)添加繪制代碼

      std::list::iterator v;

      for (v = pDoc->graphList.begin(); v != pDoc->graphList.end(); ++v) {

      (*v)->onDraw(pDC);

      }

      }

      20.運行程序,發(fā)現(xiàn)報錯,這是預(yù)編譯頭的問題

      1>------ 已啟動生成: 項目: Draw, 配置: Debug Win32 ------

      1>pch.cpp

      1>calendarbar.cpp

      vs2019 MFC實現(xiàn)office界面的畫圖小項目(超超級詳細)

      1>ChildFrm.cpp

      1>Draw.cpp

      1>DrawDoc.cpp

      1>DrawView.cpp

      1>graph.cpp

      1>D:\vs2019_project\Draw\graph.cpp(110): fatal error C1010: 在查找預(yù)編譯頭時遇到意外的文件結(jié)尾。是否忘記了向源中添加“#include "pch.h"”?

      1>MainFrm.cpp

      1>rectangle.cpp

      1>D:\vs2019_project\Draw\rectangle.cpp(25): fatal error C1010: 在查找預(yù)編譯頭時遇到意外的文件結(jié)尾。是否忘記了向源中添加“#include "pch.h"”?

      1>正在生成代碼...

      1>已完成生成項目“Draw.vcxproj”的操作 - 失敗。

      ========== 生成: 成功 0 個,失敗 1 個,最新 0 個,跳過 0 個 ==========

      21.點擊菜單欄的項目-->屬性,選擇C/C++-->預(yù)編譯頭,如下

      改為不使用預(yù)編譯頭,點擊確定

      22.我們再次運行代碼,出現(xiàn)如下界面

      23.我們點擊圖形面板的矩形,可以看到窗口生成了一個矩形

      24.然而,僅僅是生成一個矩形還是不夠的;我們還需要添加鼠標(biāo)的相關(guān)消息響應(yīng)函數(shù),例如鼠標(biāo)移動,鼠標(biāo)按下和鼠標(biāo)抬起

      右鍵源文件,點擊類向?qū)?/p>

      25.如下

      26.我們添加一個鼠標(biāo)左鍵按下的消息響應(yīng):選擇消息欄,選擇WM_LBUTTONUP,類名選擇CDrawView,點擊添加處理程序

      如下

      添加如下代碼:

      void CDrawView::OnLButtonDown(UINT nFlags, CPoint point)

      {

      // TODO: 在此添加消息處理程序代碼和/或調(diào)用默認值

      CDrawDoc* pDoc = GetDocument();

      ASSERT_VALID(pDoc);

      if (!pDoc)

      return;

      // TODO: 在此處為本機數(shù)據(jù)添加繪制代碼

      std::list::iterator v;

      for (v = pDoc->graphList.begin(); v != pDoc->graphList.end(); ++v) {

      (*v)->onPress(point.x, point.y);

      }

      Invalidate();

      //CView::OnLButtonDown(nFlags, point);

      }

      27.同樣地,我們再添加鼠標(biāo)左鍵松開

      填寫代碼:

      void CDrawView::OnLButtonUp(UINT nFlags, CPoint point)

      {

      // TODO: 在此添加消息處理程序代碼和/或調(diào)用默認值

      CDrawDoc* pDoc = GetDocument();

      ASSERT_VALID(pDoc);

      if (!pDoc)

      return;

      // TODO: 在此處為本機數(shù)據(jù)添加繪制代碼

      std::list::iterator v;

      for (v = pDoc->graphList.begin(); v != pDoc->graphList.end(); ++v) {

      (*v)->onRelease(point.x, point.y);

      }

      Invalidate();

      //CView::OnLButtonUp(nFlags, point);

      }

      28.同樣地,我們再添加鼠標(biāo)移動

      填寫代碼:

      void CDrawView::OnMouseMove(UINT nFlags, CPoint point)

      {

      // TODO: 在此添加消息處理程序代碼和/或調(diào)用默認值

      CDrawDoc* pDoc = GetDocument();

      ASSERT_VALID(pDoc);

      if (!pDoc)

      return;

      // TODO: 在此處為本機數(shù)據(jù)添加繪制代碼

      std::list::iterator v;

      for (v = pDoc->graphList.begin(); v != pDoc->graphList.end(); ++v) {

      (*v)->onMove(point.x, point.y);

      }

      Invalidate();

      //CView::OnMouseMove(nFlags, point);

      }

      29.運行程序,我們點擊矩形,可以拖動這個矩形了!!

      30.博主這里還做了放大和縮小:把鼠標(biāo)移到矩形邊緣,點擊邊緣就可以放大縮小~

      31.當(dāng)然,我們還可以再添加好幾個矩形,因為別忘了博主是用list來存儲每次生成的graph對象的~

      四、我們還可以再多畫一些,例如箭頭、直線和三角

      1.相信前面的步驟大家了解的話,我相信添加按鈕是很容易的,這里就直接給出博主的按鈕ID

      三角形:ID_TRIANGLE

      箭頭:ID_ARROW

      直線:ID_LINE

      2.添加的類和方法:

      *framework.h

      #include // MFC 核心組件和標(biāo)準(zhǔn)組件

      #include // MFC 擴展

      #include "graph.h"

      #include "rectangle.h"

      #include "triangle.h"

      #include "arrow.h"

      #include "line.h"

      #include

      (1)三角形:

      triangle.h

      #pragma once

      #include "graph.h"

      class triangle :

      public graph

      {

      protected:

      public:

      triangle(int l, int u, int r, int d);

      int getGraphID() { return 3; }

      void onDraw(CDC* pDC);

      ~triangle();

      };

      triangle.cpp

      #include "framework.h"

      triangle::triangle(int l, int u, int r, int d) :graph(l, u, r, d)

      {

      state = 0;

      fcolor = 0xffffff;

      }

      void triangle::onDraw(CDC* pDC)

      {

      CPoint pts[3];

      pts[0].x = (left + right) / 2;

      pts[0].y = up;

      pts[1].x = left;

      pts[1].y = down;

      pts[2].x = right;

      pts[2].y = down;

      CBrush b(fcolor);

      pDC->SelectObject(&b);

      CPen p(PS_SOLID, 1, bcolor);

      pDC->SelectObject(&p);

      pDC->Polygon(pts, 3);

      }

      triangle::~triangle()

      {

      }

      (2)箭頭:

      arrow.h

      #pragma once

      #include "graph.h"

      class arrow :

      public graph

      {

      public:

      arrow(int l, int u, int r, int d);

      void onDraw(CDC* pDC);

      int getGraphID() { return 4; }

      ~arrow();

      };

      arrow.cpp

      #include "framework.h"

      arrow::arrow(int l, int u, int r, int d) :graph(l, u, r, d)

      {

      }

      void arrow::onDraw(CDC* pDC)

      {

      CPoint pts[2], pt[3];

      pts[0].x = left;

      pts[0].y = (up + down) / 2;

      pts[1].x = (left + right) / 2;

      pts[1].y = (up + down) / 2;

      pt[0].x = (left + right) / 2;

      pt[0].y = up;

      pt[1].x = (left + right) / 2;

      pt[1].y = down;

      pt[2].x = right;

      pt[2].y = (up + down) / 2;

      CBrush b(fcolor);

      pDC->SelectObject(&b);

      CPen p(PS_SOLID, 1, bcolor);

      pDC->SelectObject(&p);

      pDC->Polygon(pts, 2);

      pDC->Polygon(pt, 3);

      }

      arrow::~arrow()

      {

      }

      (3)直線:

      line.h

      #pragma once

      #include "graph.h"

      class line :

      public graph

      {

      public:

      line() :line(50, 50, 100, 100) {}

      line(int l, int u, int r, int d);

      void onDraw(CDC* pDC);

      int getGraphID() { return 1; }

      ~line();

      };

      line.cpp

      #include "framework.h"

      line::line(int l, int u, int r, int d) :graph(l, u, r, d)

      {

      state = 0;

      fcolor = 0xffffff;

      }

      void line::onDraw(CDC* pDC)

      {

      CPoint pts[2];

      pts[0].x = left;

      pts[0].y = (up + down) / 2;

      pts[1].x = right;

      pts[1].y = (up + down) / 2;

      CBrush b(fcolor);

      pDC->SelectObject(&b);

      CPen p(PS_SOLID, 1, bcolor);

      pDC->SelectObject(&p);

      pDC->Polygon(pts, 2);

      }

      line::~line()

      {

      }

      3.添加的事件處理程序:

      (1)三角形:

      void CDrawView::OnTriangle()

      {

      // TODO: 在此添加命令處理程序代碼

      CDrawDoc* pDoc = GetDocument();

      ASSERT_VALID(pDoc);

      if (!pDoc)

      return;

      pDoc->graphList.push_front(new triangle(50, 50, 100, 100));

      Invalidate();

      }

      (2)箭頭:

      void CDrawView::OnArrow()

      {

      // TODO: 在此添加命令處理程序代碼

      CDrawDoc* pDoc = GetDocument();

      ASSERT_VALID(pDoc);

      if (!pDoc)

      return;

      pDoc->graphList.push_front(new arrow(50, 50, 100, 100));

      Invalidate();

      }

      (3)直線:

      void CDrawView::OnLine()

      {

      // TODO: 在此添加命令處理程序代碼

      CDrawDoc* pDoc = GetDocument();

      ASSERT_VALID(pDoc);

      if (!pDoc)

      return;

      pDoc->graphList.push_front(new line(50, 50, 100, 100));

      Invalidate();

      }

      4.運行程序,現(xiàn)在可以添加各種圖形并且可以改變大小啦

      五、圖形的輪廓填充和內(nèi)部填充(為了方便,都是統(tǒng)一更改顏色,一個一個改代碼很麻煩)

      1.添加一個面板,再添加兩個按鈕。按鈕的選擇是顏色按鈕

      2.如下

      輪廓:ID_FILLCOLOR_LINE

      內(nèi)部:ID_FILLCOLOR_IN

      3.添加的事件處理程序:

      (1)需要在DrawView.cpp中添加MainFrm.h頭文件

      #include "MainFrm.h"

      (2)還需要在MainFrm.h中將m_wndRibbonBar從protected變?yōu)閜ublic,這樣才能訪問到這個變量,否則報錯!

      protected: // 控件條嵌入成員

      //CMFCRibbonBar m_wndRibbonBar;

      CMFCRibbonApplicationButton m_MainButton;

      CMFCToolBarImages m_PanelImages;

      CMFCRibbonStatusBar m_wndStatusBar;

      COutlookBar m_wndNavigationBar;

      CMFCShellTreeCtrl m_wndTree;

      CCalendarBar m_wndCalendar;

      CMFCCaptionBar m_wndCaptionBar;

      public:

      CMFCRibbonBar m_wndRibbonBar;

      輪廓

      void CDrawView::OnFillcolorLine()

      {

      // TODO: 在此添加命令處理程序代碼

      CDrawDoc* pDoc = GetDocument();

      ASSERT_VALID(pDoc);

      if (!pDoc)

      return;

      CMainFrame* pFrame = (CMainFrame*)AfxGetMainWnd();

      CMFCRibbonColorButton* a = (CMFCRibbonColorButton*)((pFrame->m_wndRibbonBar).FindByID(ID_FILLCOLOR_LINE));

      COLORREF c = a->GetColor();

      std::list::iterator v;

      for (v = pDoc->graphList.begin(); v != pDoc->graphList.end(); ++v) {

      (*v)->SetFillColor(c);

      }

      Invalidate();

      }

      內(nèi)部

      void CDrawView::OnFillcolorIn()

      {

      // TODO: 在此添加命令處理程序代碼

      CDrawDoc* pDoc = GetDocument();

      ASSERT_VALID(pDoc);

      if (!pDoc)

      return;

      CMainFrame* pFrame = (CMainFrame*)AfxGetMainWnd();

      CMFCRibbonColorButton* a = (CMFCRibbonColorButton*)((pFrame->m_wndRibbonBar).FindByID(ID_FILLCOLOR_IN));

      COLORREF c = a->GetColor();

      std::list::iterator v;

      for (v = pDoc->graphList.begin(); v != pDoc->graphList.end(); ++v) {

      (*v)->SetBorderColor(c);

      }

      Invalidate();

      }

      4.運行程序

      (1)輪廓變紅,選擇紅色

      如下

      (2)內(nèi)部填充為綠色,選擇綠色

      如下

      六、序列化保存和讀取文件

      1.修改DrawDoc.cpp的序列化部分,這是用于菜單欄里的保存和打開圖片所使用的

      2.修改代碼如下:

      // CDrawDoc 序列化

      void CDrawDoc::Serialize(CArchive& ar)

      {

      if (ar.IsStoring())

      {

      // TODO: 在此添加存儲代碼

      ar << graphList.size();

      for (auto it = graphList.begin(); it != graphList.end(); it++) {

      ar << (*it)->getGraphID();

      (*it)->Serialize(ar);

      }

      }

      else

      {

      // TODO: 在此添加加載代碼

      for (auto it = graphList.begin(); it != graphList.end(); it++) {

      delete* it;

      }

      graphList.clear();

      int i, gid;

      ar >> i;

      graph* g;

      while (i--) {

      ar >> gid;

      switch (gid)

      {

      case 1:

      g = new line();

      break;

      case 2:

      g = new rectangle();

      break;

      case 3:

      g = new triangle(0, 0, 0, 0);

      break;

      case 4:

      g = new arrow(0, 0, 0, 0);

      break;

      default:

      g = new graph();

      break;

      }

      g->Serialize(ar);

      graphList.push_back(g);

      }

      }

      }

      3.運行程序:博主隨便畫一個圖

      選擇保存,默認路徑和名字

      可以看到有一個Draw1的文件

      我們關(guān)掉程序,再運行程序,打開這個文件

      可以看到多一個窗口,說明我們序列化成功!!

      七、自己寫一個導(dǎo)出文件的按鈕

      1.再新建一個面板,拖入一個按鈕,名字到導(dǎo)出圖片,ID為ID_SAVE

      2.添加的事件處理程序:

      void CDrawView::OnSave()

      {

      // TODO: 在此添加命令處理程序代碼

      CClientDC dc(this);

      CRect rect;

      CString saveFilePath;

      BOOL showMsgTag;

      BOOL saveTag = FALSE;

      GetClientRect(&rect);

      HBITMAP hbitmap = CreateCompatibleBitmap(dc, rect.right - rect.left, rect.bottom - rect.top);

      HDC hdc = CreateCompatibleDC(dc);

      HBITMAP hOldMap = (HBITMAP)SelectObject(hdc, hbitmap);

      BitBlt(hdc, 0, 0, rect.right - rect.left, rect.bottom - rect.top, dc, 0, 0, SRCCOPY);

      CImage image;

      image.Attach(hbitmap);

      if (!saveTag)

      {

      saveTag = TRUE;

      showMsgTag = TRUE;

      CString strFilter = _T("位圖文件(*.bmp)|*.bmp|JPEG 圖像文件|*.jpg| GIF圖像文件 | *.gif | PNG圖像文件 | *.png |其他格式(*.*) | *.* || ");

      CFileDialog dlg(FALSE, _T("bmp"), _T("iPaint1.bmp"), NULL, strFilter);

      if (dlg.DoModal() != IDOK) return;

      CString strFileName;

      CString strExtension;

      strFileName = dlg.m_ofn.lpstrFile;

      if (dlg.m_ofn.nFileExtension == 0)

      {

      switch (dlg.m_ofn.nFilterIndex)

      {

      case 1:

      strExtension = "bmp";

      break;

      case 2:

      strExtension = "jpg";

      break;

      case 3:

      strExtension = "gif";

      break;

      case 4:

      strExtension = "png";

      break;

      }

      strFileName = strFileName + "." + strExtension;

      }

      saveFilePath = strFileName;

      }

      else

      {

      showMsgTag = FALSE;

      }

      HRESULT hResult = image.Save(saveFilePath);

      if (FAILED(hResult)) {

      MessageBox(_T("保存圖像文件失敗!"));

      }

      else

      {

      if (showMsgTag)

      MessageBox(_T("文件保存成功!"));

      }

      image.Detach();

      SelectObject(hdc, hOldMap);

      }

      3.運行程序,導(dǎo)入Draw1

      點擊導(dǎo)出圖片,選擇路徑和文件名稱,確定

      4.提示文件保存成功!

      5.雙擊打開這個文件iPaint1.bmp

      6.可以看到成功打開(注意:這個文件不能用剛才自己寫的MFC程序自帶的打開來打開這個文件,因為打開的文件不是被序列化過的,因此打開會失敗!)

      因此不能用這里的打開按鈕喲

      八、總結(jié)

      1.MFC的按鈕消息需要熟練掌握

      2.鼠標(biāo)消息的使用也很重要

      3.序列化保存和普通的導(dǎo)出圖片不是一碼事

      4.對于抽象類的使用,尤其是畫各種圖是很重要的

      5.MFC內(nèi)置的庫函數(shù)需要熟練掌握(畫筆、刷子等等)

      后記:這篇博客廢了博主老大的工夫,大家可以試試加個畫圓啥的哈哈哈~

      返回至原博客:

      vs2019安裝和使用教程(詳細)

      Windows

      版權(quán)聲明:本文內(nèi)容由網(wǎng)絡(luò)用戶投稿,版權(quán)歸原作者所有,本站不擁有其著作權(quán),亦不承擔(dān)相應(yīng)法律責(zé)任。如果您發(fā)現(xiàn)本站中有涉嫌抄襲或描述失實的內(nèi)容,請聯(lián)系我們jiasou666@gmail.com 處理,核實后本網(wǎng)站將在24小時內(nèi)刪除侵權(quán)內(nèi)容。

      版權(quán)聲明:本文內(nèi)容由網(wǎng)絡(luò)用戶投稿,版權(quán)歸原作者所有,本站不擁有其著作權(quán),亦不承擔(dān)相應(yīng)法律責(zé)任。如果您發(fā)現(xiàn)本站中有涉嫌抄襲或描述失實的內(nèi)容,請聯(lián)系我們jiasou666@gmail.com 處理,核實后本網(wǎng)站將在24小時內(nèi)刪除侵權(quán)內(nèi)容。

      上一篇:Excel2016怎么自動拆分提取
      下一篇:WPS表格中的數(shù)據(jù)怎么設(shè)置分組標(biāo)識?
      相關(guān)文章
      亚洲色婷婷一区二区三区| 亚洲Av无码国产情品久久| 色噜噜AV亚洲色一区二区| 国产AV日韩A∨亚洲AV电影| 亚洲熟妇无码AV| 亚洲kkk4444在线观看| 亚洲伊人久久大香线蕉影院| 亚洲最大黄色网址| 91亚洲自偷在线观看国产馆| 亚洲精品午夜视频| 亚洲国产精品成人精品软件| 亚洲综合激情六月婷婷在线观看| 亚洲AV福利天堂一区二区三| 亚洲av无码一区二区三区不卡| 亚洲va国产va天堂va久久| 亚洲成AV人片在WWW色猫咪| 亚洲成A∨人片在线观看不卡| 亚洲成av人影院| 亚洲一区二区三区高清| 久久噜噜噜久久亚洲va久| 久久久久亚洲AV片无码| 久久亚洲精品成人AV| 亚洲日韩乱码久久久久久| 亚洲Av无码一区二区二三区| 亚洲AV无码乱码麻豆精品国产| 亚洲成A人片在线播放器| 亚洲爆乳成av人在线视菜奈实| 噜噜噜亚洲色成人网站| 久久久久亚洲AV成人网| 亚洲人成人77777网站| 亚洲AV综合色区无码一区| 亚洲色四在线视频观看| 亚洲欧洲日产国码二区首页 | 亚洲五月综合缴情婷婷| 亚洲国产系列一区二区三区| 亚洲女子高潮不断爆白浆| 国产午夜亚洲精品不卡电影| 国产国拍亚洲精品福利 | 亚洲爱情岛论坛永久| 亚洲白嫩在线观看| 亚洲色成人四虎在线观看|