广州大学面向对象程序设计实验五

广州大学学生实验报告

开课实验室:计算机科学与工程实验(电子楼418A)   2023年5月25

学院

计算机科学与网络工程学院

年级、专业、班

姓名

学号

实验课程

面向对象程序设计

成绩

实验项目

实验五  综合应用程序

指导老师

一、实验目的:

本实验是对前面所学知识的总结,通过一个比较完整的应用程序的设计,将学过的知识连贯起来,掌握开发一个实际应用程序的步骤,同时学会使用开发工具实现界面友好的应用程序。并通过本实验,掌握如何运用面向对象技术对具体的应用系统进行分析和设计。

1、类和对象的定义、对象的初始化和使用

2、面向对象的特征的应用:封装、继承和多态

3、可视化程序设计中资源的运用

4、Windows的消息传递机制

5、MFC类库的使用

6、算法的使用

二、使用仪器、器材

微机一台

操作系统:WinXP

编程软件:C++

三、实验内容及原理

利用文档/视图结构创建一个绘图板,实现用鼠标画线等功能,该画板至少要实现以下3个功能:

  1. 可以用不同的线宽和颜色画图

2)可以修改所绘制图形的线宽和颜色,效果如下图。

3)可以存储所绘制的图形。

// MyPaintView.h: CMyPaintView 类的接口

//

#pragma once

class CMyPaintView : public CView

{

protected: // 仅从序列化创建

    CMyPaintView() noexcept;

    DECLARE_DYNCREATE(CMyPaintView)

// 特性

public:

    CMyPaintDoc* GetDocument() const;

// 操作

public:

    int m_PenSize;

    COLORREF m_PenColor, m_BrushColor;

    CPoint m_PointBegin, m_PointEnd;

    enum class DrawType {

        LineSetgment, Circle, Rectangle, Ellips, Pencil, Eraser

    }m_DrawType;

// 重写

public:

    virtual void OnDraw(CDC* pDC);  // 重写以绘制该视图

    virtual BOOL PreCreateWindow(CREATESTRUCT& cs);

protected:

    virtual BOOL OnPreparePrinting(CPrintInfo* pInfo);

    virtual void OnBeginPrinting(CDC* pDC, CPrintInfo* pInfo);

    virtual void OnEndPrinting(CDC* pDC, CPrintInfo* pInfo);

// 实现

public:

    virtual ~CMyPaintView();

#ifdef _DEBUG

    virtual void AssertValid() const;

    virtual void Dump(CDumpContext& dc) const;

#endif

protected:

// 生成的消息映射函数

protected:

    DECLARE_MESSAGE_MAP()

public:

    afx_msg void OnLButtonDown(UINT nFlags, CPoint point);

    afx_msg void OnMouseMove(UINT nFlags, CPoint point);

    afx_msg void OnLButtonUp(UINT nFlags, CPoint point);

    afx_msg void OnDrawLineSegment();

    afx_msg void OnDrawRectangle();

    afx_msg void OnDrawCircle();

    afx_msg void OnDrawEllips();

    afx_msg void OnSetPencil();

    afx_msg void OnSetEraser();

    afx_msg void OnSetColor();

    afx_msg void OnSetPenSize();

    afx_msg void OnFileSave();

};

#ifndef _DEBUG  // MyPaintView.cpp 中的调试版本

inline CMyPaintDoc* CMyPaintView::GetDocument() const

   { return reinterpret_cast<CMyPaintDoc*>(m_pDocument); }

#endif

// MyPaintView.cpp: CMyPaintView 类的实现

//

#include "pch.h"

#include "framework.h"

// SHARED_HANDLERS 可以在实现预览、缩略图和搜索筛选器句柄的

// ATL 项目中进行定义,并允许与该项目共享文档代码。

#ifndef SHARED_HANDLERS

#include "MyPaint.h"

#endif

#include "MyPaintDoc.h"

#include "MyPaintView.h"

#include "resource.h"

#include "CSetPenSizeDialog.h"

#ifdef _DEBUG

#define new DEBUG_NEW

