基于MFC单文档的画图程序(小项目)
程序员文章站
2023-12-27 08:11:33
...
基于MFC单文档的画图程序
前言
- 学习了一年多的MFC和Qt,对其基本用法已经熟练掌握,迫不及待的想实战一波,但是心急吃不了热豆腐,我还是踏踏实实的找一些既能复习以前知识的单子又不消耗我太多时间(最近在学习数据库MySQL),最终找到一单基于MFC单文档的画图程序代写,来一起看看我是怎么实现其功能的。
- 注意:这个比较基础适合初学者阅读,如果你是老鸟可以不用看了!!!
- 如果有错误欢迎大家指正,我很乐意接受大家的批评指正。
需求
设计一个基于单文档的画图程序。
1.建立菜单“绘制”,其下菜单项如图所示。当用户鼠标放在“绘图|绘制圆形”菜单项上时, 在状态栏上要显示出相应的提示信息,其他菜单可没有提示信息。(10分)
2.默认时, 使用黑色笔,粗细为1,圆的半径为100.(5分)
3.点击“红笔”菜单项后,画笔颜色更换为红色。(5分)点击“黑笔”菜单项后,画笔颜色更换为黑色(5分)。
4.点击“粗”菜单项后,画笔的宽度增加1。(5分)点击“细”菜单项后,画笔的宽度减少1,当宽度变为1时不再减少。(5分)
5.点击“半径”菜单项后,弹出对话框,设置半径。(15分)
6. 点击“绘制圆形”菜单项后,鼠标在客户区点击后,显示个用户设置后圆形,如未进行任何参数设置,则用默认值,点击取消绘制时不能绘制图形。(20分)
7. 要求:客户区刷新后仍能显示这些圆。提示:圆形的绘制使用CDC类的Ellipse函数,该函数的功能是绘制椭圆,
参数为(左上角坐标x,左上角坐标y,右下角 坐标x,右下角坐标y),然后绘制以左上角和右下角构成的矩形的内切
椭圆,只要使得这个矩形是正方形,就可以绘制圆形,可根据圆心坐标和半径计算左上角和右下角的坐标。
根据分析其需求
第一,要一个名为绘图菜单项,其里面子项有绘制圆形、取消绘制、红笔、黑笔、粗、细、半径
第二,半径功能点击时跳出对话框进行交互
第三,状态栏要显示“绘图|绘制圆形”,的提示信息
第四,客户区刷新后能继续显示图形。
实现
- 第一步:创建项目搭建环境
- 第二步:添加菜单项名字为绘图,为其添加子项,并修改其ID使其命名规范化。
- 第三步:用类向导为其菜单项添加消息响应函数
- 第四步,开始为其菜单项实现其功能,先用类向导添加变量,再从菜单项触发函数添加代码
- drawView.h
protected:
CPoint m_pOrigin; //鼠标点击起始点
UINT m_nWidth; //线宽
int m_radius; //半径大小
COLORREF m_color; //颜色
bool m_brgborblack; //用于判断选择红色或黑色的画笔
bool m_bDrawCircular; //用于判断是否要画圆
CMetaFileDC m_dcMetaFile; //元文件
- drawView.cpp
void CdrawView::OnDrawCircular()
{
// TODO: 在此添加命令处理程序代码
//MessageBox(_T("画圆"));
m_bDrawCircular = true;
}
void CdrawView::OnCancelDraw()
{
// TODO: 在此添加命令处理程序代码
//MessageBox(_T("取消绘制"));
m_bDrawCircular = false;
}
void CdrawView::OnRedPen()
{
// TODO: 在此添加命令处理程序代码
//MessageBox(_T("红笔"));
m_color = RGB(255, 0, 0);
m_brgborblack = true;
}
void CdrawView::OnBlackPen()
{
// TODO: 在此添加命令处理程序代码
//MessageBox(_T("黑笔"));
m_color = RGB(0, 0, 0);
m_brgborblack = false;
}
void CdrawView::OnCrude()
{
// TODO: 在此添加命令处理程序代码
//MessageBox(_T("粗"));
++m_nWidth;
}
void CdrawView::OnFine()
{
// TODO: 在此添加命令处理程序代码
//MessageBox(_T("细"));
if(m_nWidth != 1)
{
--m_nWidth;
}
}
- 第五步,用类向导添加鼠标左键响应函数并添加代码
- drawView.cpp
void CdrawView::OnLButtonDown(UINT nFlags, CPoint point)
{
// TODO: 在此添加消息处理程序代码和/或调用默认值
m_pOrigin = point;
CView::OnLButtonDown(nFlags, point);
}
void CdrawView::OnLButtonUp(UINT nFlags, CPoint point)
{
// TODO: 在此添加消息处理程序代码和/或调用默认值
if (m_bDrawCircular)
{
//CClientDC dc(this);
int leftUpX = 0;
int leftUpY = 0;
int rightLowerX = 0;
int rightLowerY = 0;
CPen pen(PS_SOLID, m_nWidth, m_color);
CPen* poje = m_dcMetaFile.SelectObject(&pen);
leftUpX = m_pOrigin.x - m_radius;
leftUpY = m_pOrigin.y - m_radius;
rightLowerX = m_pOrigin.x + m_radius;
rightLowerY = m_pOrigin.y + m_radius;
m_dcMetaFile.Ellipse(CRect(leftUpX, leftUpY, rightLowerX, rightLowerY));
m_dcMetaFile.SelectObject(poje);
}
//无效界面
Invalidate();
CView::OnLButtonUp(nFlags, point);
}
- 第六步,为菜单子项添加状态显示
-
- drawView.cpp
void CdrawView::OnUpdateDrawcircular(CCmdUI *pCmdUI)
{
// TODO: 在此添加命令更新用户界面处理程序代码
pCmdUI->SetCheck(m_bDrawCircular);
}
void CdrawView::OnUpdateRedpen(CCmdUI *pCmdUI)
{
// TODO: 在此添加命令更新用户界面处理程序代码
//pCmdUI->Enable(FALSE);
pCmdUI->SetCheck(m_brgborblack);
}
void CdrawView::OnUpdateBlackpen(CCmdUI *pCmdUI)
{
// TODO: 在此添加命令更新用户界面处理程序代码
pCmdUI->SetCheck(!m_brgborblack);
}
void CdrawView::OnUpdateCanceldraw(CCmdUI *pCmdUI)
{
// TODO: 在此添加命令更新用户界面处理程序代码
pCmdUI->SetCheck(!m_bDrawCircular);
}
void CdrawView::OnUpdateCrude(CCmdUI *pCmdUI)
{
// TODO: 在此添加命令更新用户界面处理程序代码
}
void CdrawView::OnUpdateFine(CCmdUI *pCmdUI)
{
// TODO: 在此添加命令更新用户界面处理程序代码
if (m_nWidth == 1)
{
pCmdUI->Enable(FALSE);
}
else
{
pCmdUI->Enable(TRUE);
}
}
void CdrawView::OnUpdateRadius(CCmdUI *pCmdUI)
{
// TODO: 在此添加命令更新用户界面处理程序代码
}
- 第七步,添加半径对话框,为其添加类,并为编辑框绑定变量用于数据交互
- 第八步,实现对话框与主程序数据交互
- drawView.cpp
void CdrawView::OnRadius()
{
// TODO: 在此添加命令处理程序代码
//MessageBox(_T("半径"));
//m_bRadius = true;
Raduus raduis;
raduis.m_nRadius = m_radius;
if (IDOK == raduis.DoModal())
{
m_radius = raduis.m_nRadius;
}
}
- 第九步,实现状态栏提示
- 第十步:实现刷新客户区图形不消失
- drawView.cpp
void CdrawView::OnDraw(CDC* pDC)
{
CdrawDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
if (!pDoc)
return;
// TODO: 在此处为本机数据添加绘制代码
HMETAFILE metafile;
//结束录制,保存文件
metafile = m_dcMetaFile.Close();
//重放元文件
pDC->PlayMetaFile(metafile);
//重新开始录制
m_dcMetaFile.Create();
m_dcMetaFile.PlayMetaFile(metafile);
//删除元文件
DeleteMetaFile(metafile);
}