MFC/윈도우 프로그래밍

MFC 윈도우 프로그래밍 4장 연습문제(1~8)

꾸준함. 2018. 3. 24. 22:24

윈도우 프로그래밍 Visual C++ 2010 MFC Programming(김선우, 신화서 저) 4장 연습문제입니다.

우선 1~8번 문제까지 풀어봤습니다.


[4-1]

//직사각형과 타원 모두 CRect 객체를 사용하도록 PaintDC 예제를 수정하시오

void CChildView::OnPaint()

{

        CPaintDC dc(this); // 그리기를 위한 디바이스 컨텍스트입니다.

       

        // TODO: 여기에 메시지 처리기 코드를 추가합니다.

        CRect rect1(0, 0, 200, 100), rect2(200, 100, 500, 200);

        dc.Rectangle(&rect1);

        dc.Ellipse(&rect2);

        // 그리기 메시지에 대해서는 CWnd::OnPaint()를 호출하지 마십시오.

}

 


[4-2]

<ChildView.h>

#pragma once

#include <afxtempl.h>

 

// CChildView

 

class CChildView : public CWnd

{

// 생성입니다.

public:

        CChildView();

 

// 특성입니다.

public:

        CArray<CPoint, POINT> m_rect, m_elli; //직사각형과 타원

        UINT rIdx, eIdx;

// 작업입니다.

public:

 

// 재정의입니다.

        protected:

        virtual BOOL PreCreateWindow(CREATESTRUCT& cs);

 

// 구현입니다.

public:

        virtual ~CChildView();

 

        // 생성된 메시지 맵 함수

protected:

        afx_msg void OnPaint();

        DECLARE_MESSAGE_MAP()

public:

        afx_msg void OnLButtonDown(UINT nFlags, CPoint point);

        afx_msg void OnRButtonDown(UINT nFlags, CPoint point);

};


<ChildView.cpp>

//ClientDC 예제가 다른 윈도우에 가려지거나 최소화 상태에서 복원되어 윈도우가 다시

//그려져도 그렸던 원이 모두 나타나도록 예제를 수정하시오

void CChildView::OnPaint()

{

        CPaintDC dc(this); // 그리기를 위한 디바이스 컨텍스트입니다.

       

        // TODO: 여기에 메시지 처리기 코드를 추가합니다.

        for (int i = 0; i < rIdx; i++)

        {

               CRect rect(m_rect[i].x - 20, m_rect[i].y - 20, m_rect[i].x + 20, m_rect[i].y + 20);

               dc.Rectangle(&rect);

        }

        for (int i = 0; i < eIdx; i++)

        {

               CRect rect(m_elli[i].x - 20, m_elli[i].y - 20, m_elli[i].x + 20, m_elli[i].y + 20);

               dc.Ellipse(&rect);

        }

        // 그리기 메시지에 대해서는 CWnd::OnPaint()를 호출하지 마십시오.

}

 

 

 

void CChildView::OnLButtonDown(UINT nFlags, CPoint point)

{

        // TODO: 여기에 메시지 처리기 코드를 추가 및/또는 기본값을 호출합니다.

        CClientDC dc(this);

        dc.Rectangle(point.x - 20, point.y - 20, point.x + 20, point.y + 20);

        m_rect[rIdx++] = point;

        //CWnd::OnLButtonDown(nFlags, point);

}

 

 

void CChildView::OnRButtonDown(UINT nFlags, CPoint point)

{

        // TODO: 여기에 메시지 처리기 코드를 추가 및/또는 기본값을 호출합니다.

        CClientDC dc(this);

        dc.Ellipse(point.x - 20, point.y - 20, point.x + 20, point.y + 20);

        m_elli[eIdx++] = point;

        //CWnd::OnRButtonDown(nFlags, point);

}

 

[4-3]

<ChildView.h>

 

// ChildView.h: CChildView 클래스의 인터페이스

//

 

 

#pragma once

#include <afxtempl.h>

 

// CChildView

 

class CChildView : public CWnd

{

// 생성입니다.

public:

        CChildView();

 

// 특성입니다.

public:

        CList<CPoint, POINT> m_rect, m_elli;

// 작업입니다.

public:

 

// 재정의입니다.

        protected:

        virtual BOOL PreCreateWindow(CREATESTRUCT& cs);

 

// 구현입니다.

public:

        virtual ~CChildView();

 

        // 생성된 메시지 맵 함수

protected:

        afx_msg void OnPaint();

        DECLARE_MESSAGE_MAP()

public:

        afx_msg void OnLButtonDown(UINT nFlags, CPoint point);

        afx_msg void OnRButtonDown(UINT nFlags, CPoint point);

};

 

<ChildView.cpp>

//ClientDC 예제가 다른 윈도우에 가려지거나 최소화 상태에서 복원되어 윈도우가 다시

//그려져도 그렸던 원이 모두 나타나도록 예제를 수정하시오

void CChildView::OnPaint()

{

        CPaintDC dc(this); // 그리기를 위한 디바이스 컨텍스트입니다.

       

        // TODO: 여기에 메시지 처리기 코드를 추가합니다.

        POSITION pos1 = m_rect.GetHeadPosition();

        POSITION pos2 = m_elli.GetHeadPosition();

        while (pos1 != NULL)

        {

               CPoint coord = m_rect.GetNext(pos1);

               dc.Rectangle(coord.x - 20, coord.y - 20, coord.x + 20, coord.y + 20);

        }

        while (pos2 != NULL)

        {

               CPoint coord = m_rect.GetNext(pos2);

               dc.Ellipse(coord.x - 20, coord.y - 20, coord.x + 20, coord.y + 20);

        }

        // 그리기 메시지에 대해서는 CWnd::OnPaint()를 호출하지 마십시오.

}

 

 

 

void CChildView::OnLButtonDown(UINT nFlags, CPoint point)

{

        // TODO: 여기에 메시지 처리기 코드를 추가 및/또는 기본값을 호출합니다.

        CClientDC dc(this);

        dc.Rectangle(point.x - 20, point.y - 20, point.x + 20, point.y + 20);

        m_rect.AddTail(point);

        //CWnd::OnLButtonDown(nFlags, point);

}

 

 

void CChildView::OnRButtonDown(UINT nFlags, CPoint point)

{

        // TODO: 여기에 메시지 처리기 코드를 추가 및/또는 기본값을 호출합니다.

        CClientDC dc(this);

        dc.Ellipse(point.x - 20, point.y - 20, point.x + 20, point.y + 20);

        m_elli.AddTail(point);

        //CWnd::OnRButtonDown(nFlags, point);

}


[4-4]

//배경이 초록색인 직사각형을 그리고 그 위에 투명모드로 글자를 출력하도록

//WindowDC 예제를 수정하시오

void CMainFrame::OnNcPaint()

{

        // TODO: 여기에 메시지 처리기 코드를 추가합니다.

        // 그리기 메시지에 대해서는 CFrameWnd::OnNcPaint()() 호출하지 마십시오.

 

        //운영체제가 자동으로 비클라이언트 영역을 그리게 한다

        CFrameWnd::OnNcPaint();

 

        //타이틀바에 직사각형을 그린다

        CWindowDC dc(this);

        int height = GetSystemMetrics(SM_CYSIZE) + GetSystemMetrics(SM_CYSIZEFRAME);

        dc.Rectangle(150, 0, 350, height + 1);

        dc.FillSolidRect(CRect(150, 0, 350, height + 1), RGB(0, 255, 0)); //초록색

        dc.SetBkMode(TRANSPARENT); //투명

        //메인(프레임) 윈도우의 크기를 얻는다

        CRect rect;

        GetWindowRect(&rect);

 

        //타이틀바에 크기 출력

        CString str;

        str.Format(_T("Width=%4d, Height=%4d"), rect.Width(), rect.Height());

        dc.TextOutW(160, 7, str);

}


[4-5]

 

// ChildView.cpp: CChildView 클래스의 구현

//

 

#include "stdafx.h"

#include "연습문제 4-5.h"

#include "ChildView.h"

 

#ifdef _DEBUG

#define new DEBUG_NEW

#endif

 

 

// CChildView

 

CChildView::CChildView()