#endif

// CMyPaintView

IMPLEMENT_DYNCREATE(CMyPaintView, CView)

BEGIN_MESSAGE_MAP(CMyPaintView, CView)

    // 标准打印命令

    ON_COMMAND(ID_FILE_PRINT, &CView::OnFilePrint)

    ON_COMMAND(ID_FILE_PRINT_DIRECT, &CView::OnFilePrint)

    ON_COMMAND(ID_FILE_PRINT_PREVIEW, &CView::OnFilePrintPreview)

    ON_WM_LBUTTONDOWN()

    ON_WM_MOUSEMOVE()

    ON_WM_LBUTTONUP()

    ON_COMMAND(1, &CMyPaintView::OnDrawLineSegment)

    ON_COMMAND(2, &CMyPaintView::OnDrawRectangle)

    ON_COMMAND(3, &CMyPaintView::OnDrawCircle)

    ON_COMMAND(4, &CMyPaintView::OnDrawEllips)

    ON_COMMAND(5, &CMyPaintView::OnSetPencil)

    ON_COMMAND(6, &CMyPaintView::OnSetEraser)

    ON_COMMAND(7, &CMyPaintView::OnSetPenSize)

    ON_COMMAND(8, &CMyPaintView::OnSetColor)

    ON_COMMAND(9, &CMyPaintView::OnFileSave)

   

END_MESSAGE_MAP()

// CMyPaintView 构造/析构

CMyPaintView::CMyPaintView() noexcept

{

    // TODO: 在此处添加构造代码

    m_PenSize = 1;

    m_PenColor = RGB(0, 0, 0),

        m_BrushColor = RGB(0, 0, 0);

    m_PointBegin = CPoint(0, 0);

    m_PointEnd = CPoint(0, 0);

    m_DrawType = DrawType::LineSetgment;

}

CMyPaintView::~CMyPaintView()

{

}

BOOL CMyPaintView::PreCreateWindow(CREATESTRUCT& cs)

{

    // TODO: 在此处通过修改

    //  CREATESTRUCT cs 来修改窗口类或样式

    return CView::PreCreateWindow(cs);

}

// CMyPaintView 绘图

void CMyPaintView::OnDraw(CDC* /*pDC*/)

{

    CMyPaintDoc* pDoc = GetDocument();

    ASSERT_VALID(pDoc);

    if (!pDoc)

        return;

    // TODO: 在此处为本机数据添加绘制代码

}

// CMyPaintView 打印

BOOL CMyPaintView::OnPreparePrinting(CPrintInfo* pInfo)

{

    // 默认准备

    return DoPreparePrinting(pInfo);

}

void CMyPaintView::OnBeginPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)

{

    // TODO: 添加额外的打印前进行的初始化过程

}

void CMyPaintView::OnEndPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)

{

    // TODO: 添加打印后进行的清理过程

}

// CMyPaintView 诊断

#ifdef _DEBUG

void CMyPaintView::AssertValid() const

{

    CView::AssertValid();

}

void CMyPaintView::Dump(CDumpContext& dc) const

{

    CView::Dump(dc);

}

CMyPaintDoc* CMyPaintView::GetDocument() const // 非调试版本是内联的

{

    ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CMyPaintDoc)));

    return (CMyPaintDoc*)m_pDocument;

}

#endif //_DEBUG

// CMyPaintView 消息处理程序

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

{

    // TODO: 在此添加消息处理程序代码和/或调用默认值

    m_PointBegin = m_PointEnd = point;

    /*CClientDC dc(this);

    dc.MoveTo(m_PointBegin);

    dc.LineTo(m_PointEnd);

*/

    CView::OnLButtonDown(nFlags, point);

    CView::OnLButtonDown(nFlags, point);

}

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

