MFC单文档应用程序基础训练——文本输出、绘图等

MFC单文档

基础训练——文本输出、绘图等

 

平台为:VS2010

1.   一个简单的单文档应用程序

文件->新建项目->MFC应用程序 ,出现窗口按“下一步”,出现下面窗口选择单文档

 

点 "调试—>运行",最后运行界面为下图:

 

 

一个简单的单文档应用程序向导自动建立五个类:

向导自动建立的类

相应源文件

其他源文件

相应头文件

其他头文件

CAboutDlg

 

StdAfx.cpp

 

StdAfx.h

CXxxApp

Xxx.cpp

Xxx.rc

Xxx.h

Resource.h

CXxxView

XxxView.cpp

 

XxxView.h

 

CXxxDoc

XxxDoc.cpp

 

XxxDoc.h

 

CMainFrame

MainFrame.cpp

 

MainFrame.h

 

 

文档—视结构

 

 

 

 

 

 

 

 

 

 

 

 

 

 

每个类的主要函数:

void  CAboutDlg::DoDataExchange(CDataExchange* pDX)

 

int   CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)//创建窗体的工具栏,状态栏等

BOOLCMainFrame::PreCreateWindow(CREATESTRUCT& cs)

 

BOOL CXxxApp::InitInstance()

void  CXxxApp::OnAppAbout()

 

BOOL CXxxDoc::OnNewDocument()//初始化文档字符数据、字体信息等

void  CXxxDoc::Serialize(CArchive& ar)

 

BOOL      CXxxView::PreCreateWindow(CREATESTRUCT& cs)

void       CXxxView::OnDraw(CDC* pDC)

BOOL   CXxxView::OnPreparePrinting(CPrintInfo* pInfo)//弹出打印对话框

void      CXxxView::OnBeginPrinting(CDC* pDC,CPrintInfo* pInfo)

void     CXxxView::OnEndPrinting(CDC* pDC, CPrintInfo* pInfo)

CXxxDoc* CXxxView::GetDocument() //non-debug version is inline

创建单文档应用程序的一般步骤:

l  利用AppWizard创建应用程序框架

l  在文档内中声明保存文档数据所需要数据对象

l  完成文档类的OnNewDocument函数,初始化新文档

l  完成文档类的Serialize函数,保持和加载文档数据

l  完成视类的OnInitialUpdate函数,初始化显示

l  完成视类的OnDraw函数,显示当前文档内容

l  在视类中加入可以使用户编辑文档数据所需的代码

 

2.简单文本和图形输出

建立一个简单的单文档应用程序SimpleTextPicture,通过修改OnDraw函数在视(View)中输出信息或画图。

找到函数OnDraw(CDC* /*pDC*/),改为OnDraw(CDC* pDC);

OnDraw函数在SimpleTextPicture.cpp文件中,专门用于输出信息或画图。负责视图显示功能(包括打印、显示、预览等)

例2.1 显示正方形和文本

voidCSimpleTextPictureView::OnDraw(CDC* pDC)

{

       CSimpleTextPictureDoc* pDoc = GetDocument();

       ASSERT_VALID(pDoc);

       // TODO: add draw code for native datahere

       pDC->TextOut(10,120,_T("HelloWorld!"));

       pDC->Rectangle(20,20,100,100);

 

}

在AppWizard生成的OnDraw函数中加入以黑体字给出的两行代码,运行程序,显示如下:

 

例2.2显示彩色图形和文本

voidCSimpleTextPictureView::OnDraw(CDC* pDC)

{

       CSimpleTextPictureDoc* pDoc =GetDocument();

       ASSERT_VALID(pDoc);

       // TODO: add draw code for native datahere

       CPen pen;

       CBrush brush;

       pen.CreatePen(PS_SOLID, 3, RGB(250,0,0));

       brush.CreateSolidBrush(RGB(0,250,0));

       pDC->SelectObject(pen);

       pDC->SelectObject(brush);

       pDC->Ellipse(100,200,300,300);

       DeleteObject(pen);

       DeleteObject(brush);

       CString str(_T("HelloWorld!"));  //用UNICODE编码      pDC->SetTextColor(RGB(0,0,250));

       pDC->TextOut(120,150,str);

       pDC->SetTextColor(RGB(125,125,125));

       double a[]={31.4,888.54};

       char ch[10];

       CString str1;

       str1.Format(_T("%f"),a[0]);

       pDC->TextOut(20,40,str1);

       str1.Format(_T("%f"),a[1]);

       pDC->TextOut(20,60,str1);

      

}

