MFC单文档应用程序问题

1.   文档——视结构

     

   每个类的主要函数有:

   void   CAboutDlg::DoDataExchange(CDataExchange* pDX)

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

   BOOL   CMainFrame::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

      

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

1) 利用AppWizard创建应用程序框架;

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

3) 完成文档类的OnNewDocument函数,初始化新文档;

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

5) 完成视类的OnInitialUpdate函数,初始化显示;

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

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

3.  简单文本和图形输出

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

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

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

        3.1  显示正方形和文本

 void CSimpleTextPictureView::OnDraw(CDC* pDC)
 {
     CSimpleTextPictureDoc* pDoc =GetDocument();
     ASSERT_VALID(pDoc);
     // TODO: add draw code for native data here
     <span style="color:#3366ff;">pDC->TextOut(10,120,_T("HelloWorld!"));
     pDC->Rectangle(20,20,100,100);</span>
 }

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

       3.2  显示彩色图形和文本

void CSimpleTextPictureView::OnDraw(CDC* pDC)
{
	CSimpleTextPictureDoc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);
	// TODO: add draw code for native data here
	<span style="color:#3366ff;">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("Hello World!"));  //用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);</span>
}

         运行结果如下:

         

4.   滚动字幕

        创建一个简单的单文档应用程序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 constructi on code here
        n=0;
}

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

void CXxx2View::OnDraw(CDC* pDC)
{
	CXxx2Doc* pDoc = GetDocument();
        ASSERT_VALID(pDoc);
	if (!pDoc)
		return;

	pDC->SetTextColor(RGB(0,0,235));
	pDC->SetBkMode(TRANSPARENT);
	CFont font;
	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;
	RECT r;
	GetClientRect(&r); //获得窗口
	if(n>r.right-r.left) //窗口如果n> 右坐标减去左坐标
	   n=0;  
} 

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

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

void CXxx2View::OnLButtonDblClk(UINT nFlags, CPoint point) 
{  // 鼠标左双击函数
   // TODO: Add your message handler code here and/or call default
      SetTimer(1,500,NULL);
      CView::OnLButtonDblClk(nFlags, point);
}
void CXxx2View::OnRButtonDblClk(UINT nFlags, 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);
}
5.    使用计算数据画直方图

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的实现部分:

// CPlotDoc commands
double Max::Max2(double a, double b)
{
     if(a>=b) return a;
     else return b;
}
Max::Max(double a, double b, double c, double d)
{
     x1=a;x2=b;x3=c;x4=d;
}
double Max::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增加调用语句准备数据
BOOL CPlotDoc::OnNewDocument()
{
     if (!CDocument::OnNewDocument())
	return FALSE;
     // TODO: add reinitialization code here
     // (SDI documents will reuse this document)
     Find();		//增加的语句
     return TRUE;
}

6. 在视类中画图写字

void CPlotView::OnDraw(CDC* pDC)
{
     CPlotDoc* pDoc = GetDocument();
     ASSERT_VALID(pDoc);
     // TODO: add draw code for 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);<pre name="code" class="cpp">
     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
     }<pre name="code" class="cpp">     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.      运行程序,结果如下:

         

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

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

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

       

2.   初始界面如下:

      

3.   在Form上添加控件

      

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

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

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

class CSerialRectDoc : public CDocument
{
     protected: // create from serialization only
	       CSerialRectDoc();
	       DECLARE_DYNCREATE(CSerialRectDoc)
// Attributes
     public:
	      int x1, y1, x2, y2;
// Operations
}

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

CSerialRectDoc::CSerialRectDoc()
{
     // TODO: add one-time construction code here
     x1=y1=x2=y2=0;
}

8.     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);
}

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

void CSerialRectDoc::Serialize(CArchive& ar)
{
     if (ar.IsStoring())
     {
	// TODO: add storing code here
	ar<<x1<<y1<<x2<<y2;
     }
     else
     {
	// TODO: add loading code here
	ar>>x1>>y1>>x2>>y2;
     }
}

10.    为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);
}
7.    单文档串行化编程之二

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

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

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

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

          

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

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

struct Date
{
     int m_nYear;
     int m_nMonth;
     int m_nDay;
};
#include "DateDialog.h"
class CSerialDateDoc : public CDocument
{
protected: // create from serialization only
     CSerialDateDoc();
     DECLARE_DYNCREATE(CSerialDateDoc)
// Attributes
public:
     Date date;
}

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

        6.    在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<<date.m_nYear <<date.m_nMonth <<date.m_nDay ;
     }
     else
     {		
        ar>>date.m_nYear >>date.m_nMonth >>date.m_nDay ;
     }
}

void CSerialDateDoc::OnEditModify() 
{
     CDateDialog dlg;
     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);//关闭窗口时提示存盘
}

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

void CSerialDateView::OnDraw(CDC* pDC)
{
     CSerialDateDoc* pDoc = GetDocument();
     ASSERT_VALID(pDoc);
     CString str;
     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);
}

整理自百度文库。



  • 2
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值