{

    // TODO: 在此添加消息处理程序代码和/或调用默认值

    if (nFlags & MK_LBUTTON)

    {

        //定义新笔和旧笔的指针

        CClientDC dc(this);

        CPen newPen, * oldPen;

        newPen.CreatePen(PS_SOLID, m_PenSize, m_PenColor);

        oldPen = dc.SelectObject(&newPen);

        switch (m_DrawType)

        {

        case DrawType::LineSetgment:

        {

             dc.SetROP2(R2_NOTXORPEN);

             dc.MoveTo(m_PointBegin);

             dc.LineTo(m_PointEnd);

             dc.MoveTo(m_PointBegin);

             dc.LineTo(point);

             m_PointEnd = point;

             break;

        }

        case DrawType::Rectangle:

        {dc.SetROP2(R2_NOTXORPEN);

        dc.SelectStockObject(5);

        CRect rectP1(m_PointBegin, m_PointEnd);

        dc.Rectangle(rectP1);

        CRect rectP2(m_PointBegin, point);

        dc.Rectangle(rectP2);

        m_PointEnd = point;

        break;

        }

        case DrawType::Pencil:

        {

             m_PointBegin = m_PointEnd;

             m_PointEnd = point;

             dc.MoveTo(m_PointBegin);

             dc.LineTo(m_PointEnd);

             break;

        }

        case DrawType::Eraser:

        {

             COLORREF pColor = dc.GetBkColor();

             CPen newPen(PS_SOLID, m_PenSize, pColor);

             dc.SelectObject(&newPen);

             m_PointBegin = m_PointEnd;

             m_PointEnd = point;

             dc.MoveTo(m_PointBegin);

             dc.LineTo(m_PointEnd);

             break;

        }

        case DrawType::Ellips:

        {dc.SetROP2(R2_NOTXORPEN);

        dc.SelectStockObject(5);

        CRect rectP1(m_PointBegin, m_PointEnd);

        dc.Ellipse(rectP1);

        CRect rectP2(m_PointBegin, point);

        dc.Ellipse(rectP2);

        m_PointEnd = point;

        break;

        }

        case DrawType::Circle:

        {

             dc.SetROP2(R2_NOTXORPEN);

             dc.SelectStockObject(5);

             int length_1 = m_PointEnd.y - m_PointBegin.y;

             if (m_PointEnd.x < m_PointBegin.x)

             {

                 m_PointEnd.x = m_PointBegin.x - abs(length_1);

             }

             else

             {

                 m_PointEnd.x = m_PointBegin.x + abs(length_1);

             }

             CRect rectP1(m_PointBegin, m_PointEnd);

             dc.Ellipse(rectP1);

             int length_2 = point.y - m_PointBegin.y;

             if (point.x < m_PointBegin.x)

             {

                 m_PointEnd.x = m_PointBegin.x - abs(length_2);

             }

             else

             {

                 m_PointEnd.x = m_PointBegin.x + abs(length_2);

             }

             m_PointEnd.y = point.y;

             CRect rectP2(m_PointBegin, m_PointEnd);

             dc.Ellipse(rectP2);

             m_PointEnd = point;

             break;

        }

        default:

             break;

        }

        dc.SelectObject(oldPen);

    }

    CView::OnMouseMove(nFlags, point);

}

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

{

    // TODO: 在此添加消息处理程序代码和/或调用默认值

    CClientDC dc(this);

    CPen newPen, * oldPen;

    newPen.CreatePen(PS_SOLID, m_PenSize, m_PenColor);

    oldPen = dc.SelectObject(&newPen);

    switch (m_DrawType)

    {

    case DrawType::LineSetgment:

    {

        dc.MoveTo(m_PointBegin);

        dc.LineTo(point);

        break;

    }

    case DrawType::Rectangle:

    {

        dc.SelectStockObject(PS_NULL);

        CRect rectP2(m_PointBegin, point);

        dc.Rectangle(rectP2);

        break;

    }

    case DrawType::Pencil:

    {

        m_PointBegin = m_PointEnd;

        m_PointEnd = point;

        dc.MoveTo(m_PointBegin);

        dc.LineTo(m_PointEnd);

        break;

    }

    case DrawType::Ellips:

    {

        dc.SelectStockObject(PS_NULL);

        CRect rectP2(m_PointBegin, point);

        dc.Ellipse(rectP2);

        break;

    }

    default:

        break;

    }

    dc.SelectObject(oldPen);

    CView::OnLButtonUp(nFlags, point);

}

