65.9K
CodeProject 正在变化。 阅读更多。
Home

CCanvas - 用于绘制简单图形的可重用类

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.71/5 (21投票s)

2009年2月1日

公共领域

2分钟阅读

viewsIcon

92991

downloadIcon

5049

一个用于绘制简单图形的可重用类

引言

实际上,我有点紧张地介绍这篇文章。这是我第一次使用MFC。在这里,我制作了一个可复用的类,能够通过使用GDI设备上下文编程来绘制诸如矩形、椭圆、圆和线等对象。这些对象是可选择、可移动和可调整大小的。它被命名为CCanvas。我希望它对您有所帮助。您可以在需要简单图形编辑器的项目中使用它。

Using the Code

类方法

这里有一些public方法

  • bool loadFile(char *fileName);

    加载文件。

  • bool saveFile(char *fileName);

    保存文件。

  • void set(CPoint ptStart, CPoint ptEnd);

    检索鼠标拖动时的起始和结束位置。

  • set(int tool);

    设置活动工具:绘制矩形、绘制椭圆、绘制圆或擦除。

  • int update(CDC *dc);

    更新窗口。

  • void store();

    将对象存储到内存中。

  • void drawGrid(CDC *dc, HWND hwnd, int gridsizeX, int gridsizeY)();

    在指定大小内绘制网格。

  • void setSnapToGrid(bool setting, int gridsizeX, int gridsizeY);

    在指定的网格大小内设置吸附到网格选项。

工作原理

它通过处理这三个重要的消息来工作

  • WM_LBUTTONDOWN - 开始绘图,记住鼠标指针的原始位置
  • WM_MOUSEMOVE - 在这里它跟踪鼠标移动,记住其当前位置
  • WM_LBUTTONUP - 完成绘图,将新创建的对象存储到内存中

如何使用

假设您有一个名为Demo的SDI项目。

  • 将文件"canvas.h"添加到您的DemoView.h

    #include "canvas.h"
  • 将这些变量添加到您的DemoView.h

    private:
        CCanvas m_canvas;
        CPoint m_ptStart;
        CPoint m_ptEnd;
  • 将这些窗口消息添加到您的DemoView.cpp

    BEGIN_MESSAGE_MAP(CDemoView, CView)
        //{{AFX_MSG_MAP(CDemoView)
        ON_WM_MOUSEMOVE()
        ON_WM_LBUTTONUP()
        ON_WM_LBUTTONDOWN()
        //}}AFX_MSG_MAP
    END_MESSAGE_MAP()
  • 将这些代码添加到您的DemoView.cpp 以处理那些窗口消息

    void CDemoView::OnDraw(CDC* dc)
    {
        CNiceDoc* pDoc = GetDocument();
        ASSERT_VALID(pDoc);
    
        m_canvas.update(dc);
    }
    
    BOOL CDemoView::PreCreateWindow(CREATESTRUCT& cs)
    {
        m_canvas.setSnapToGrid(true, 10, 10);
        return CView::PreCreateWindow(cs);
    }
    
    void CDemoView::OnMouseMove(UINT nFlags, CPoint point)
    {
        CView::OnMouseMove(nFlags, point);
    
        // Update end point while mouse is moving
        if (GetCapture() == this){
    	m_ptEnd = point;
    	Invalidate();
    	m_canvas.set(m_ptStart, m_ptEnd);
        }
    }
    
    void CDemoView::OnLButtonDown(UINT nFlags, CPoint point)
    {
        CView::OnLButtonDown(nFlags, point);
    
        // Get start point for drawing
        m_ptStart = m_ptEnd = point;SetCapture();
        m_canvas.set(m_ptStart, m_ptEnd);
    }
    
    void CDemoView::OnLButtonUp(UINT nFlags, CPoint point)
    {
        CView::OnLButtonUp(nFlags, point);
    
        // Get end point for drawing
        if (GetCapture() == this)
        {
            ReleaseCapture();
            m_ptEnd = point;
            Invalidate();
            m_canvas.store();
        }
    }

加载和保存文档

用于加载和保存文档的函数成员在类CDemoDoc中调用,该类存在于文件DemoDoc.hDemoDoc.cpp中。这是一个很长的解释。您可以在演示源代码中自己查看。基本上,它只是一个“您如何处理CDocument”的问题。

闪烁问题 - 双缓冲

为了摆脱闪烁问题,我们可以使用双缓冲方法。看这里。按照步骤操作,您将看到闪烁问题消失。与本文一起提供的演示项目使用了此方法。

关注点

这是我的第一个MFC项目,我仍在改进它。我计划添加更多功能,例如

  • 更多对象形状
  • 旋转
  • 排序(向后和向前)
  • 选择和移动多个对象
  • 着色
  • 等等。

第1次更新

我修复了创建垂直线时的主要错误。您无法对垂直线执行任何操作,它似乎被冻结了。这是因为我在代码中使用了不完整的数学方程式。我还添加了两个新功能:setSnapToGriddrawGrid。我从Johan Rosengren那里改编了用于drawGrid函数的代码。别担心,其余的仍然是原始的,并且保持尽可能简单。除此之外,现在当您进行调整大小时,鼠标光标将根据调整方向而改变。该源代码也已转换为VC++ 2005。我认为VC++6.0已经被放弃了。

历史

  • 2009年1月31日:初始版本
  • 2009年2月25日:第1次更新
© . All rights reserved.