{

        //확장 메타파일 객체를 생성하고 초기화

        CMetaFileDC dc;

        dc.CreateEnhanced(NULL, NULL, NULL, NULL);

        //멤버 함수를 호출하여 출력

        dc.Rectangle(0, 0, 10, 10);

        dc.Ellipse(1, 1, 9, 9);

        //확장 메타파일 핸들을 얻는다

        m_hmf = dc.CloseEnhanced();

}

 

CChildView::~CChildView()

{

        //확장 메타파일을 삭제한다

        ::DeleteEnhMetaFile(m_hmf);

        m_rect.RemoveAll();

        m_elli.RemoveAll();

}

 

 

BEGIN_MESSAGE_MAP(CChildView, CWnd)

        ON_WM_PAINT()

        ON_WM_LBUTTONDOWN()

        ON_WM_RBUTTONDOWN()

END_MESSAGE_MAP()

 

 

 

// CChildView 메시지 처리기

 

BOOL CChildView::PreCreateWindow(CREATESTRUCT& cs)

{

        if (!CWnd::PreCreateWindow(cs))

               return FALSE;

 

        cs.dwExStyle |= WS_EX_CLIENTEDGE;

        cs.style &= ~WS_BORDER;

        cs.lpszClass = AfxRegisterWndClass(CS_HREDRAW|CS_VREDRAW|CS_DBLCLKS,

               ::LoadCursor(NULL, IDC_ARROW), reinterpret_cast<HBRUSH>(COLOR_WINDOW+1), NULL);

 

        return TRUE;

}

 

//윈도우가 다른 윈도우에 가려지거나 최소화 상태에서 복원되어 다시 그려져도 그렸던 원이

//모두 나타나도록 MetaFileDC 예제를 수정하시오. , 정보는 CList 클래스를 이용하여 보관한다

void CChildView::OnPaint()

{

        CPaintDC dc(this); // 그리기를 위한 디바이스 컨텍스트입니다.

       

        // TODO: 여기에 메시지 처리기 코드를 추가합니다.

        POSITION pos1 = m_rect.GetHeadPosition(), pos2 = m_elli.GetHeadPosition();

        while (pos1 != NULL)

        {

               CPoint coord = m_rect.GetNext(pos1);

               CRect rect(coord.x - 20, coord.y - 20, coord.x + 20, coord.y + 20);

               dc.PlayMetaFile(m_hmf, &rect);

        }

        while (pos2 != NULL)

        {

               CPoint coord = m_elli.GetNext(pos2);

               CRect rect(coord.x - 50, coord.y - 20, coord.x + 50, coord.y + 20);

               dc.PlayMetaFile(m_hmf, &rect);

        }

        // 그리기 메시지에 대해서는 CWnd::OnPaint()를 호출하지 마십시오.

}

 

 

 

void CChildView::OnLButtonDown(UINT nFlags, CPoint point)

{

        // TODO: 여기에 메시지 처리기 코드를 추가 및/또는 기본값을 호출합니다.

        CClientDC dc(this);

        CRect rect(point.x - 20, point.y - 20, point.x + 20, point.y + 20);

        dc.PlayMetaFile(m_hmf, &rect);

        m_rect.AddTail(point);

        //CWnd::OnLButtonDown(nFlags, point);

}

 

 

void CChildView::OnRButtonDown(UINT nFlags, CPoint point)

{

        // TODO: 여기에 메시지 처리기 코드를 추가 및/또는 기본값을 호출합니다.

        CClientDC dc(this);

        CRect rect(point.x - 50, point.y - 20, point.x + 50, point.y + 20);

        dc.PlayMetaFile(m_hmf, &rect);

        m_elli.AddTail(point);

        //CWnd::OnRButtonDown(nFlags, point);

}

 

[4-6]

//마우스 왼쪽 버튼을 클릭하면 해당 좌표에 해당하는 색상값을 다음과 같이

//메시지 상자에 출력하도록 DrawPoints 예제를 수정하시오

void CChildView::OnPaint()