3.滚动字幕

创建一个简单的单文档应用程序Xxx2;

[1] 在Xxx2View.h中添加代码如下:

public:

       virtual ~CXxx2View();

#ifdef _DEBUG

       virtual void AssertValid() const;

       virtual void Dump(CDumpContext& dc)const;

#endif

protected:

private:

       int n;//定义变量

[2]在CXxx2View构造函数中初始化变量n

CXxx2View::CXxx2View()

{

       // TODO: add construction code here

       n=0;

}

[3]Xxx2View.cpp文件中修改OnDraw函数:

voidCXxx2View::OnDraw(CDC* pDC)

{

         CXxx2Doc* pDoc = GetDocument();

     ASSERT_VALID(pDoc);

         if(!pDoc)

                   return;

 

       pDC->SetTextColor(RGB(0,0,235));

       pDC->SetBkMode(TRANSPARENT);

       CFontfont;

font.CreateFont(28,15,0,0,FW_NORMAL,false,false,false,DEFAULT_CHARSET,OUT_DEVICE_PRECIS,CLIP_DEFAULT_PRECIS,DEFAULT_QUALITY,DEFAULT_PITCH,_T("隶书"));

       pDC->SelectObject(&font);

       pDC->TextOut(n,100,_T("世上无难事,只要肯登攀!"));

       n=n+20;

       RECTr;

       GetClientRect(&r);//获得窗口

       if(n>r.right-r.left)//窗口如果n> 右坐标减去左坐标

              n=0; 

}

[4]添加三条消息映射,并加入相应代码。

通过菜单命令:视图/类视图,找到CXxx2View类,在CXxx2View类上点击“右键->属性”,找到消息按扭,如下图

 

          

 

                      点击

                  

 

 

void CXxx2View::OnLButtonDblClk(UINTnFlags, CPoint point)

{  //鼠标左双击函数

       //TODO: Add your message handler code here and/or call default

       SetTimer(1,500,NULL);

       CView::OnLButtonDblClk(nFlags,point);

}

void CXxx2View::OnRButtonDblClk(UINTnFlags, CPoint point)

{ //鼠标右双击函数

 

       //TODO: Add your message handler code here and/or call default

       KillTimer(1);

       CView::OnRButtonDblClk(nFlags,point);

}

void CXxx2View::OnTimer(UINT nIDEvent)

{

       //TODO: Add your message handler code here and/or call default

       Invalidate();//擦除背景,重新绘制

       CView::OnTimer(nIDEvent);

}

[5]添加菜单控制与代理

点击视图->资源视图,如下图,双击IDR_MAINFRAME,进入菜单编辑。

 

在资源Menu中添加运行子菜单:启动(IDC_MOVE)和停止(IDC_STOP)及其消息映射(右键->添加事件处理程序)。

 

 

 


下为“启动”对应的消息映射:

 

并修改代码:

void CXxx2View::OnMove() //启动对应消息

{

       //TODO: Add your command handler code here

              SetTimer(1,300,NULL);

}

void CXxx2View::OnStop() //停止对应的消息

{

       //TODO: Add your command handler code here

       KillTimer(1);

}

4.使用计算数据画直方图

1. 使用AppWixard生成单文档工程Plot

2. 在PlotDoc.h中类 CPlotDoc的定义之前加入类Max的定义:

class Max

{

double x1,x2,x3,x4;

double Max2(double,double);

public:

Max(double,double,double,double);

double Max4();

};

3. 在PlotDoc.cpp的文件尾部加入类Max的实现部分:

// CPlotDoccommands

doubleMax::Max2(double a, double b)

{

       if(a>=b) return a;

       else return b;

}

Max::Max(doublea, double b, double c, double d)

{

       x1=a;x2=b;x3=c;x4=d;

}

doubleMax::Max4()

