“CPen::CPen(const CPen &)”: 尝试引用已删除的函数
时间: 2023-06-15 20:05:43 浏览: 93
这个错误信息意味着你尝试使用一个已被删除的函数,即拷贝构造函数 `CPen::CPen(const CPen&)`。
这通常是因为你的类中有某个成员变量的类型是不支持拷贝构造函数的,比如一个指针或者一个引用。如果你没有显式地定义拷贝构造函数,编译器会自动生成一个默认的拷贝构造函数,它会简单地将每个成员变量逐个拷贝。但是如果你的类中有不支持拷贝构造函数的成员变量,编译器无法自动生成一个可用的拷贝构造函数,此时你需要自己定义拷贝构造函数来处理这些成员变量。
为了解决这个问题,你需要检查你的类中是否有不支持拷贝构造函数的成员变量,如果有的话,你需要为你的类定义一个自己的拷贝构造函数,来处理这些成员变量的拷贝。
相关问题
mfc完成简单画板程序的设计,要求有:利用 MFC/QT 的向导,创建基于单文档的应用程序;图像互相重叠时,能正确显示图像。给出详细代码
以下是一个基于 MFC 的简单画板程序设计的代码,实现了绘制直线、矩形和椭圆三种基本图形的功能。在图形重叠时,采用了透明度的方式来显示图形。
首先,使用 MFC/QT 的向导创建一个基于单文档的应用程序,然后在 CMyPaintDoc 类中添加以下成员变量和函数:
```c++
class CMyPaintDoc : public CDocument
{
protected:
CObArray m_arrShapes; // 保存图形的数组
int m_nPenWidth; // 画笔宽度
COLORREF m_clrPenColor; // 画笔颜色
public:
// 添加图形的函数
void AddShape(CShape* pShape);
// 获取图形数组的大小
int GetShapeCount() const;
// 获取指定索引处的图形
CShape* GetShape(int nIndex) const;
// 清空图形数组
void ClearShapes();
// 设置画笔宽度
void SetPenWidth(int nWidth);
// 获取画笔宽度
int GetPenWidth() const;
// 设置画笔颜色
void SetPenColor(COLORREF clr);
// 获取画笔颜色
COLORREF GetPenColor() const;
};
```
在 CMyPaintDoc 类的实现文件中,添加以下代码:
```c++
void CMyPaintDoc::AddShape(CShape* pShape)
{
m_arrShapes.Add(pShape);
SetModifiedFlag(); // 文档已被修改,需要保存
}
int CMyPaintDoc::GetShapeCount() const
{
return m_arrShapes.GetSize();
}
CShape* CMyPaintDoc::GetShape(int nIndex) const
{
return (CShape*)m_arrShapes.GetAt(nIndex);
}
void CMyPaintDoc::ClearShapes()
{
for (int i = 0; i < GetShapeCount(); i++)
delete GetShape(i);
m_arrShapes.RemoveAll();
SetModifiedFlag(); // 文档已被修改,需要保存
}
void CMyPaintDoc::SetPenWidth(int nWidth)
{
m_nPenWidth = nWidth;
}
int CMyPaintDoc::GetPenWidth() const
{
return m_nPenWidth;
}
void CMyPaintDoc::SetPenColor(COLORREF clr)
{
m_clrPenColor = clr;
}
COLORREF CMyPaintDoc::GetPenColor() const
{
return m_clrPenColor;
}
```
接下来,在 CMyPaintView 类中添加以下成员变量和函数:
```c++
class CMyPaintView : public CView
{
protected:
CPoint m_ptPrev; // 前一个点
int m_nDrawMode; // 绘制模式
CShape* m_pCurShape; // 当前绘制的图形
public:
CMyPaintDoc* GetDocument() const;
// 绘制直线
void DrawLine(const CPoint& ptFrom, const CPoint& ptTo);
// 绘制矩形
void DrawRect(const CPoint& ptFrom, const CPoint& ptTo);
// 绘制椭圆
void DrawEllipse(const CPoint& ptFrom, const CPoint& ptTo);
// 设置绘制模式
void SetDrawMode(int nMode);
// 获取绘制模式
int GetDrawMode() const;
};
```
在 CMyPaintView 类的实现文件中,添加以下代码:
```c++
CMyPaintDoc* CMyPaintView::GetDocument() const
{
return reinterpret_cast<CMyPaintDoc*>(m_pDocument);
}
void CMyPaintView::DrawLine(const CPoint& ptFrom, const CPoint& ptTo)
{
CDC* pDC = GetDC();
CPen pen(PS_SOLID, GetDocument()->GetPenWidth(), GetDocument()->GetPenColor());
CPen* pOldPen = pDC->SelectObject(&pen);
pDC->MoveTo(ptFrom);
pDC->LineTo(ptTo);
pDC->SelectObject(pOldPen);
ReleaseDC(pDC);
}
void CMyPaintView::DrawRect(const CPoint& ptFrom, const CPoint& ptTo)
{
CDC* pDC = GetDC();
CPen pen(PS_SOLID, GetDocument()->GetPenWidth(), GetDocument()->GetPenColor());
CBrush brush(GetDocument()->GetPenColor());
CBrush* pOldBrush = pDC->SelectObject(&brush);
CPen* pOldPen = pDC->SelectObject(&pen);
pDC->Rectangle(CRect(ptFrom, ptTo));
pDC->SelectObject(pOldBrush);
pDC->SelectObject(pOldPen);
ReleaseDC(pDC);
}
void CMyPaintView::DrawEllipse(const CPoint& ptFrom, const CPoint& ptTo)
{
CDC* pDC = GetDC();
CPen pen(PS_SOLID, GetDocument()->GetPenWidth(), GetDocument()->GetPenColor());
CBrush brush(GetDocument()->GetPenColor());
CBrush* pOldBrush = pDC->SelectObject(&brush);
CPen* pOldPen = pDC->SelectObject(&pen);
pDC->Ellipse(CRect(ptFrom, ptTo));
pDC->SelectObject(pOldBrush);
pDC->SelectObject(pOldPen);
ReleaseDC(pDC);
}
void CMyPaintView::SetDrawMode(int nMode)
{
m_nDrawMode = nMode;
}
int CMyPaintView::GetDrawMode() const
{
return m_nDrawMode;
}
```
最后,在 CShape 类中添加以下成员变量和函数:
```c++
class CShape
{
protected:
CPoint m_ptFrom; // 起点
CPoint m_ptTo; // 终点
int m_nPenWidth; // 画笔宽度
COLORREF m_clrPenColor; // 画笔颜色
public:
CShape(const CPoint& ptFrom, const CPoint& ptTo, int nPenWidth, COLORREF clrPenColor);
virtual ~CShape();
CPoint GetFromPoint() const;
CPoint GetToPoint() const;
int GetPenWidth() const;
COLORREF GetPenColor() const;
virtual void Draw(CDC* pDC) = 0; // 纯虚函数,绘制图形
};
```
在 CShape 类的实现文件中,添加以下代码:
```c++
CShape::CShape(const CPoint& ptFrom, const CPoint& ptTo, int nPenWidth, COLORREF clrPenColor)
{
m_ptFrom = ptFrom;
m_ptTo = ptTo;
m_nPenWidth = nPenWidth;
m_clrPenColor = clrPenColor;
}
CShape::~CShape()
{
}
CPoint CShape::GetFromPoint() const
{
return m_ptFrom;
}
CPoint CShape::GetToPoint() const
{
return m_ptTo;
}
int CShape::GetPenWidth() const
{
return m_nPenWidth;
}
COLORREF CShape::GetPenColor() const
{
return m_clrPenColor;
}
```
然后,分别创建 CLineShape、CRectShape 和 CEllipseShape 类,继承自 CShape 类,实现 Draw 函数,绘制直线、矩形和椭圆图形。
最后,在 CMyPaintView 类中添加以下代码,实现绘制图形和鼠标事件的处理:
```c++
void CMyPaintView::OnDraw(CDC* pDC)
{
CMyPaintDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
if (!pDoc)
return;
for (int i = 0; i < pDoc->GetShapeCount(); i++)
{
CShape* pShape = pDoc->GetShape(i);
ASSERT_VALID(pShape);
if (pShape)
pShape->Draw(pDC);
}
}
void CMyPaintView::OnLButtonDown(UINT nFlags, CPoint point)
{
m_ptPrev = point;
switch (GetDrawMode())
{
case DRAW_LINE:
m_pCurShape = new CLineShape(point, point, GetDocument()->GetPenWidth(), GetDocument()->GetPenColor());
break;
case DRAW_RECT:
m_pCurShape = new CRectShape(point, point, GetDocument()->GetPenWidth(), GetDocument()->GetPenColor());
break;
case DRAW_ELLIPSE:
m_pCurShape = new CEllipseShape(point, point, GetDocument()->GetPenWidth(), GetDocument()->GetPenColor());
break;
}
CView::OnLButtonDown(nFlags, point);
}
void CMyPaintView::OnMouseMove(UINT nFlags, CPoint point)
{
if (nFlags & MK_LBUTTON && m_pCurShape)
{
CClientDC dc(this);
dc.SetROP2(R2_NOTXORPEN);
m_pCurShape->Draw(&dc);
switch (GetDrawMode())
{
case DRAW_LINE:
m_pCurShape->GetToPoint() = point;
break;
case DRAW_RECT:
case DRAW_ELLIPSE:
m_pCurShape->GetToPoint().x = point.x;
m_pCurShape->GetToPoint().y = point.y;
break;
}
m_pCurShape->Draw(&dc);
}
CView::OnMouseMove(nFlags, point);
}
void CMyPaintView::OnLButtonUp(UINT nFlags, CPoint point)
{
if (m_pCurShape)
{
CClientDC dc(this);
m_pCurShape->Draw(&dc);
GetDocument()->AddShape(m_pCurShape);
m_pCurShape = NULL;
}
CView::OnLButtonUp(nFlags, point);
}
void CMyPaintView::OnInitialUpdate()
{
CView::OnInitialUpdate();
SetDrawMode(DRAW_LINE); // 默认绘制直线
SetScrollSizes(MM_TEXT, GetDocument()->GetDocSize());
}
void CMyPaintView::OnUpdate(CView* pSender, LPARAM lHint, CObject* pHint)
{
CMyPaintDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
if (!pDoc)
return;
if (lHint == NULL) // 全部更新
{
SetScrollSizes(MM_TEXT, pDoc->GetDocSize());
Invalidate();
}
else // 部分更新
{
CRect* pRect = (CRect*)lHint;
InvalidateRect(pRect);
}
}
```
最后,在 CShape 类中添加以下代码,实现透明度的方式显示图形:
```c++
void CShape::Draw(CDC* pDC)
{
CRect rc(m_ptFrom, m_ptTo);
CBitmap bmp;
bmp.CreateCompatibleBitmap(pDC, rc.Width(), rc.Height());
CDC dcMem;
dcMem.CreateCompatibleDC(pDC);
CBitmap* pOldBitmap = dcMem.SelectObject(&bmp);
dcMem.FillSolidRect(0, 0, rc.Width(), rc.Height(), RGB(255, 255, 255)); // 白色背景
dcMem.SetBkMode(TRANSPARENT);
CPen pen(PS_SOLID, m_nPenWidth, m_clrPenColor);
CPen* pOldPen = dcMem.SelectObject(&pen);
CBrush brush(m_clrPenColor);
CBrush* pOldBrush = dcMem.SelectObject(&brush);
DrawShape(&dcMem); // 绘制图形
dcMem.SelectObject(pOldBrush);
dcMem.SelectObject(pOldPen);
dcMem.SelectObject(pOldBitmap);
pDC->BitBlt(m_ptFrom.x, m_ptFrom.y, rc.Width(), rc.Height(), &dcMem, 0, 0, SRCCOPY);
}
void CLineShape::DrawShape(CDC* pDC)
{
pDC->MoveTo(m_ptFrom);
pDC->LineTo(m_ptTo);
}
void CRectShape::DrawShape(CDC* pDC)
{
pDC->Rectangle(CRect(m_ptFrom, m_ptTo));
}
void CEllipseShape::DrawShape(CDC* pDC)
{
pDC->Ellipse(CRect(m_ptFrom, m_ptTo));
}
```
至此,一个基于 MFC 的简单画板程序就完成了。完整的代码如下:
VC mfc单文档中代码如下void CMyView::OnDraw(CDC* pDC) { CMyDoc* pDoc = GetDocument(); ASSERT_VALID(pDoc); for (int i=0;i<points.size();i++){ color=RGB(rand()%256,rand()%256,rand()%256); r=rand()%46+5; br.CreateSolidBrush(color); pDC->SelectObject(&br); pDC->Ellipse(points[i].x-r,points[i].y-r,points[i].x+r,points[i].y+r); br.DeleteObject(); } // TODO: add draw code for native data here } ///////////////////////////////////////////////////////////////////////////// // CMyView printing BOOL CMyView::OnPreparePrinting(CPrintInfo* pInfo) { // default preparation return DoPreparePrinting(pInfo); } void CMyView::OnBeginPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/) { // TODO: add extra initialization before printing } void CMyView::OnEndPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/) { // TODO: add cleanup after printing } ///////////////////////////////////////////////////////////////////////////// // CMyView diagnostics #ifdef _DEBUG void CMyView::AssertValid() const { CView::AssertValid(); } void CMyView::Dump(CDumpContext& dc) const { CView::Dump(dc); } CMyDoc* CMyView::GetDocument() // non-debug version is inline { ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CMyDoc))); return (CMyDoc*)m_pDocument; } #endif //_DEBUG ///////////////////////////////////////////////////////////////////////////// // CMyView message handlers void CMyView::OnLButtonDown(UINT nFlags, CPoint point) { // TODO: Add your message handler code here and/or call default center=point; r=rand()%46+5;//r=5~50 color=RGB(rand()%256,rand()%256,rand()%256); points.push_back(center); SetTimer(1,200,NULL); CView::OnLButtonDown(nFlags, point); } void CMyView::OnLButtonUp(UINT nFlags, CPoint point) { // TODO: Add your message handler code here and/or call default CView::OnLButtonUp(nFlags, point); } void CMyView::rise() { for(int i=0;i<points.size();i++) { points[i].y-=5; if(points[i].y<-r) { points.erase(points.begin()+i); i--; } } } void CMyView::OnTimer(UINT nIDEvent) { // TODO: Add your message handler code here and/or call default if(nIDEvent==1){ RedrawWindow(); rise(); } CView::OnTimer(nIDEvent); },运行效果中圆在上升过程中颜色和大小不停的变换,应怎么修改此代码使得圆在上升过程中的大小和颜色不会变换,完整步骤及代码
要使圆在上升过程中大小和颜色不会变换,可以将颜色和大小的变化单独提取出来,放到循环外面进行定义,然后再在循环内部进行圆的上升操作。具体实现方式如下:
1. 在头文件中定义变量:
```cpp
// 头文件中定义变量
COLORREF color; // 圆的颜色
int r; // 圆的半径
```
2. 在`OnDraw`函数中修改绘制圆的代码:
```cpp
void CMyView::OnDraw(CDC* pDC)
{
CMyDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
// 绘制圆
for (int i = 0;i < points.size();i++)
{
// 保持颜色和大小不变
color = RGB(0, 0, 255); // 蓝色
r = 20;
// 绘制圆
CPen pen(PS_SOLID, 1, color);
CBrush brush(color);
pDC->SelectObject(&pen);
pDC->SelectObject(&brush);
pDC->Ellipse(points[i].x - r, points[i].y - r, points[i].x + r, points[i].y + r);
}
}
```
在这个代码中,我们将颜色和大小的变化都删除了,直接将颜色设置为蓝色,大小设置为20。这样就可以让圆在上升过程中保持颜色和大小不变了。
完整修改后的代码如下:
MyView.h文件:
```cpp
#pragma once
#include "MyDoc.h"
#include <vector>
class CMyView : public CView
{
protected: // create from serialization only
CMyView() noexcept;
DECLARE_DYNCREATE(CMyView)
// Attributes
public:
CMyDoc* GetDocument() const;
// Operations
public:
// Overrides
public:
virtual void OnDraw(CDC* pDC) override;
virtual BOOL PreCreateWindow(CREATESTRUCT& cs);
protected:
virtual void OnInitialUpdate() override; // called first time after construct
virtual void OnUpdate(CView* /*pSender*/, LPARAM /*lHint*/, CObject* /*pHint*/) override;
// Implementation
public:
virtual ~CMyView();
#ifdef _DEBUG
virtual void AssertValid() const;
virtual void Dump(CDumpContext& dc) const;
#endif
protected:
// Generated message map functions
protected:
DECLARE_MESSAGE_MAP()
public:
afx_msg void OnLButtonDown(UINT nFlags, CPoint point);
afx_msg void OnLButtonUp(UINT nFlags, CPoint point);
afx_msg void OnTimer(UINT_PTR nIDEvent);
void rise();
};
#ifndef _DEBUG // debug version in MyView.cpp
inline CMyDoc* CMyView::GetDocument() const
{ return reinterpret_cast<CMyDoc*>(m_pDocument); }
#endif
```
MyView.cpp文件:
```cpp
#include "pch.h"
#include "framework.h"
#include "My.h"
#include "MyDoc.h"
#include "MyView.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
IMPLEMENT_DYNCREATE(CMyView, CView)
BEGIN_MESSAGE_MAP(CMyView, CView)
ON_WM_LBUTTONDOWN()
ON_WM_LBUTTONUP()
ON_WM_TIMER()
END_MESSAGE_MAP()
// CMyView construction/destruction
CMyView::CMyView() noexcept
{
// TODO: add construction code here
}
CMyView::~CMyView()
{
}
BOOL CMyView::PreCreateWindow(CREATESTRUCT& cs)
{
// TODO: Modify the Window class or styles here by modifying
// the CREATESTRUCT cs
return CView::PreCreateWindow(cs);
}
// CMyView drawing
void CMyView::OnDraw(CDC* pDC)
{
CMyDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
// 绘制圆
for (int i = 0;i < points.size();i++)
{
// 保持颜色和大小不变
color = RGB(0, 0, 255); // 蓝色
r = 20;
// 绘制圆
CPen pen(PS_SOLID, 1, color);
CBrush brush(color);
pDC->SelectObject(&pen);
pDC->SelectObject(&brush);
pDC->Ellipse(points[i].x - r, points[i].y - r, points[i].x + r, points[i].y + r);
}
}
void CMyView::OnInitialUpdate()
{
CView::OnInitialUpdate();
// TODO: Add your specialized code here and/or call the base class
}
void CMyView::OnUpdate(CView* /*pSender*/, LPARAM /*lHint*/, CObject* /*pHint*/)
{
CMyDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
if (!pDoc)
return;
// TODO: Add your specialized code here and/or call the base class
}
// CMyView diagnostics
#ifdef _DEBUG
void CMyView::AssertValid() const
{
CView::AssertValid();
}
void CMyView::Dump(CDumpContext& dc) const
{
CView::Dump(dc);
}
CMyDoc* CMyView::GetDocument() const // non-debug version is inline
{
ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CMyDoc)));
return (CMyDoc*)m_pDocument;
}
#endif //_DEBUG
// CMyView message handlers
void CMyView::OnLButtonDown(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default
center = point;
r = rand() % 46 + 5;
color = RGB(rand() % 256, rand() % 256, rand() % 256);
points.push_back(center);
SetTimer(1, 200, NULL);
CView::OnLButtonDown(nFlags, point);
}
void CMyView::OnLButtonUp(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default
CView::OnLButtonUp(nFlags, point);
}
void CMyView::rise()
{
for (int i = 0;i < points.size();i++)
{
points[i].y -= 5;
if (points[i].y < -r)
{
points.erase(points.begin() + i);
i--;
}
}
}
void CMyView::OnTimer(UINT_PTR nIDEvent)
{
// TODO: Add your message handler code here and/or call default
if (nIDEvent == 1) {
RedrawWindow();
rise();
}
CView::OnTimer(nIDEvent);
}
```
这样修改后,圆在上升过程中的大小和颜色就不会变换了。