使用MFC完成手动绘制点、手绘线、折线、圆的代码
时间: 2023-09-30 20:09:00 浏览: 154
以下是使用MFC完成手动绘制点、手绘线、折线、圆的代码:
首先在类视图中创建一个新的View类,例如CMyDrawView。
在CMyDrawView.h文件中添加如下代码:
```cpp
class CMyDrawView : public CView
{
protected: // 仅从序列化创建
CMyDrawView() noexcept;
DECLARE_DYNCREATE(CMyDrawView)
// 特性
public:
CMyDrawDoc* GetDocument() const;
// 操作
public:
// 重写
public:
virtual void OnDraw(CDC* pDC); // 重写以绘制该视图
virtual BOOL PreCreateWindow(CREATESTRUCT& cs);
protected:
// 实现
public:
virtual ~CMyDrawView();
#ifdef _DEBUG
virtual void AssertValid() const;
virtual void Dump(CDumpContext& dc) const;
#endif
protected:
// 生成的消息映射函数
protected:
afx_msg void OnLButtonDown(UINT nFlags, CPoint point);
afx_msg void OnMouseMove(UINT nFlags, CPoint point);
afx_msg void OnLButtonUp(UINT nFlags, CPoint point);
DECLARE_MESSAGE_MAP()
private:
CPoint m_ptStart; // 起点
CPoint m_ptEnd; // 终点
BOOL m_bDrawing; // 是否正在绘制
int m_nShape; // 绘制的形状:0-点,1-线,2-折线,3-圆
CArray<CPoint, CPoint&> m_arrPoints; // 折线的点集合
};
#ifndef _DEBUG // MyDrawView.cpp 中的调试版本
inline CMyDrawDoc* CMyDrawView::GetDocument() const
{ return reinterpret_cast<CMyDrawDoc*>(m_pDocument); }
#endif
```
在CMyDrawView.cpp文件中添加如下代码:
```cpp
// CMyDrawView
IMPLEMENT_DYNCREATE(CMyDrawView, CView)
BEGIN_MESSAGE_MAP(CMyDrawView, CView)
ON_WM_LBUTTONDOWN()
ON_WM_MOUSEMOVE()
ON_WM_LBUTTONUP()
END_MESSAGE_MAP()
// CMyDrawView 构造/析构
CMyDrawView::CMyDrawView() noexcept
{
m_bDrawing = FALSE;
m_nShape = 0;
}
CMyDrawView::~CMyDrawView()
{
}
BOOL CMyDrawView::PreCreateWindow(CREATESTRUCT& cs)
{
// TODO: 在此处通过修改
// CREATESTRUCT cs 来修改窗口类或样式
return CView::PreCreateWindow(cs);
}
// CMyDrawView 绘制
void CMyDrawView::OnDraw(CDC* pDC)
{
CMyDrawDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
if (!pDoc)
return;
// 绘制折线
if (m_nShape == 2)
{
if (m_arrPoints.GetSize() > 0)
{
POINT* pPoints = new POINT[m_arrPoints.GetSize()];
for (int i = 0; i < m_arrPoints.GetSize(); i++)
{
pPoints[i] = m_arrPoints.GetAt(i);
}
pDC->Polyline(pPoints, m_arrPoints.GetSize());
delete[] pPoints;
}
}
// 绘制圆
if (m_nShape == 3)
{
int nRadius = (int)sqrt((double)((m_ptStart.x - m_ptEnd.x) * (m_ptStart.x - m_ptEnd.x) + (m_ptStart.y - m_ptEnd.y) * (m_ptStart.y - m_ptEnd.y)));
pDC->Ellipse(m_ptStart.x - nRadius, m_ptStart.y - nRadius, m_ptStart.x + nRadius, m_ptStart.y + nRadius);
}
}
// CMyDrawView 消息处理程序
void CMyDrawView::OnLButtonDown(UINT nFlags, CPoint point)
{
m_bDrawing = TRUE;
m_ptStart = point;
m_ptEnd = point;
// 绘制点
if (m_nShape == 0)
{
CDC* pDC = GetDC();
pDC->SetPixel(m_ptStart, RGB(0, 0, 0));
ReleaseDC(pDC);
}
CView::OnLButtonDown(nFlags, point);
}
void CMyDrawView::OnMouseMove(UINT nFlags, CPoint point)
{
if (m_bDrawing)
{
CDC* pDC = GetDC();
pDC->SetROP2(R2_NOTXORPEN);
// 擦除之前的绘制
if (m_nShape == 1 || m_nShape == 2 || m_nShape == 3)
{
pDC->MoveTo(m_ptStart);
pDC->LineTo(m_ptEnd);
}
// 更新终点
m_ptEnd = point;
// 绘制线
if (m_nShape == 1)
{
pDC->MoveTo(m_ptStart);
pDC->LineTo(m_ptEnd);
}
// 绘制折线
if (m_nShape == 2)
{
if (m_arrPoints.GetSize() > 0)
{
pDC->MoveTo(m_arrPoints.GetAt(m_arrPoints.GetSize() - 1));
pDC->LineTo(m_ptEnd);
}
else
{
pDC->MoveTo(m_ptStart);
pDC->LineTo(m_ptEnd);
}
}
// 绘制圆
if (m_nShape == 3)
{
pDC->Ellipse(m_ptStart.x - abs(m_ptStart.x - m_ptEnd.x), m_ptStart.y - abs(m_ptStart.x - m_ptEnd.x), m_ptStart.x + abs(m_ptStart.x - m_ptEnd.x), m_ptStart.y + abs(m_ptStart.x - m_ptEnd.x));
}
pDC->SetROP2(R2_COPYPEN);
ReleaseDC(pDC);
}
CView::OnMouseMove(nFlags, point);
}
void CMyDrawView::OnLButtonUp(UINT nFlags, CPoint point)
{
m_bDrawing = FALSE;
// 绘制线
if (m_nShape == 1)
{
CDC* pDC = GetDC();
pDC->MoveTo(m_ptStart);
pDC->LineTo(m_ptEnd);
ReleaseDC(pDC);
}
// 绘制折线
if (m_nShape == 2)
{
m_arrPoints.Add(point);
}
// 绘制圆
if (m_nShape == 3)
{
Invalidate();
}
CView::OnLButtonUp(nFlags, point);
}
#ifdef _DEBUG
void CMyDrawView::AssertValid() const
{
CView::AssertValid();
}
void CMyDrawView::Dump(CDumpContext& dc) const
{
CView::Dump(dc);
}
CMyDrawDoc* CMyDrawView::GetDocument() const // 非调试版本是内联的
{
ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CMyDrawDoc)));
return (CMyDrawDoc*)m_pDocument;
}
#endif //_DEBUG
```
接下来在CMyDrawDoc.cpp文件中添加如下代码:
```cpp
// CMyDrawDoc
IMPLEMENT_DYNCREATE(CMyDrawDoc, CDocument)
BEGIN_MESSAGE_MAP(CMyDrawDoc, CDocument)
END_MESSAGE_MAP()
// CMyDrawDoc 构造/析构
CMyDrawDoc::CMyDrawDoc() noexcept
{
}
CMyDrawDoc::~CMyDrawDoc()
{
}
BOOL CMyDrawDoc::OnNewDocument()
{
if (!CDocument::OnNewDocument())
return FALSE;
return TRUE;
}
// CMyDrawDoc 序列化
void CMyDrawDoc::Serialize(CArchive& ar)
{
if (ar.IsStoring())
{
// TODO: add storing code here
}
else
{
// TODO: add loading code here
}
}
#ifdef _DEBUG
void CMyDrawDoc::AssertValid() const
{
CDocument::AssertValid();
}
void CMyDrawDoc::Dump(CDumpContext& dc) const
{
CDocument::Dump(dc);
}
#endif //_DEBUG
```
最后,在MainFrm.cpp文件中添加如下代码:
```cpp
// CMainFrame
IMPLEMENT_DYNCREATE(CMainFrame, CFrameWnd)
BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd)
ON_WM_CREATE()
ON_COMMAND(ID_DRAW_POINT, OnDrawPoint)
ON_COMMAND(ID_DRAW_LINE, OnDrawLine)
ON_COMMAND(ID_DRAW_POLYLINE, OnDrawPolyline)
ON_COMMAND(ID_DRAW_CIRCLE, OnDrawCircle)
END_MESSAGE_MAP()
// CMainFrame 构造/析构
CMainFrame::CMainFrame() noexcept
{
// TODO: 在此添加成员初始化代码
}
CMainFrame::~CMainFrame()
{
}
int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CFrameWnd::OnCreate(lpCreateStruct) == -1)
return -1;
// TODO: 如果在此处添加任何特定于应用程序的代码,
// 将该代码放置于最终应该出现的位置
return 0;
}
BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs)
{
if( !CFrameWnd::PreCreateWindow(cs) )
return FALSE;
// TODO: 在此处通过修改
// CREATESTRUCT cs 来修改窗口类或样式
return TRUE;
}
// CMainFrame 消息处理程序
void CMainFrame::OnDrawPoint()
{
CMyDrawView* pView = (CMyDrawView*)GetActiveView();
if (pView != NULL)
{
pView->m_nShape = 0;
}
}
void CMainFrame::OnDrawLine()
{
CMyDrawView* pView = (CMyDrawView*)GetActiveView();
if (pView != NULL)
{
pView->m_nShape = 1;
}
}
void CMainFrame::OnDrawPolyline()
{
CMyDrawView* pView = (CMyDrawView*)GetActiveView();
if (pView != NULL)
{
pView->m_nShape = 2;
pView->m_arrPoints.RemoveAll();
}
}
void CMainFrame::OnDrawCircle()
{
CMyDrawView* pView = (CMyDrawView*)GetActiveView();
if (pView != NULL)
{
pView->m_nShape = 3;
}
}
```
现在可以在菜单栏上添加四个按钮,分别对应绘制点、线、折线和圆的功能。当用户选择其中一个按钮时,就改变视图中的m_nShape变量,使之对应相应的绘制形状。当用户开始绘制时,OnLButtonDown()函数将启动绘制过程,并在OnMouseMove()函数中更新绘制结果。当用户完成绘制时,OnLButtonUp()函数将完成绘制。
注意:本示例只支持绘制单个圆形。如果需要绘制多个圆形,可以用一个CArray来存储所有的圆心和半径。
阅读全文