mfc实现画板功能

首先在view.h文件里面进行声明

// 操作
public:
    int m_PenSize;//画笔
    COLORREF m_PenColor, m_BrushColor;//填充
    CPoint m_PointBegin, m_PointEnd;//画圆

    enum class DrawType {
        LineSegment,Circle,Rectangle,Ellips,Pencil,Text,Eraser,myLoadImage,Magnify
    }m_DrawType;//绘制功能

    int m_TextId;
    CEdit* m_Edit = nullptr;
    CPoint m_TextPos = CPoint(0, 0);//设置文本框初值

    CPoint m_MagnifyCenter = CPoint(0, 0);
    int m_MagnifyWidth = 600;
    int m_MagnifyHeight = 400;//设置放大框的初值

在生成的消息映射函数中加入

CRect* GetMagnifyRect(CPoint&);

接下来在view.cpp文件中进行操作 

首先依旧是对画笔功能进行初始化

CMFCTest1View::CMFCTest1View() 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::LineSegment;
     m_TextId = 10086;
}

CMFCTest1View::~CMFCTest1View()
{
    if (m_Edit != nullptr) {
        delete m_Edit;
        m_Edit = nullptr;
    }

 在解决方案资源管理器中的资源文件找到.rc后缀文件,点开后在找到Menu,再点击其中的内容,设置按钮,如下图所示:

设置好按钮后依次为各项功能添加事件处理程序,此时在view.cpp文件中会产生相应函数

我们为每项功能的函数进行补充

 //绘制线条

void CMFCTest1View::OnDrawLineSegment()
{
    m_DrawType = DrawType::LineSegment;
    // TODO: 在此添加命令处理程序代码
}

 //绘制长方形
void CMFCTest1View::OnDrawRectangle()
{
    m_DrawType = DrawType::Rectangle;
    // TODO: 在此添加命令处理程序代码
}

 //绘制圆
void CMFCTest1View::OnDrawCircle()
{
    m_DrawType = DrawType::Circle;
    // TODO: 在此添加命令处理程序代码
}

 //绘制椭圆
void CMFCTest1View::OnDrawEllipse()
{
    m_DrawType = DrawType::Ellips;
    // TODO: 在此添加命令处理程序代码
}

 //选择颜色
void CMFCTest1View::OnSetColor()
{
    // TODO: 在此添加命令处理程序代码
    CColorDialog dlg;
    if (IDOK == dlg.DoModal()) {
        m_PenColor = dlg.GetColor();

    }
}

 //设置尺寸
void CMFCTest1View::OnSetPenSize()
{
    // TODO: 在此添加命令处理程序代码
    CSetPenSizeDialog dlg;
    if (IDOK == dlg.DoModal()) {
        this->m_PenSize = dlg.m_PenSize;
    }
}

 //绘制文本框
void CMFCTest1View::OnText()
{
    m_DrawType = DrawType::Text;
    // TODO: 在此添加命令处理程序代码
}

 //传递文本框内容
BOOL CMFCTest1View::PreTranslateMessage(MSG* pMsg)
{
    // TODO: 在此添加专用代码和/或调用基类
    if (pMsg->message == WM_KEYDOWN && pMsg->wParam == VK_RETURN)
    {
        if (m_DrawType == DrawType::Text)
        {
            CString pStr;
            m_Edit->GetWindowTextW(pStr);
            delete m_Edit;
            m_Edit = nullptr;

            CClientDC dc(this);
            dc.TextOutW(m_TextPos.x, m_TextPos.y, pStr);

            return TRUE;
        }
        
    }

    return CView::PreTranslateMessage(pMsg);
}

 //创建画笔

void CMFCTest1View::OnSetPencil()
{
    // TODO: 在此添加命令处理程序代码
    m_DrawType = DrawType::Pencil;
}

 //创建橡皮擦
void CMFCTest1View::OnSetEraser()
{
    // TODO: 在此添加命令处理程序代码
    m_DrawType = DrawType::Eraser;
}

 //打开文件
void CMFCTest1View::OnFileOpen()
{
    // TODO: 在此添加命令处理程序代码
    m_DrawType = DrawType::myLoadImage;

    CString filter, strPath;
    filter = "bmp图片(*.bmp)|*.bmp||";
    CFileDialog dlg(TRUE, NULL, NULL, OFN_HIDEREADONLY, filter);
    if (dlg.DoModal() == IDOK)
    {
        strPath = dlg.GetPathName();
    }

    HBITMAP hBitmap = (HBITMAP)::LoadImage(NULL, strPath,IMAGE_BITMAP,0,0,
        LR_DEFAULTCOLOR | LR_CREATEDIBSECTION | LR_LOADFROMFILE);

    CBitmap loadImageBitmap;
    loadImageBitmap.Attach(hBitmap);

    BITMAP bitMap;
    loadImageBitmap.GetBitmap(&bitMap);

    CBrush newBrush, * oldBrush;
    newBrush.CreatePatternBrush(&loadImageBitmap);
    
    CClientDC dc(this);
    oldBrush = (CBrush*)dc.SelectObject(&newBrush);

    dc.Rectangle(0, 0, bitMap.bmWidth, bitMap.bmHeight);
    
    dc.SelectObject(oldBrush);
}

 //放大框功能
void CMFCTest1View::OnMagnify()
{
    // TODO: 在此添加命令处理程序代码
    m_DrawType = DrawType::Magnify;
}

//设置放大框属性

CRect* CMFCTest1View::GetMagnifyRect(CPoint& p_Msg)
{
    CRect rect;
    GetClientRect(&rect);

    CPoint leftTop, rightBottom;
    leftTop.x = p_Msg.x - m_MagnifyWidth / 2;
    rightBottom.x = p_Msg.x + m_MagnifyWidth / 2;
    leftTop.y = p_Msg.y - m_MagnifyHeight / 2;
    rightBottom.y = p_Msg.y + m_MagnifyHeight / 2;

    if (leftTop.x < 0) {
        leftTop.x = 0;
        rightBottom.x = leftTop.x + m_MagnifyWidth;
    }
    else if (rightBottom.x > rect.right) {
        rightBottom.x = rect.right;
        leftTop.x = rightBottom.x - m_MagnifyWidth;
    }
    if (leftTop.y < 0) {
        leftTop.y = 0;
        rightBottom.y = leftTop.y + m_MagnifyHeight;
    }
    else if (rightBottom.y > rect.bottom) {
        rightBottom.y = rect.bottom;
        leftTop.y = rightBottom.y - m_MagnifyHeight;
    }
        
    CRect* r_Rect = new CRect(leftTop, rightBottom);

    return r_Rect;
}

 根据以下代码添加相应类向导,其作用是在鼠标按下、移动、松开时绘制出相应功能的线条、文本框等

void CMFCTest1View::OnLButtonDown(UINT nFlags, CPoint point)
{
    // TODO: 在此添加消息处理程序代码和/或调用默认值
    m_PointBegin = m_PointEnd = point;
    m_TextPos = point;
    m_MagnifyCenter = point;

    switch (m_DrawType) {
        case DrawType::Magnify:
        {
            CClientDC dc(this);
            dc.SetROP2(R2_NOTXORPEN);

            CPen newPen, * oldPen;
            newPen.CreatePen(PS_SOLID, m_PenSize, m_PenColor);
            oldPen = dc.SelectObject(&newPen);

            dc.SelectStockObject(5);

            CRect* rectUndraw = GetMagnifyRect(m_MagnifyCenter);
            dc.Rectangle(rectUndraw);

            dc.SelectObject(oldPen);
            delete rectUndraw;

            break;
        }
    }
    CView::OnLButtonDown(nFlags, point);
}


void CMFCTest1View::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::LineSegment:

            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::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;

        }

        case DrawType::Text:
        {
            if (m_Edit != nullptr ) {
                delete m_Edit;
            }

            CEdit* myEdit = new CEdit();//新建edit对象
            myEdit->Create(WS_CHILD | WS_VISIBLE | WS_BORDER, CRect(m_PointBegin, point), this, m_TextId);//设置文本框模式

            m_Edit = myEdit;
            myEdit->ShowWindow(SW_SHOW);


            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::Magnify:
        {
            dc.SetROP2(R2_NOTXORPEN);
            dc.SelectStockObject(5);

            CRect* rectUndraw = GetMagnifyRect(m_MagnifyCenter);
            dc.Rectangle(rectUndraw);
            delete rectUndraw;

            CRect* rectDraw = GetMagnifyRect(point);
            dc.Rectangle(rectDraw);
            delete rectDraw;

            m_MagnifyCenter = point;

            break;
        }

        default:

            break;
        }
        dc.SelectObject(oldPen);
    }

    CView::OnMouseMove(nFlags, point);
}