{

       return Max2(Max2(x1,x2),Max2(x3,x4));

}

4. 为CPlotDoc类增加一个公有的void类型的成员函数Find和一个公有int数据成员数组m_num[5],使用类产生对象并计算它们的最大值,将它们转换成int,存入整数数组m_num。

void CPlotDoc::Find()

{

Max a(110.5, 120.8, 110, 68);     

       Max b(130, 256.5, 90,200);

       Max c(125, 406.8, 350,330);

       Max d(120, 356.8, 300,280.5);

       Max e(102, 256.8, 120,105);

       m_num[0] = (int) a.Max4();

       m_num[1] = (int) b.Max4();

       m_num[2] = (int) c.Max4();

       m_num[3] = (int) d.Max4();

       m_num[4] = (int) e.Max4();

}

5. 为CPlotDoc类的成员函数OnNewDocument增加调用语句准备数据。

BOOLCPlotDoc::OnNewDocument()

{

       if (!CDocument::OnNewDocument())

              return FALSE;

 

       // TODO: add reinitialization code here

       // (SDI documents will reuse thisdocument)

       Find();          //增加的语句

       return TRUE;

}

6. 在视类中画图写字

void CPlotView::OnDraw(CDC* pDC)

{

       CPlotDoc* pDoc =GetDocument();

       ASSERT_VALID(pDoc);

       // TODO: add draw codefor native data here

 

       pDC->SetMapMode(MM_ISOTROPIC);

       pDC->SetViewportOrg(50,250);

       pDC->MoveTo(0,0);

       pDC->LineTo(1100,0);

       pDC->MoveTo(0,0);

       pDC->LineTo(0,600);

       int width = 40;

       int ch = 'A';

        CString str1;

 

       CBrush brush;

       brush.CreateSolidBrush(RGB(50,250,0));

       pDC->SelectObject(brush);

       for(int i = 1; i<6;i++, ch++)

       {

              pDC->Rectangle(200*i,0, 200*i+width, pDoc->m_num[i-1]);

              

            str1.Format(_T("%c"),ch);//整型以字符格式赋给str1

       pDC->TextOut(200*i+10,-10, str1); //输出ABCDE

       }

       CFont font;

       font.CreateFont(0,0,0,0,800,0,0,0,OEM_CHARSET,OUT_DEFAULT_PRECIS,CLIP_DEFAULT_PRECIS,DEFAULT_QUALITY,DEFAULT_PITCH,_T("楷体"));

       pDC->SelectObject(&font);

       pDC->TextOut(200,550,_T("各公司销售点水果月销售量直方图"));

}

7. 运行程序,结果如下:

 

 

 

 

 

5. 单文档串行化编程之一

SerialRect应用程序串行化一个矩形数据,用对话框修改数据,用编辑/修改菜单打开对话框。

2.      用AppWizard建立一个普通单文档SerialRect工程,按下一步,直到出现下图,将CSerialRectView的基类设为CFormView。

3.      初始界面如下:

4.      在Form上添加控件

5.      添加变量Edit1~Edit4整型(m_x1, m_y1, m_x2, m_y2),取值范围0~300,Edit5为Control-CEdit型(m_Ctrl)

6.      用右键选择控件的Events修改Edit1的黙认EN_CHANGE消息处理OnChangeEdit1为自定义的OnChangeEdit。其他三个Edit也映射到这个函数。

7.      在Doc头文件SerialRectDoc.h中添加变量:

class CSerialRectDoc : public CDocument

{

protected: // createfrom serialization only

       CSerialRectDoc();

       DECLARE_DYNCREATE(CSerialRectDoc)

// Attributes

public:

