MFC---画图中的重绘操作整合
  5Z6Aj0LQwRjK 2023年12月10日 53 0


前面开发的应用中,如果调整窗口大小,会发现前面画线条,矩形等都不见,这是为什么呢?这里的原因是,当调整窗口大小时,窗口会收到WM_PAINT消息,即OS通过应用程序,需要对应用界面进行重绘。

使用元文件(画笔模式有闪烁异常)

Metafile是记录所有"绘图指令"的集合,拥有录制,重放的功能
•draw3view类中定义成员变量并在构造函数中初始化

// draw3view.h
CMetaFileDC m_dcMetaFile;
Cdraw3View::Cdraw3View() noexcept
{
    // TODO: 在此处添加构造代码
    ...
    m_dcMetaFile.Create();
}

•在画图的位置替换原有的DC
•在OnDraw函数中播放元文件,以实现重绘效果

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

    // TODO: 在此处为本机数据添加绘制代码
    HMETAFILE metaFile;
    // 结束录制,得到元文件
    metaFile = m_dcMetaFile.Close();
    // 在DC中播放元文件
    pDC->PlayMetaFile(metaFile);
    // 开始新的录制
    m_dcMetaFile.Create();
    // 在新的录制文件中重放前一个录制文件
    m_dcMetaFile.PlayMetaFile(metaFile);
    // 删除前一个录制文件
    DeleteMetaFile(metaFile);
}

使用兼容设备描述表(画笔模式有闪烁异常)

兼容设备是一种内存设备,在显示图像的过程中,可以先在内存中准备这些图像,之后可以直接拷贝内存数据到真实的设备中,完成图像的显示。
•draw3view类中定义成员变量并在构造函数中初始化

// draw3view.h
CDC m_dcCompatible;

•初始化兼容设备表(二次缓冲)

if (!m_dcCompatible.m_hDC)
    {
        // 创建兼容DC
        m_dcCompatible.CreateCompatibleDC(&dc);
        CRect rect;
        // 获得客户区大小
        GetClientRect(&rect);
        CBitmap bitmap;
        // 创建兼容Bitmap,与客户区大小一致
        bitmap.CreateCompatibleBitmap(&dc, rect.Width(), rect.Height());
        // 兼容DC选入兼容bitmap
        m_dcCompatible.SelectObject(&bitmap);
        // 兼容DC填充指定颜色
        m_dcCompatible.FillSolidRect(rect, RGB(255,255,255));
    }

•画图位置替换原有的DC
•在OnDraw函数中复制兼容DC到真实DC上

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

    // TODO: 在此处为本机数据添加绘制代码
    CRect rect;
    // 获得客户区的大小
    GetClientRect(&rect);
    // 复制兼容DC的内容到真实DC上,实现绘制效果
    pDC->BitBlt(0, 0, rect.Width(), rect.Height(), &m_dcCompatible, 0, 0, SRCCOPY);
}

使用自定义类存储绘图数据(所有功能均正常)

•仿元文件机制,记录绘图过程中关键信息

class Graph :
    public CObject
{
public:
    Graph(UINT drawType);
    void AddPoint(CPoint point);
    void AddPoint(CPoint start, CPoint end);
    void Draw(CDC* pDC);

public:
    // 形状
    UINT m_nDrawType;
    // 点的集合
    CArray<CPoint> m_pPoints;
};

MFC---画图中的重绘操作整合_mfc

MFC定义的集合类

•模板集合类
CArray/CList/CMap
•非模板集合类
–数组
CObArray/CByteArray/CDWordArray/CPtrArray/CStringArray/CWordArray/CUIntArray
–链表
CObList/CPtrList/CStringList
–映射

使用Graph对象记录关键信息

在Draw3view.h添加成员变量

// 记录所有Graph对象的数组
CObArray m_pGraphs;
// 当前的画笔对象
Graph* m_TmpGraph;

在鼠标左键弹起的响应函数中处理画线,画矩形,画椭圆的信息

void Cdraw3View::OnLButtonUp(UINT nFlags, CPoint point)
{
    ...
    if (m_DrawType != DT_PEN)
    {
        Graph *graph = new Graph(m_DrawType);
        graph->AddPoint(m_pOrigin, point);
        m_pGraphs.Add(graph);
    }
    else {
        m_TmpGraph->AddPoint(point);
        m_pGraphs.Add(m_TmpGraph);
    }
    ...
}

在鼠标左键按下响应函数中添加对画笔的处理

void Cdraw3View::OnLButtonDown(UINT nFlags, CPoint point)
{
    // TODO: 在此添加消息处理程序代码和/或调用默认值
    // 保存起点到成员变量
    m_pOrigin = point;
    
    if (m_DrawType == DT_PEN)
    {
        m_bDraw = TRUE;
        m_TmpGraph = new Graph(DT_PEN);
        m_TmpGraph->AddPoint(point);
    }

    CView::OnLButtonDown(nFlags, point);
}

在鼠标移动的响应函数中添加对画笔的处理

void Cdraw3View::OnMouseMove(UINT nFlags, CPoint point)
{
    // TODO: 在此添加消息处理程序代码和/或调用默认值
    if (m_DrawType == DT_PEN && m_bDraw == TRUE)
    {
        ...
        m_TmpGraph->AddPoint(point);
        ...
    }
}

在OnDraw函数中实现重绘工作

void Cdraw3View::OnDraw(CDC* pDC)
{
    // TODO: 在此处为本机数据添加绘制代码
    for (int i = 0; i < m_pGraphs.GetSize(); i++)
    {
        Graph* gh = (Graph*)m_pGraphs.GetAt(i);
        gh->Draw(pDC);
    }
}

清理工作

Cdraw3View::~Cdraw3View()
{
    int cnt = m_pGraphs.GetSize();
    // 从数组末尾开始遍历,依次释放元素空间
    while (cnt--)
    {
        delete m_pGraphs.GetAt(cnt);
    }
    // 清空数组
    m_pGraphs.RemoveAll();
}

补充

要想记录画笔的所有信息

#pragma once

// Graph 命令目标

class Graph : public CObject
{
public:
	Graph(UINT drawtype,UINT lineStyle,UINT lineWidth,COLORREF color);
	//添加点到数组
	void AddPoint(CPoint point);
	void AddPoint(CPoint start,CPoint end);
	void Draw(CDC* pDC);

	virtual ~Graph();


public:
	//绘制类型
	UINT m_nDrawType;
	UINT m_nLineStyle;
	UINT m_nLineWidth;
	COLORREF m_color;
	//点的数组
	CArray<CPoint> m_Points;


};

每次作画的时候更改画笔

```cpp
	CPen pen(m_nLineStyle,m_nLineWidth,m_color);
	CPen* pOldPen=pDC->SelectObject(&pen);
	pDC->SelectObject(pOldPen);

MFC---画图中的重绘操作整合_c++_02

MFC—用局部变量的引用导致程序崩溃的解决办法


【版权声明】本文内容来自摩杜云社区用户原创、第三方投稿、转载,内容版权归原作者所有。本网站的目的在于传递更多信息,不拥有版权,亦不承担相应法律责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@moduyun.com

  1. 分享:
最后一次编辑于 2023年12月10日 0

暂无评论

推荐阅读
5Z6Aj0LQwRjK