void CMFCTest1View::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::LineSegment:

        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::Ellips:
    {
        dc.SelectStockObject(PS_NULL);
        CRect rectP2(m_PointBegin, point);
        dc.Ellipse(rectP2);

        break;
    }

    case DrawType::Circle:
    {
        dc.SelectStockObject(5);

        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;

    }

    case DrawType::Text:
    {
        CEdit* myEdit = new CEdit();//新建edit对象
        myEdit->Create(WS_CHILD | WS_VISIBLE | WS_BORDER, CRect(m_PointBegin, point), this, m_TextId);//设置文本框模式
        myEdit->ShowWindow(SW_SHOW);

        if (nullptr != m_Edit) {
            delete m_Edit;
        }

        m_Edit = myEdit;

        break;
    }
        
    case DrawType::Magnify:
    {
        dc.SetROP2(R2_NOTXORPEN);
        dc.SelectStockObject(5);

        CRect* rectUndraw = GetMagnifyRect(m_MagnifyCenter);
        dc.Rectangle(rectUndraw);

        CRect rect;
        GetClientRect(&rect);

        CDC * pDC = GetDC();
        dc.StretchBlt(0, 0, rect.Width(), rect.Height(), pDC, rectUndraw->left, rectUndraw->top, rectUndraw->Width(), rectUndraw->Height(), SRCCOPY);


        delete rectUndraw;
        ReleaseDC(pDC);
        break;
    }

    default:

        break;
    }

    oldPen = dc.SelectObject(oldPen);
    CView::OnLButtonUp(nFlags, point);
}

最后让我们一起看看功能实现的样子

放大后效果图

  • 3
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 9
    评论
评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值