       intx1, y1, x2, y2;

// Operations

6.  在SerialRectDoc.cpp的构造函数中初始化变量:

CSerialRectDoc::CSerialRectDoc()

{

       // TODO: add one-timeconstruction code here

       x1=y1=x2=y2=0;

}

7.      SerialRectView.cpp中添加下面内容:

void CSerialRectView::OnChangeEdit()

{    

       //TODO: Add your control notification handler code here

UpdateData();

       CSerialRectDoc*pDoc= GetDocument();

       if(m_x1!=pDoc->x1) pDoc-> x1 =m_x1;

       if(m_y1!=pDoc->y1) pDoc-> y1 =m_y1;

       if(m_x2!=pDoc->x2) pDoc-> x2 =m_x2;

       if(m_y2!=pDoc->y2) pDoc-> y2 =m_y2;

       Invalidate(true);

}

void CSerialRectView::OnInitialUpdate()

{

       CFormView::OnInitialUpdate();

       GetParentFrame()->RecalcLayout();

       ResizeParentToFit();

 

       m_x1=GetDocument()->x1;

       m_x2=GetDocument()->x2;

       m_y1=GetDocument()->y1;

       m_y2=GetDocument()->y2;

       UpdateData(false);

}

8. 在SerialRectDoc.cpp的串行化代码:

voidCSerialRectDoc::Serialize(CArchive& ar)

{

       if(ar.IsStoring())

       {

              //TODO: add storing code here

                     ar<

       }

       else

       {

              //TODO: add loading code here

                     ar>>x1>>y1>>x2>>y2;

       }

}

9.      为CSerialRectView类添加OnDraw函数

在工作区类视图中右键单击CSerialRectView类,选择Add Member Function弹出对话框:

 

void CSerialRectView::OnDraw(CDC *pDC)

{

       m_Ctrl.UpdateWindow();

       pDC=m_Ctrl.GetWindowDC();

       pDC->Rectangle(m_x1,m_y1,m_x2,m_y2);

       UpdateData(false);

}

 

6.单文档串行化编程之二

  SerialData应用程序串行化日期结构数据,用对话框修改数据,用编辑/修改菜单打开对话框。

1.      用AppWizard建立一个普通单文档SerialDate工程

2.      添加一个对话框资源如下:

并为三个编辑框添加变量m_nYear, m_nMonth, m_nDay,

3. 用ClassWizard添加类CDateDialog(其基类为CDialog)

4. 在Doc头文件SerialDateDoc.h中添加下面内容:

struct Date

{

       intm_nYear;

       intm_nMonth;

       intm_nDay;

};

#include "DateDialog.h"

class CSerialDateDoc : public CDocument

{

protected: // create from serializationonly

       CSerialDateDoc();

       DECLARE_DYNCREATE(CSerialDateDoc)

// Attributes

public:

   Date date;

4. 编辑菜单中添加子菜单项,ID_EDIT_MODIFY,消息映射到SerialDateDoc.cpp文件中的OnEditModify()函数

 

5. 在SerialDateDoc.cpp中添加代码

CSerialDateDoc::CSerialDateDoc()

{

       date.m_nYear=2002;

       date.m_nMonth=6;

       date.m_nDay=1;

}

void CSerialDateDoc::Serialize(CArchive&ar)

{

       if(ar.IsStoring())

       {            ar<

       }

       else

       {            ar>>date.m_nYear>>date.m_nMonth >>date.m_nDay ;

       }

}

void CSerialDateDoc::OnEditModify()

{

       CDateDialogdlg;

       dlg.m_nYear=date.m_nYear;

       dlg.m_nMonth=date.m_nMonth;

       dlg.m_nDay=date.m_nDay;

       if(dlg.DoModal()==IDOK)

       {

       date.m_nYear=dlg.m_nYear;

       date.m_nMonth=dlg.m_nMonth;

       date.m_nDay=dlg.m_nDay;

       }

       UpdateAllViews(NULL);

       SetModifiedFlag(true);//关闭窗口时提示存盘

}

6. 修改SerialDateView.cpp中的OnDraw代码

void CSerialDateView::OnDraw(CDC* pDC)

{

       CSerialDateDoc*pDoc = GetDocument();

       ASSERT_VALID(pDoc);

       CStringstr;

       str.Format(_T("Year:%d"),pDoc->date.m_nYear);

       pDC->TextOut(20,20,str);

       str.Format(_T("Month:%d"),pDoc->date.m_nMonth);

       pDC->TextOut(20,40,str);

       str.Format(_T("Day:%d"),pDoc->date.m_nDay);

       pDC->TextOut(20,60,str);

}

 

你可能感兴趣的:(MFC单文档应用程序基础训练——文本输出、绘图等)