diff --git a/ChildView.cpp b/ChildView.cpp index 2e3f841..ffc068c 100644 --- a/ChildView.cpp +++ b/ChildView.cpp @@ -69,7 +69,7 @@ void Circle(CDC* dc, void Rectangle(CDC* dc, CRect rect, COLORREF color, int thickness = 1, COLORREF color_line = RGB(0, 0, 0)) { - CPen pen(thickness <= 0 ? PS_NULL : PS_SOLID, thickness, color_line); + CPen pen(thickness <= 0 ? PS_DASH : PS_SOLID, thickness, color_line); auto pen_prev = dc->SelectObject(&pen); CBrush brush(color); @@ -188,6 +188,9 @@ BEGIN_MESSAGE_MAP(CChildView, CWnd) ON_UPDATE_COMMAND_UI(ID_DRAW_CURVE, &CChildView::OnUpdateDrawCurve) ON_WM_KEYDOWN() ON_WM_ERASEBKGND() + + // Add command, Resource.h에 커맨드 추가해야함! + // ON_COMMAND(ID_SELECT_AREA, &CChildView::OnSelectArea) END_MESSAGE_MAP() @@ -245,16 +248,46 @@ afx_msg void CChildView::OnMyPaint(CDC* dc) { dc->TextOut(10, 70, _T("Keyboard: ") + CString(std::to_string(m_keyboard).c_str())); // 튀기는 공 그리기 - Circle(dc, m_ball_pos, m_ball_radius, RGB(0, 255, 255)); + //Circle(dc, m_ball_pos, m_ball_radius, RGB(0, 255, 255)); // 고무 벽 그리기 - Rectangle(dc, m_wall_rect, RGB(255, 255, 0)); + //Rectangle(dc, m_wall_rect, RGB(255, 255, 0)); // 직선 그리기 - Line(dc, {100, 100}, {200, 300}); + //Line(dc, {100, 100}, {200, 300}); + //Line(dc, { m_pntOld.x, m_pntOld.y }, {m_pntCur.x, m_pntCur.y}); + for (auto line : m_lines) { + Line(dc, line.first, line.second); + } // 폴리곤 그리기 - Polygon(dc, {{300, 100}, {300, 50}, {250, 75}, {250, 100}}, RGB(255, 0, 255)); + //Polygon(dc, {{300, 100}, {300, 50}, {250, 75}, {250, 100}}, RGB(255, 0, 255)); + + + // 선택 영역 직사각형 표기 + Area = CRect(TOP_LEFT, BOTTOM_RIGHT); + Rectangle(dc, Area, RGB(255, 255, 255), -1, RGB(0, 0, 255)); + + for (auto x : m_shapes) { + auto color = RGB(255, 255, 0); + if (x->selected_) color = RGB(0, 0, 255); + if(dynamic_cast(x)) + Rectangle(dc, CRect{ x->p1_, x->p2_ }, color, 1); + else if (dynamic_cast(x)) { + int rad = abs(x->p1_.x - x->p2_.x) / 2; + CPoint center{ (x->p1_.x + x->p2_.x) / 2, (x->p1_.y + x->p2_.y) / 2 }; + Circle(dc, center, rad, color); + } + } + // 곡선 그리기 + for (auto curve : m_curves) { + for (auto iter = curve.begin(); iter != curve.end(); iter++) { + if ((iter + 1) != curve.end()) { + Line(dc, { (*iter).x, (*iter).y }, { (*(iter + 1)).x, (*(iter + 1)).y }); + } + } + } + } void CChildView::OnContextMenu(CWnd* pWnd, CPoint point) @@ -336,9 +369,62 @@ int CChildView::OnCreate(LPCREATESTRUCT lpCreateStruct) m_wall_rect.bottom = p.y + h / 2; }); + + // 마우스 드래그 이벤트 리스너 + m_mouse_event_listeners.Add(kMouseDrag, [this](auto, auto p) { + switch (m_toolbar_mode) { + case kToolbarDrawRectangle: + /*m_rects.back().right = p.x; + m_rects.back().bottom = p.y;*/ + m_shapes.back()->p2_ = p; + break; + case kToolbarDrawCircle: + /*m_circles.back().right = p.x; + m_circles.back().bottom = p.y;*/ + m_shapes.back()->p2_ = p; + break; + case kToolbarDrawLine: + //m_pntCur = p; + m_lines.back().second = p; + break; + case kToolbarDrawCurve: + //m_points.push_back(p); + m_curves.back().push_back(p); + break; + } + + }); // 마우스 클릭 이벤트 리스너 - m_mouse_event_listeners.Add(kMouseLButtonDown, [this](auto, auto p) { m_mouse_event = "LButtonDown"; }); - m_mouse_event_listeners.Add(kMouseLButtonUp, [this](auto, auto p) { m_mouse_event = "LButtonUp"; }); + m_mouse_event_listeners.Add(kMouseLButtonDown, [this](auto, auto p) { + m_mouse_event = "LButtonDown"; + switch (m_toolbar_mode) { + case kToolbarDrawRectangle: + m_shapes.push_back(new CRectangle(CPoint{ p.x, p.y }, CPoint{p.x, p.y})); + break; + case kToolbarDrawCircle: + m_shapes.push_back(new CCircle(CPoint{ p.x, p.y }, CPoint{ p.x, p.y })); + break; + case kToolbarDrawLine: + m_lines.push_back({ CPoint(p), CPoint(p) }); + /*m_pntOld = p; + m_pntCur = p;*/ + break; + case kToolbarDrawCurve: + if (m_curves.size() == 0) { + m_curves.push_back(std::vector{p}); + } + //m_points.push_back(p); + break; + } + }); + m_mouse_event_listeners.Add(kMouseLButtonUp, [this](auto, auto p) { + m_mouse_event = "LButtonUp"; + switch (m_toolbar_mode) { + case kToolbarDrawCurve: + m_curves.push_back(std::vector{}); + } + }); + m_mouse_event_listeners.Add(kMouseLButtonDblClk, [this](auto, auto p) { m_mouse_event = "LButtonDblClk"; }); m_mouse_event_listeners.Add(kMouseRButtonDown, [this](auto, auto p) { m_mouse_event = "RButtonDown"; }); @@ -354,11 +440,49 @@ int CChildView::OnCreate(LPCREATESTRUCT lpCreateStruct) // ESC 시 그리기 모드 취소 m_keyboard_listeners.Add(VK_ESCAPE, [this](...) { m_toolbar_mode = kToolbarNone; }); - return 0; + // 영역 선택 마우스 이벤트 -> 다운 + m_mouse_event_listeners.Add(kMouseLButtonDown, [this](auto, auto p) { + if (m_toolbar_mode == kToolbarSelectArea) { // 툴바에서 영역 선택 버튼을 눌렀을 경우 + TOP_LEFT = p; + } + }); + // 영역 선택 마우스 이벤트 -> 드래그 + m_mouse_event_listeners.Add(kMouseDrag, [this](auto, auto p) { + if (m_toolbar_mode == kToolbarSelectArea) { // 툴바에서 영역 선택 버튼을 눌렀을 경우 + BOTTOM_RIGHT = p; + } + }); + // 영역 선택 마우스 이벤트 -> 업 + m_mouse_event_listeners.Add(kMouseLButtonUp, [this](auto, auto p) { + if (m_toolbar_mode == kToolbarSelectArea) { // 툴바에서 영역 선택 버튼을 눌렀을 경우 + BOTTOM_RIGHT = p; + + auto iter = m_shapes.begin(); + + while (iter != m_shapes.end()) { + int shape_tl_x = (*iter)->p1_.x; + int shape_tl_y = (*iter)->p1_.y; + + int shape_br_x = (*iter)->p2_.x; + int shape_br_y = (*iter)->p2_.y; + + if (TOP_LEFT.x <= shape_tl_x && shape_br_x <= BOTTOM_RIGHT.x && TOP_LEFT.y <= shape_tl_y && shape_br_y <= BOTTOM_RIGHT.y) { + (*iter)->selected_ = true; + } + else { + (*iter)->selected_ = false; + } + iter++; + } + } + }); } void CChildView::OnMouseMove(UINT nFlags, CPoint point) { m_mouse_event_listeners(kMouseMove, nFlags, point); + if ((nFlags & MK_LBUTTON) == MK_LBUTTON) + m_mouse_event_listeners(kMouseDrag, nFlags, point); + CWnd::Invalidate(); CWnd::OnMouseMove(nFlags, point); } @@ -462,7 +586,17 @@ void CChildView::OnUpdateDrawCurve(CCmdUI* pCmdUI) { } void CChildView::OnRemoveSelected() { - // TODO: 여기에 명령 처리기 코드를 추가합니다. + auto iter = m_shapes.begin(); + while (iter != m_shapes.end()) { + if ((*iter)->selected_ == true) { + iter = m_shapes.erase(iter); + } + else { + iter++; + } + } + BOTTOM_RIGHT = 0; + TOP_LEFT = 0; } diff --git a/ChildView.h b/ChildView.h index 9dd46a7..a483f25 100644 --- a/ChildView.h +++ b/ChildView.h @@ -12,6 +12,7 @@ #include #include "EventListener.h" +#include "Shape.h" // CChildView 창 @@ -34,8 +35,19 @@ class CChildView : public CWnd public: CPoint m_mouse_pos; + CPoint m_pntOld; + CPoint m_pntCur; + + //std::vector m_pntOld; + //std::vector m_pntCur; + + std::vector m_points; + std::vector> m_curves; + std::vector < std::pair> m_lines; CString m_mouse_event{"None"}; CString m_current_time; + + UINT m_keyboard = -1; @@ -47,8 +59,16 @@ class CChildView : public CWnd // 고무벽 정보 CRect m_wall_rect{CPoint{}, CSize{20, 200}}; + // 도형 리스트 + std::list m_shapes; + void CalculateBall(); + // 영역 선택 변수들 + CPoint TOP_LEFT; + CPoint BOTTOM_RIGHT; + CRect Area; + public: protected: @@ -77,7 +97,7 @@ class CChildView : public CWnd enum MouseEvent { kMouseMove, - + kMouseDrag, kMouseLButtonDown, kMouseLButtonUp, kMouseLButtonDblClk, diff --git a/MenuAndControls.vcxproj b/MenuAndControls.vcxproj index 18f92bc..aa2e449 100644 --- a/MenuAndControls.vcxproj +++ b/MenuAndControls.vcxproj @@ -190,6 +190,7 @@ + diff --git a/MenuAndControls.vcxproj.filters b/MenuAndControls.vcxproj.filters index 3ce1842..5825c5d 100644 --- a/MenuAndControls.vcxproj.filters +++ b/MenuAndControls.vcxproj.filters @@ -36,6 +36,12 @@ 헤더 파일 + + 헤더 파일 + + + 헤더 파일 + diff --git a/Shape.h b/Shape.h new file mode 100644 index 0000000..7c1ea5a --- /dev/null +++ b/Shape.h @@ -0,0 +1,82 @@ +#pragma once +#include + +class CShape { +public: + CShape(CPoint p1 = CPoint{ 0,0 }, CPoint p2 = CPoint{ 0,0 }, bool selected = false) : p1_(p1), p2_(p2), selected_(selected) {} + CShape(const CShape& r) : p1_(r.p1_), p2_(r.p2_), selected_(r.selected_) {} + CShape(CShape&& r) noexcept : p1_(r.p1_), p2_(r.p2_), selected_(r.selected_) {} + CShape& operator=(const CShape& r) { + p1_ = r.p1_; + p2_ = r.p1_; + selected_ = r.selected_; + } + CShape& operator=(CShape&& r) noexcept { + p1_ = r.p1_; + p2_ = r.p1_; + selected_ = r.selected_; + } + virtual ~CShape() {} +public: + CPoint p1_; + CPoint p2_; + bool selected_; +}; + +class CRectangle : public CShape { +public: + CRectangle(CPoint p1 = CPoint{ 0,0 }, CPoint p2= CPoint{0,0}, bool selected = false) : CShape(p1, p2, selected) { + + } + CRectangle(const CRectangle& r) : CShape(r.p1_, r.p2_, r.selected_) {} + CRectangle(CRectangle&& r) noexcept : CShape(r.p1_, r.p2_, r.selected_) {} + CRectangle& operator=(const CRectangle& r) { + p1_ = r.p1_; + p2_ = r.p1_; + selected_ = r.selected_; + } + CRectangle& operator=(CRectangle&& r) noexcept { + p1_ = r.p1_; + p2_ = r.p1_; + selected_ = r.selected_; + } +}; + +class CCircle : public CShape { +public: + CCircle(CPoint p1 = CPoint{ 0,0 }, CPoint p2 = CPoint{ 0,0 }, bool selected=false) : CShape(p1, p2, selected) { + + } + CCircle(const CCircle& r) : CShape(r.p1_, r.p2_, r.selected_) {} + CCircle(CCircle&& r) noexcept : CShape(r.p1_, r.p2_, r.selected_) {} + CCircle& operator=(const CCircle& r) { + p1_ = r.p1_; + p2_ = r.p1_; + selected_ = r.selected_; + } + CCircle& operator=(CCircle&& r) noexcept { + p1_ = r.p1_; + p2_ = r.p1_; + selected_ = r.selected_; + } +}; + + +class CLine : public CShape { +public: + CLine(CPoint p1 = CPoint{ 0,0 }, CPoint p2 = CPoint{ 0,0 }, bool selected=false) : CShape(p1, p2, selected) { + + } + CLine(const CLine& r) : CShape(r.p1_, r.p2_, r.selected_) {} + CLine(CLine&& r) noexcept : CShape(r.p1_, r.p2_, r.selected_) {} + CLine& operator=(const CLine& r) { + p1_ = r.p1_; + p2_ = r.p1_; + selected_ = r.selected_; + } + CLine& operator=(CLine&& r) noexcept { + p1_ = r.p1_; + p2_ = r.p1_; + selected_ = r.selected_; + } +}; \ No newline at end of file