{

        CPaintDC dc(this); // 그리기를 위한 디바이스 컨텍스트입니다.

       

        // TODO: 여기에 메시지 처리기 코드를 추가합니다.

        for (int x = 0; x < 256; x++)

               for (int y = 0; y < 256; y++)

                       dc.SetPixelV(x, y, RGB(x, y, 0));

        // 그리기 메시지에 대해서는 CWnd::OnPaint()를 호출하지 마십시오.

}

 

 

 

void CChildView::OnLButtonDown(UINT nFlags, CPoint point)

{

        // TODO: 여기에 메시지 처리기 코드를 추가 및/또는 기본값을 호출합니다.

        CClientDC dc(this);

        COLORREF color = dc.GetPixel(point);

        CString str;

        str.Format(_T("R:%d, G:%d, B:%d"), GetRValue(color), GetGValue(color), GetBValue(color));

        MessageBox(str, _T("DrawPoints"), NULL);

        //CWnd::OnLButtonDown(nFlags, point);

}

 


[4-7]

void CChildView::OnPaint()

{

        CPaintDC dc(this); // 그리기를 위한 디바이스 컨텍스트입니다.

       

        // TODO: 여기에 메시지 처리기 코드를 추가합니다.

        //클라이언트 영역의 좌표를 얻는다

        CRect rect;

        GetClientRect(&rect);

       

        //수평선과 수직선을 그린다

        dc.MoveTo(0, rect.bottom / 2);

        dc.LineTo(rect.right, rect.bottom / 2);

        dc.MoveTo(rect.right / 2, 0);

        dc.LineTo(rect.right / 2, rect.bottom);

 

        int centerX = rect.Width() / 2, centerY = rect.Height() / 2; //원점 재설정

 

        CArray<POINT, POINT&> arr;

        double PI = 3.14159265358979323846;

        //마름모꼴을 그린다

        for (int i = -centerX; i <= centerX; i++)

        {

               POINT coord;

               coord.x = i + centerX; //x축의 원점이 centerX이므로

               coord.y = centerY - (int)(sin(i*PI / 180.0)*centerY); //y좌표계 또한 반대

               arr.Add(coord);

        }

        dc.Polyline(arr.GetData(), arr.GetSize());

        // 그리기 메시지에 대해서는 CWnd::OnPaint()를 호출하지 마십시오.

}


[4-8]

//DrawTexts 예제에서 서체가 각각 첫번째 문장은 굴림, 두번째 문장은 궁서

//세번째 문장은 바탕으로 출력되도록 예제를 수정하시오

void CChildView::OnPaint()

{

        CPaintDC dc(this); // 그리기를 위한 디바이스 컨텍스트입니다.

       

        // TODO: 여기에 메시지 처리기 코드를 추가합니다.

        CRect rect;

        GetClientRect(&rect);

 

        dc.SetTextColor(RGB(255, 0, 0)); //글자를 빨간색으로 설정

        dc.SetBkColor(RGB(255, 255, 0)); //배경을 노란색으로 설정

        CFont font1, font2, font3;

        font1.CreatePointFont(400, _T("굴림"));

        dc.SelectObject(&font1);

        dc.DrawText(CString(_T("DrawText 함수를 연습합니다. [1]")), &rect, 0);

        font2.CreatePointFont(400, _T("궁서"));

        dc.SelectObject(&font2);

        dc.DrawText(CString(_T("DrawText 함수를 연습합니다. [2]")), &rect, DT_CENTER | DT_VCENTER | DT_SINGLELINE);

 

        dc.SetTextAlign(TA_CENTER); //가운데 정렬방식으로 변경

        dc.SetTextColor(RGB(0, 0, 255)); //글자를 파란색으로 설정

        dc.SetBkColor(RGB(0, 255, 0)); //배경을 초록색으로 설정

        font3.CreatePointFont(400, _T("바탕"));

        dc.SelectObject(&font3);

        dc.TextOutW(rect.right / 2, 3 * rect.bottom / 4, CString(_T("TextOut 함수를 연습합니다.")));

        // 그리기 메시지에 대해서는 CWnd::OnPaint()를 호출하지 마십시오.

}


개발환경:Visual Studio 2017


지적, 조언, 질문 환영입니다! 댓글 남겨주세요~

반응형