大作业要求:
一个绘图程序
使用VC++,MFC 能绘制至少4种图形;具备增,删、改、(查,可选,增加属性功能)等功能能没量填充,描边图形可保存、打开。
实在太忙了,但是还有人催我更这个。
分享结果可达到作业最低要求,具体实现如下:
1、创建项目
创建完成。
2、创建你自己的形状类
(1)创建头文件
class Yjjj0310Shape : public CObject
{
DECLARE_SERIAL(Yjjj0310Shape)
private:
double up;
double down;
double left;
double right;
int body;
COLORREF col_area;
COLORREF col_line;
bool isOk;
public:
Yjjj0310Shape(); // 无参构造
Yjjj0310Shape(double up, double down, double left, double right, int body, COLORREF col_area, COLORREF col_line); // 构造函数
virtual void Serialize(CArchive& ar); // 序列化函数
void Draw(CDC* pDC); // 绘图函数
void IsSelect(double x, double y); // 判断选择函数
bool CD(); // 返回选择状态函数
void NoSelect(); // 取消选择状态函数
void MoveUP(); // 向上移动
void MoveDOWN(); // 向下移动
void MoveLEFT(); // 向左移动
void MoveRight(); // 向右移动
double GetUP(); // 返回up值
double GetDPWN(); // 返回down值
double GetLEFT(); // 返回left值
double GetRIGHT(); // 返回right值
int GetBODY(); // 返回body值
COLORREF GetCOL_AREA(); // 返回填充颜色
COLORREF GetCOL_LINE(); // 返回描边颜色
void ad(); // 个数+
void da(); // 个数-
};
(2)创建源文件
#include "pch.h"
#include "windef.h"
#include "Yjjj0310Shape.h"
IMPLEMENT_SERIAL(Yjjj0310Shape, CObject, 1)
Yjjj0310Shape::Yjjj0310Shape() {}
Yjjj0310Shape::Yjjj0310Shape(double x, double y, double m, double n, int z, COLORREF c, COLORREF c0) // 构造
{
up = x;
down = y;
left = m;
right = n;
body = z;
col_area = c;
col_line = c0;
isOk = false;
}
void Yjjj0310Shape::Serialize(CArchive& ar)
{
if (ar.IsStoring()) { //序列化,保存信息
ar << up << down << left << right << body << col_area << col_line << isOk;
}
else //反序列化,读取信息
{
ar >> up >> down >> left >> right >> body >> col_area >> col_line >> isOk;
}
}
void Yjjj0310Shape::Draw(CDC* pDC) // 绘画
{
CBrush NBrush(col_area);
CPen NPen(PS_SOLID, 0, col_line);
pDC->SelectObject(NBrush);
pDC->SelectObject(NPen);
switch (body)
{
case 1:
{
pDC->MoveTo(left, up);
pDC->LineTo(right, down);
break;
}
case 2:
{
pDC->Ellipse(left, down, right, up);
break;
}
case 3:
{
pDC->Rectangle(left, down, right, up);
break;
}
case 4:
{
double r = sqrt(pow(up - down, 2) + pow(right - left, 2)) / 2;
double o_x = (left + right) / 2, o_y = (up + down) / 2;
pDC->Ellipse(o_x + r, o_y + r, o_x - r, o_y - r);
break;
}
}
}
void Yjjj0310Shape::IsSelect(double x, double y) // 选择
{
switch (body)
{
case 1: // 直线
{
double k = (up - down) / (left - right);
double b = up - k * left;
if (y == k * x + b)
isOk = true;
break;
}
case 2: // 椭圆
{
double a = abs(right - left) / 2, b = abs(up - down) / 2;
double c, Clx, Cly, Crx, Cry, o_l;
if (a > b)
{
c = sqrt(pow(a, 2) - pow(b, 2));
Clx = (left + right) / 2 - c, Crx = (left + right) / 2 + c, Cly = Cry = (up + down) / 2;
o_l = sqrt(pow(x - Clx, 2) + pow(y - Cly, 2)) + sqrt(pow(x - Crx, 2) + pow(y - Cry, 2));
if (o_l <= 2 * a)
isOk = true;
}
else
{
c = sqrt(pow(b, 2) - pow(a, 2));
Cly = (up + down) / 2 - c, Cry = (up + down) / 2 + c, Clx = Crx = (left + right) / 2;
o_l = sqrt(pow(x - Clx, 2) + pow(y - Cly, 2)) + sqrt(pow(x - Crx, 2) + pow(y - Cry, 2));
if (o_l <= 2 * b)
isOk = true;
}
break;
}
case 3: // 矩形
{
if (y >= up && y <= down && x >= left && x <= right)
isOk = true;
break;
}
case 4: // 正圆
{
double r = sqrt(pow(up - down, 2) + pow(right - left, 2)) / 2;
double o_x = (left + right) / 2, o_y = (up + down) / 2;
double o_l = sqrt(pow(x - o_x, 2) + pow(y - o_y, 2)) / 2;
if (o_l <= r)
isOk = true;
break;
}
}
}
bool Yjjj0310Shape::CD() // 返回选中状态
{
return isOk;
}
void Yjjj0310Shape::NoSelect() // 取消选中状态
{
isOk = false;
}
void Yjjj0310Shape::MoveUP()
{
up -= 10;
down -= 10;
}
void Yjjj0310Shape::MoveDOWN()
{
up += 10;
down += 10;
}
void Yjjj0310Shape::MoveLEFT()
{
left -= 10;
right -= 10;
}
void Yjjj0310Shape::MoveRight()
{
left += 10;
right += 10;
}
double Yjjj0310Shape::GetUP() { return up; }
double Yjjj0310Shape::GetDPWN() { return down; }
double Yjjj0310Shape::GetLEFT() { return left; }
double Yjjj0310Shape::GetRIGHT() { return right; }
int Yjjj0310Shape::GetBODY() { return body; }
COLORREF Yjjj0310Shape::GetCOL_AREA() { return col_area; }
COLORREF Yjjj0310Shape::GetCOL_LINE() { return col_line; }
void Yjjj0310Shape::ad() { up++; }
void Yjjj0310Shape::da() { up--; }
3、Doc类
(1)头文件
(2)源文件
for (int i = 0; i < ShapeArray.GetSize(); ++i)
{
Yjjj0310Shape* pShape = ShapeArray.GetAt(i);
delete pShape;
}
截图上有点错,以下面为准
if (ar.IsStoring())
{
// TODO: 在此添加存储代码
for (int i = 0; i < ShapeArray.GetSize(); i++)
{
Yjjj0310Shape* CS = ShapeArray[i];
CS->Serialize(ar);
}
}
else
{
// TODO: 在此添加加载代码
ShapeArray.RemoveAll(); // 清空数组
Yjjj0310Shape* CS = new Yjjj0310Shape();
CS->Serialize(ar);
ShapeArray.Add(CS); // 添加元素到数组
int num = ShapeArray[0]->GetUP();
for (int i = 0; i < num; i++)
{
Yjjj0310Shape* CS2 = new Yjjj0310Shape();
CS2->Serialize(ar);
ShapeArray.Add(CS2); // 添加元素到数组
}
}
4、View类
(1)头文件
int num = 0;
bool ff = false;
double m_u;
double m_d;
double m_l;
double m_r;
double m_x;
double m_y;
COLORREF col_in = RGB(0, 0, 0);
COLORREF col_out = RGB(0, 0, 0);
Yjjj0310Shape* CS;
void DeleteSelect(double x, double y); // 删除选择函数
Yjjj0310Shape* Choose(double x, double y); // 选择函数
(2)添加按钮
完事保存一下
(3)源文件
如果没有或者少几个,重新打开VS
完成就OK了。(12.27更新,这里右边少了一个消息,WM_CREATE这个消息也要添加)
void CYjjj0310View::CreateLine()
{
// TODO: 在此添加命令处理程序代码
num = 1;
}
void CYjjj0310View::CreateCircle()
{
// TODO: 在此添加命令处理程序代码
num = 2;
}
void CYjjj0310View::CreateRectangle()
{
// TODO: 在此添加命令处理程序代码
num = 3;
}
void CYjjj0310View::CreateRCircle()
{
// TODO: 在此添加命令处理程序代码
num = 4;
}
void CYjjj0310View::ChooseColor()
{
// TODO: 在此添加命令处理程序代码
CColorDialog dlg;
dlg.m_cc.Flags |= CC_RGBINIT | CC_FULLOPEN;
if (IDOK == dlg.DoModal())
{
col_in = dlg.m_cc.rgbResult; // 将 dlg.m_cc.rgbResult 获取到的颜色对话框中的颜色保存到变量 m_clr 中
}
}
void CYjjj0310View::ChooseColorOut()
{
// TODO: 在此添加命令处理程序代码
CColorDialog dlg;
dlg.m_cc.Flags |= CC_RGBINIT | CC_FULLOPEN;
if (IDOK == dlg.DoModal())
{
col_out = dlg.m_cc.rgbResult; // 将 dlg.m_cc.rgbResult 获取到的颜色对话框中的颜色保存到变量 m_clr 中
}
}
void CYjjj0310View::OnFileOpen()
{
// TODO: 在此添加命令处理程序代码
CFileDialog dlg(TRUE, _T("dat"), NULL, OFN_FILEMUSTEXIST | OFN_HIDEREADONLY, _T("Data Files (*.dat)|*.dat|All Files (*.*)|*.*||"), this);
if (dlg.DoModal() == IDOK) {
CFile file(dlg.GetPathName(), CFile::modeRead);
CArchive ar(&file, CArchive::load);
GetDocument()->Serialize(ar); // 调用文档类的序列化方法
ar.Close();
file.Close();
// 加载完数据后,如果需要更新视图,可以在此处进行刷新操作
Invalidate(NULL); // 重新绘制视图
}
}
void CYjjj0310View::OnFileSave()
{
// TODO: 在此添加命令处理程序代码
CFileDialog dlg(FALSE, _T("dat"), NULL, OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT, _T("Data Files (*.dat)|*.dat|All Files (*.*)|*.*||"), this);
if (dlg.DoModal() == IDOK) {
CFile file(dlg.GetPathName(), CFile::modeCreate | CFile::modeWrite);
CArchive ar(&file, CArchive::store);
GetDocument()->Serialize(ar); // 调用文档类的序列化方法
ar.Close();
file.Close();
}
}
void CYjjj0310View::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)
{
// TODO: 在此添加消息处理程序代码和/或调用默认值
switch (nChar)
{
case VK_DELETE:
{
DeleteSelect(m_x, m_y);
InvalidateRect(NULL);
break;
}
case VK_CONTROL:
{
CS = Choose(m_x, m_y);
ff = true;
break;
}
case VK_UP:
{
if (ff)
{
CS->MoveUP();
CS->NoSelect();
InvalidateRect(NULL);
}
break;
}
case VK_DOWN:
{
if (ff)
{
CS->MoveDOWN();
CS->NoSelect();
InvalidateRect(NULL);
}
break;
}
case VK_LEFT:
{
if (ff)
{
CS->MoveLEFT();
CS->NoSelect();
InvalidateRect(NULL);
}
break;
}
case VK_RIGHT:
{
if (ff)
{
CS->MoveRight();
CS->NoSelect();
InvalidateRect(NULL);
}
break;
}
}
CView::OnKeyDown(nChar, nRepCnt, nFlags);
}
void CYjjj0310View::OnKeyUp(UINT nChar, UINT nRepCnt, UINT nFlags)
{
// TODO: 在此添加消息处理程序代码和/或调用默认值
switch (nChar)
{
case VK_CONTROL:
{
ff = false;
break;
}
}
CView::OnKeyUp(nChar, nRepCnt, nFlags);
}
void CYjjj0310View::OnLButtonDown(UINT nFlags, CPoint point)
{
// TODO: 在此添加消息处理程序代码和/或调用默认值
m_u = point.y;
m_l = point.x;
CView::OnLButtonDown(nFlags, point);
}
void CYjjj0310View::OnLButtonUp(UINT nFlags, CPoint point)
{
// TODO: 在此添加消息处理程序代码和/或调用默认值
m_d = point.y;
m_r = point.x;
if (num != 0)
{
CYjjj0310Doc* pDoc = GetDocument();
Yjjj0310Shape* pShape;
if (num == 1)
pShape = new Yjjj0310Shape(m_u, m_d, m_l, m_r, num, col_in, col_out);
else
pShape = new Yjjj0310Shape(min(m_u, m_d), max(m_u, m_d), min(m_l, m_r), max(m_l, m_r), num, col_in, col_out);
pDoc->ShapeArray.Add(pShape);
pDoc->ShapeArray[0]->ad();
InvalidateRect(NULL);
}
CView::OnLButtonUp(nFlags, point);
}
void CYjjj0310View::OnMouseMove(UINT nFlags, CPoint point)
{
// TODO: 在此添加消息处理程序代码和/或调用默认值
m_x = point.x;
m_y = point.y;
CView::OnMouseMove(nFlags, point);
}
int CYjjj0310View::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CView::OnCreate(lpCreateStruct) == -1)
return -1;
// TODO: 在此添加您专用的创建代码
Yjjj0310Shape* pShape = new Yjjj0310Shape(0, 0, 0, 0, 99999, col_in, col_out);
CYjjj0310Doc* pDoc = GetDocument();
pDoc->ShapeArray.Add(pShape);
return 0;
}
void CYjjj0310View::DeleteSelect(double x, double y)
{
CYjjj0310Doc* pDoc = GetDocument();
for (int i = 0; i < pDoc->ShapeArray.GetSize(); ++i)
{
Yjjj0310Shape* pShape = pDoc->ShapeArray.GetAt(i);
pShape->IsSelect(x, y);
if (pShape->CD())
{
pDoc->ShapeArray.RemoveAt(i);
pDoc->ShapeArray[0]->da();
}
}
}
Yjjj0310Shape* CYjjj0310View::Choose(double x, double y)
{
CYjjj0310Doc* pDoc = GetDocument();
Yjjj0310Shape* pShape = NULL;
for (int i = 0; i < pDoc->ShapeArray.GetSize(); ++i)
{
pShape = pDoc->ShapeArray.GetAt(i);
pShape->IsSelect(x, y);
}
return pShape;
}
void CYjjj0310View::OnDraw(CDC* pDC)
{
CYjjj0310Doc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
if (!pDoc)
return;
// TODO: 在此处为本机数据添加绘制代码
for (int i = 0; i < pDoc->ShapeArray.GetSize(); ++i)
{
Yjjj0310Shape* pShape = (pDoc->ShapeArray).GetAt(i);
pShape->Draw(pDC);
}
}
效果大概这样。(12.27更新,如果遇到abs()函数错误的情况,可以将那一句换成下面的,应该没有其他错误了)
double a = (right - left) / 2, b = (up - down) / 2;
a = a > 0 ? a : a * -1;
b = b > 0 ? b : b * -1;
结束,运行即可,本学期VC++课程作业应该更完了,上次留的几道题我做了但是他没让交,,,,。
完结撒花,感谢陪伴,如果以后有其他需求私聊我或者评论也行。