void CMyPaintView::OnDrawLineSegment()

{

    m_DrawType = DrawType::LineSetgment;

    // TODO: 在此添加命令处理程序代码

}

void CMyPaintView::OnDrawRectangle()

{

    // TODO: 在此添加命令处理程序代码

    m_DrawType = DrawType::Rectangle;

}

void CMyPaintView::OnDrawCircle()

{

    // TODO: 在此添加命令处理程序代码

    m_DrawType = DrawType::Circle;

}

void CMyPaintView::OnDrawEllips()

{

    // TODO: 在此添加命令处理程序代码

    m_DrawType = DrawType::Ellips;

}

void CMyPaintView::OnSetColor()

{

    // TODO: 在此添加命令处理程序代码

    CColorDialog dlg;

    if (IDOK == dlg.DoModal()) {

        m_PenColor = dlg.GetColor();

    }

}

void CMyPaintView::OnSetPenSize()

{

    // TODO: 在此添加命令处理程序代码

    CSetPenSizeDialog dlg;

    if (IDOK == dlg.DoModal())

    {

        this->m_PenSize = dlg.m_PenSize2;

    }

}

void CMyPaintView::OnSetPencil()

{

    // TODO: 在此添加命令处理程序代码

    m_DrawType = DrawType::Pencil;

}

void CMyPaintView::OnSetEraser()

{

    // TODO: 在此添加命令处理程序代码

    m_DrawType = DrawType::Eraser;

}

//添加事件处理程序,生成函数OnFileSave() :

    void CMyPaintView::OnFileSave()

{

    CClientDC dc(this);

    CRect rect;

    BOOL  showMsgTag;   //是否要弹出”图像保存成功对话框"

    BOOL saveTag;

    CString saveFilePath;

    GetClientRect(&rect);                  //获取画布大小

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

    //创建兼容位图

    HDC hdc = CreateCompatibleDC(dc);      //创建兼容DC,以便将图像保存为不同的格式

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

    //将位图选入DC,并保存返回值

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

    //将屏幕DC的图像复制到内存DC中

    CImage image;

    image.Attach(hbitmap);                //将位图转化为一般图像

    saveTag = FALSE;

    if (!saveTag)                      //如果图像是第一次被写入,则打开对话框

    {

        showMsgTag = TRUE;

        CString  strFilter = _T("位图文件|*.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)               //扩展名项目为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;

             default:

                 break;

             }

             strFileName = strFileName + "." + strExtension;

        }

        saveFilePath = strFileName;     //saveFilePath为视类中的全局变量,类型为CString

    }

    else

    {

        showMsgTag = FALSE;

    }

    //AfxMessageBox(saveFilePath);               //显示图像保存的全路径(包含文件名)

    HRESULT hResult = image.Save(saveFilePath);     //保存图像

    if (FAILED(hResult))

    {

        MessageBox(_T("保存图像文件失败!"));

    }

    else

    {

        if (showMsgTag)

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

    }

    image.Detach();

    SelectObject(hdc, hOldMap);

}

  • 实验过程原始数据记录

实现功能如下:

(1)可以选择绘制多种图

(2)可以擦除所绘内容

(3)能够用选择不同颜色绘制图案

(4)能够调整画笔的粗细

(6)可以存储所绘制的图形

   

五、实验结果及分析

个人小结:

这个项目是一个基于MFC多文档的桌面应用程序,完成这个项目除了增加了对C++面向对象编程的理解,同时也加深了对MFC的理解,在整个过程中我侧重于把握前者。我的C++知识不怎么完善,写完整个项目的感觉像搭积木,而且对类中一些限定词(如constoverridevirtualprotected),指针引用和STL中的容器对象不怎么理解,所以这一次重在把握程序设计的整体架构,加深理解面向对象继承和成员函数重载等概念,同时加深了对MFC的了解。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值