윈도우 화면으로 글씨나 그래픽을 출력하기 위해서는 반드시 해당 윈도우의 DC를 얻어와야 한다.
Win32 API 프로그램을 만들 때는 GetDC(), ReleaseDC() 함수를 통해서 DC를 얻고 사용하는데,
MFC는 이 함수를 포함하는 CClientDC 클래스를 제공한다. 또한 WM_PAINT에 대응하는 함수로
BeginPaint(), EndPaint() 함수가 존재하는데, 이 함수를 포함하는 CPaintDC 클래스도 제공된다.
보통 마우스를 화면에 클릭할 때 사각형을 그리려면 다음과 같이 코딩한다.
Win32 API 에서
case WM_LBUTTONDOWN :
{
CPoint point( (DWORD)lParam ); // CPoint는 MFC 클래스
HDC hdc = GetDC( this->m_hWnd );
Rectangle( hdc, point.x, point.y, point.x+50, point.y+50 );
ReleaseDC( this->m_hWnd, hdc );
}
MFC 에서
void CTestView::OnLButtonDown(UINT nFlags, CPoint point)
{
CClientDC dc( this ); // 생성자에서 GetDC() 함수를 호출하여 DC 생성
dc.Rectangle( point.x, point.y, point.x+50, point.y+50 );
CView::OnLButtonDown(nFlags, point);
// CClientDC 소멸자에서 ReleaseDC() 자동 호출
}
또는 다음과 같이 CDC 클래스를 사용해서 구현할 수도 있다.
void CTestView::OnLButtonDown(UINT nFlags, CPoint point)
{
CDC* pDC = GetDC();
pDC->Rectangle( point.x, point.y, point.x+50, point.y+50 );
ReleaseDC( pDC );
}
CView::OnLButtonDown(nFlags, point);
다음은 MFC에서 API 함수를 직접 사용하는 경우이다.
void CTestView::OnLButtonDown(UINT nFlags, CPoint point)
{
HDC hdc = ::GetDC( this->m_hWnd );
::Rectangle( hdc, point.x, point.y, point.x+50, point.y+50 );
::ReleaseDC( this->m_hWnd, hdc );
CView::OnLButtonDown(nFlags, point);
}
CDC 클래스
CDC 클래스는 GDI와 관련된 모든 함수들을 갖고 있다.
class CDC : public CObject
{
DECLARE_DYNCREATE(CDC)
public:
// Attributes
HDC m_hDC; // The output DC (must be first data member)
HDC m_hAttribDC; // The Attribute DC
...
// Type-safe selection helpers
public:
virtual CGdiObject* SelectStockObject(int nIndex);
CPen* SelectObject(CPen* pPen);
...
CPoint MoveTo(int x, int y);
CPoint MoveTo(POINT point);
BOOL LineTo(int x, int y);
BOOL LineTo(POINT point);
...
};
CClientDC 클래스
CClientDC 클래스는 WM_PAINT 메시지가 발생하지 않을 때 화면에 그림을 그리기 위해
사용한다. 이 클래스는 내부적으로 GetDC(), ReleaseDC() 함수를 사용해서 구현되어 있다.
class CClientDC : public CDC
{
DECLARE_DYNAMIC(CClientDC)
// Constructors
public:
CClientDC(CWnd* pWnd);
// Attributes
protected:
HWND m_hWnd;
// Implementation
public:
virtual ~CClientDC();
};
다음은 CClientDC의 생성자와 소멸자이다. 내부 코드를 보면 GetDC(), ReleaseDC() 함수를
사용하여 구현되어 있음을 알 수 있다.
CClientDC::CClientDC(CWnd* pWnd)
{
ASSERT(pWnd == NULL || ::IsWindow(pWnd->m_hWnd));
if (!Attach(::GetDC(m_hWnd = pWnd->GetSafeHwnd())))
AfxThrowResourceException();
}
CClientDC::~CClientDC()
{
ASSERT(m_hDC != NULL);
::ReleaseDC(m_hWnd, Detach());
}
CWindowDC 클래스
CWindowDC는 타이틀바, 메뉴바, 상태바 등을 포함하는 전체 윈도우에 대한 DC를 얻기 위해 사용한다.
예를 들어 다음과 같이 하면, 타이틀바에 사각형을 그릴 수 있다.
void CTestView::OnLButtonDown(UINT nFlags, CPoint point) CWindowDC wdc( AfxGetMainWnd() );
{
wdc.Rectangle( 0, 0, 20, 20 );
CView::OnLButtonDown(nFlags, point);
}
다음은 MFC가 내부적으로 사용하는 CWindowDC의 클래스 선언이다.
class CWindowDC : public CDC
{
DECLARE_DYNAMIC(CWindowDC)
// Constructors
public:
CWindowDC(CWnd* pWnd);
// Attributes
protected:
HWND m_hWnd;
// Implementation
public:
virtual ~CWindowDC();
};
CPaintDC 클래스
CPaintDC 클래스는 WM_PAINT 메시지를 처리하는 클래스이며,
BeginPaint() 함수와 EndPaint() 함수로 이루어 진다. MFC의 뷰 클래스는
WM_PAINT 메시지를 받으면 내부적으로 CPaintDC 클래스를 생성하고,
OnDraw() 함수를 호출해 준다. 그래서 OnDraw() 함수를 WM_PAINT처럼
처리하는 것이다.
void CView::OnPaint() // WM_PAINT에 의해 호출된다.
{
// standard paint routine
CPaintDC dc(this);
OnPrepareDC(&dc); // 프린트를 먼저 부른다.
OnDraw(&dc); // 화면을 다시 그리는 OnDraw()를 부른다.
}
void CTestView::OnDraw(CDC* pDC)
{
CTestDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
}
다음은 CPaintDC의 생성자와 소멸자이다. 내부 코드를 보면 BeginPaint(), EndPaint() 함수를
사용하여 구현되어 있음을 알 수 있다.
CPaintDC::CPaintDC(CWnd* pWnd)
{
ASSERT_VALID(pWnd);
ASSERT(::IsWindow(pWnd->m_hWnd));
if (!Attach(::BeginPaint(m_hWnd = pWnd->m_hWnd, &m_ps)))
AfxThrowResourceException();
}
CPaintDC::~CPaintDC()
{
ASSERT(m_hDC != NULL);
ASSERT(::IsWindow(m_hWnd));
::EndPaint(m_hWnd, &m_ps);
Detach();
}
[ CDC ]
|
---> [ CClientDC ]
|
---> [ CPaintDC ]
|
---> [ CWindowDC ]
1. CDC
반드시 ReleaseDC()함수와 쌍을 이루어야 한다.
CDC * pDC = GetDC();
...
ReleaseDC(pDC);
* OnDraw()함수의 인자로 받는 CDC는 ReleaseDC()를 사용하지 않음에 주의
2. CClientDC
화면을 출력하는 현재 클래스 어느 곳에서든지 설정하면 바로 현재 화면을 얻을 수 있다.
CClientDC cdc(this);
3. CPaintDC
OnPaint 함수내에서만 사용.
4. CWindowDC
윈도 영역 전체를 받는 DC
CWindowDC * pDC = GetWindowDC();
...
ReleaseDC(pDC);
참고) 그래픽객체와 SelectObject & DeleteObject
// 그래픽 객체 생성
CPen pen, * oldpen;
pen.CreatePen(PS_SOLID, 1, RGB(0,0,0);
// 객체를 DC에 등록
oldpen = pDC->SelectObject(&pen);
// 출력
pDC->Rectangle(0,0,100,100);
// 이전 객체로 되돌림
pDC->SelectObject(oldpen);
// 객체 삭제
pen.DeleteObject();
5. HDC , CDC 값 구하기
HDC hdc = ::GetDC(hWnd);
CDC *pDC = CDC::FromHandle(hdc);
긁어온(?) 사이트 : http://wooya510.egloos.com/942330
Visual C++ : http://wooya510.egloos.com/category/Visual%20C%2B%2B
'MFC' 카테고리의 다른 글
[MFC] 모달 vs 모달리스 (0) | 2014.02.04 |
---|---|
[MFC] MFC Control (도구상자, 컨트롤) 함수 모음 정리 (0) | 2014.01.29 |
[MFC] 2014.01.24 더블콜론(Scope resolution operator), " :: " 을 쓰는 이유 (2) | 2014.01.24 |
[MFC] MFC 프린터 관련 함수 (0) | 2014.01.22 |
[MFC/bitmap파일 출력하기] (2) | 2014.01.21 |