Major job requirements:
a drawing program
Using VC++, MFC can draw at least 4 types of graphics; it has functions such as adding, deleting, modifying, (checking, optional, and adding attribute functions) to fill in unlimited amounts, and stroked graphics can be saved and opened.
I’m really busy, but there are still people urging me to update this.
Sharing results can meet the minimum requirements of the assignment. The specific implementation is as follows:
1. Create a project
Creation completed.
2. Create your own shape class
(1) Create header file
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(); // No parameter construction Yjjj0310Shape(double up, double down, double left, double right, int body, COLORREF col_area, COLORREF col_line); // Constructor virtual void Serialize(CArchive & amp; ar); // Serialization function void Draw(CDC* pDC); // Drawing function void IsSelect(double x, double y); // Judgment selection function bool CD(); // Return selection status function void NoSelect(); // Deselect status function void MoveUP(); // Move up void MoveDOWN(); // Move down void MoveLEFT(); // Move left void MoveRight(); // Move right double GetUP(); // Return the up value double GetDPWN(); // Return the down value double GetLEFT(); // Return left value double GetRIGHT(); // Return the right value int GetBODY(); // Return body value COLORREF GetCOL_AREA(); // Return the fill color COLORREF GetCOL_LINE(); // Return the stroke color void ad(); // number + void da(); // number- };
(2) Create source files
#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) // Construction { up = x; down = y; left = m; right = n; body = z; col_area = c; col_line = c0; isOk = false; } void Yjjj0310Shape::Serialize(CArchive & amp; ar) { if (ar.IsStoring()) { //Serialization, saving information ar << up << down << left << right << body << col_area << col_line << isOk; } else //Deserialize, read information { ar >> up >> down >> left >> right >> body >> col_area >> col_line >> isOk; } } void Yjjj0310Shape::Draw(CDC* pDC) // Drawing { 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) // select { switch (body) { case 1: // straight line { double k = (up - down) / (left - right); double b = up - k * left; if (y == k * x + b) isOk = true; break; } case 2: // ellipse { 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: // rectangle { if (y >= up & amp; & amp; y <= down & amp; & amp; x >= left & amp; & amp; x <= right) isOk = true; break; } case 4: // perfect circle { 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 to selected state { return isOk; } void Yjjj0310Shape::NoSelect() // Uncheck state { 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 class
(1)Header file
(2) Source file
for (int i = 0; i < ShapeArray.GetSize(); + + i) { Yjjj0310Shape* pShape = ShapeArray.GetAt(i); delete pShape; }
There is something wrong in the screenshot, please refer to the following
if (ar.IsStoring()) { // TODO: Add storage code here for (int i = 0; i < ShapeArray.GetSize(); i + + ) { Yjjj0310Shape* CS = ShapeArray[i]; CS->Serialize(ar); } } else { // TODO: Add loading code here ShapeArray.RemoveAll(); // Clear the array Yjjj0310Shape* CS = new Yjjj0310Shape(); CS->Serialize(ar); ShapeArray.Add(CS); // Add elements to the array int num = ShapeArray[0]->GetUP(); for (int i = 0; i < num; i + + ) { Yjjj0310Shape* CS2 = new Yjjj0310Shape(); CS2->Serialize(ar); ShapeArray.Add(CS2); // Add elements to the array } }
4. View class
(1)Header file
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); // Delete selection function Yjjj0310Shape* Choose(double x, double y); //Choose function
(2) Add button
Save it when you’re done
(3) Source files
If there are none or a few are missing, reopen VS
It’s OK when done. (Updated in 12.27, there is one less message on the right here, and the WM_CREATE message must also be added)
void CYjjj0310View::CreateLine() { // TODO: Add command handler code here num = 1; } void CYjjj0310View::CreateCircle() { // TODO: Add command handler code here num = 2; } void CYjjj0310View::CreateRectangle() { // TODO: Add command handler code here num = 3; } void CYjjj0310View::CreateRCircle() { // TODO: Add command handler code here num = 4; } void CYjjj0310View::ChooseColor() { // TODO: Add command handler code here CColorDialog dlg; dlg.m_cc.Flags |= CC_RGBINIT | CC_FULLOPEN; if (IDOK == dlg.DoModal()) { col_in = dlg.m_cc.rgbResult; // Save the color in the color dialog box obtained by dlg.m_cc.rgbResult into the variable m_clr } } void CYjjj0310View::ChooseColorOut() { // TODO: add command handler code here CColorDialog dlg; dlg.m_cc.Flags |= CC_RGBINIT | CC_FULLOPEN; if (IDOK == dlg.DoModal()) { col_out = dlg.m_cc.rgbResult; // Save the color in the color dialog box obtained by dlg.m_cc.rgbResult into the variable m_clr } } void CYjjj0310View::OnFileOpen() { // TODO: Add command handler code here 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( & amp;file, CArchive::load); GetDocument()->Serialize(ar); // Call the serialization method of the document class ar.Close(); file.Close(); // After loading the data, if you need to update the view, you can refresh it here Invalidate(NULL); // Redraw the view } } void CYjjj0310View::OnFileSave() { // TODO: Add command handler code here 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( & amp;file, CArchive::store); GetDocument()->Serialize(ar); // Call the serialization method of the document class ar.Close(); file.Close(); } } void CYjjj0310View::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags) { // TODO: Add message handler code and/or call defaults here 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: Add message handler code and/or call defaults here switch(nChar) { case VK_CONTROL: { ff = false; break; } } CView::OnKeyUp(nChar, nRepCnt, nFlags); } void CYjjj0310View::OnLButtonDown(UINT nFlags, CPoint point) { // TODO: Add message handler code and/or call defaults here m_u = point.y; m_l = point.x; CView::OnLButtonDown(nFlags, point); } void CYjjj0310View::OnLButtonUp(UINT nFlags, CPoint point) { // TODO: Add message handler code and/or call defaults here 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: Add message handler code and/or call defaults here 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: Add your own creation code here 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: Add drawing code for native data here for (int i = 0; i < pDoc->ShapeArray.GetSize(); + + i) { Yjjj0310Shape* pShape = (pDoc->ShapeArray).GetAt(i); pShape->Draw(pDC); } }
The effect is roughly like this. (Updated in 12.27, if you encounter an abs() function error, you can replace that sentence with the following one. There should be no other errors)
double a = (right - left) / 2, b = (up - down) / 2; a = a > 0 ? a : a * -1; b = b > 0 ? b : b * -1;
Just finish it and run it. This semester’s VC++ coursework should be completed. I did a few questions that I left last time but he didn’t let me hand them in…
Thank you for your companionship. If you have any other needs in the future, feel free to message me privately or leave a comment.