화면 출력(GDI)
GDI(Graphics Device Interface)는 윈도우 운영체제가 제공하는 그래픽 출력 서비스 구조입니다.
개발자가 그래픽 디바이스(VGA 카드)별로 어떤 방법을 이용해서 그래픽을 출력하는지 알 필요 없이 GDI만 이용해서 그래픽을 출력할 수 있도록 지원해주는 구조입니다.
1. CDC 클래스
1)DC(Device Context)
윈도우용 Application에서 화면에 출력하는 작업을 처리하기 위해 필요한 출력 속성을 정의하고 있는 자료구조입니다.
윈도우에서는 화면 출력이 필요할 때 DC(Device Context)라는 것이 있어야 합니다.
DC는 화면(또는 프린터)출력에 필요한 모든 정보를 가지고 있는 데이터 구조체이며 이 DC를 통해야만 그래픽이든 문자든 출력할 수 있습니다.
2)DC의 사용
MFC에서는 CDC클래스 안에 DC에 관한 모든 것을 정의해 두었습니다.
CDC클래스는 DC를 관리하기 위한 API함수를 클래스로 구현한 것입니다.
따라서 MFC에서 DC를 사용하기 위해서는 CDC 클래스의 객체를 생성해서 사용해야 합니다.
3) CDC의 파생클래스
CDC클래스는 DC에 관한 모든 것을 담고 있는 중요한 클래스이지만 그 자체를 곧바로 사용하는 경우보다는 CDC로부터 파생된 클래스를 사용하는 것이 보통입니다.
GetDC()를 호출하여 CDC의 포인터 형태로 DC를 얻어서 사용할 수 있습니다.
CDC *pDC = GetDC();
CDC의 파생클래스
파생클래스 |
사용용도 |
CClientDC |
윈도우의 작업 영역 내부(View)에 출력할 때 사용합니다. WM_PAINT 메시지를 제외한 곳에서 사용합니다. |
CPaintDC |
WM_PAINT메시지의 핸들러인 OnPaint에서 사용하며 BeginPaint와 EndPaint 호출을 자동으로 수행해줍니다. OnDraw 함수에서도 사용이 가능합니다. |
CWindowDC |
전 화면 영역에 걸쳐 출력할 때 사용합니다. 이 클래스의 객체를 사용하면 화면 영역에 제한 없이 출력할 수 있습니다. |
CMetaFileDC |
메타파일로 출력할 때 사용합니다. 메타파일은 GDI명령 호출의 집합입니다. |
MFC의 특정 메시지에서는 객체를 만들고 파괴하는 일을 FrameWork이 해주므로 매개변수로 넘겨진 pDC포인터를 사용하기만 해도 되는 경우가 있습니다.
CClientDC클래스는 CDC클래스의 파생클래스이며 OnDraw외의 함수에서 직접 화면으로 출력해야 할 일이 있을 때 사용합니다.
4) WM_PAINT 메시지
이 메시지는 윈도우를 다시 그려야 할 때 발생하는 메시지입니다.
이 경우는 윈도우가 처음 생성될 때 또는 윈도우가 가려진 상태에서 다시 나타날 때 또는 Invalidate() 또는 InvalidateRect()를 호출할 때 자동으로 발생하는 메시지입니다.
또한 이 메시지는 OnDraw()라는 함수를 호출하는 경우도 있습니다.
OnDraw()는 WM_PRINT 메시지가 발생한 경우에도 호출됩니다.
따라서 윈도우에 어떤 것을 계속해서 그려져야 하는 경우가 발생하면 이 메시지나 OnDraw() 에 작성하면 되는 경우가 있습니다.
2. 작도함수
작도함수란 점, 선, 면, 원 등의 기하학적 도형을 직접 화면에 그리는 함수입니다.
CDC 클래스에 정의된 함수들을 이용하면 됩니다.
1) 점
점에 관련된 함수는 3가지로 하나는 점을 찍는 SetPixel함수이며 나머지 하나는 화면 상에
찍힌 점의 색상을 읽는 GetPixel함수이고 다른 하나는 점을 찍고 색상을 리턴하지 않는
SetPixelV함수 입니다.
- COLORREF SetPixel(int x, int y, COLORREF crColor);
인수로 주어진(x,y)위치에 세 번째 인수 crColor로 지정한 색상으로 점을 찍습니다.
이 때 (x,y)는 반드시 DC 영역 내에 있어야 하며 그렇지 않을 경우는 점을 찍을 수 없습니다.
색상은 24비트의 트루 컬러를 마음대로 지정할 수 있습니다.
- BOOL SetPixelV(int x, int y, COLORREF crColor);
색상 값을 리턴 하지 않고 단순하게 점을 찍기만 하는 함수입니다.
화면에 출력된 색상을 조사하는 함수는 GetPixel입니다.
- COLORREF GetPixel(int x, int y) const;
(x,y)좌표에 출력되어 있는 색상을 조사하여 리턴 해 줍니다.
지정한 좌표가 DC 영역의 바깥쪽에 있을 경우 아무런 동작도 하지 않으며 -1을 리턴 합니다.
2) 색상
MFC에서 색상을 지정 할 때는 COLORREF형을 사용하며 COLORREF형은 색상 값을 나타내는 32 비트의 정수 값 입니다.
색상을 지정할 때는 거의 예외 없이 RGB 매크로 함수를 사용합니다.
이 함수는 실제의 함수는 아니며 다음과 같이 정의되어 있는 매크로 함수입니다.
#define RGB(r, g, b) ((DWORD)(((BYTE)(r) | ((DWORD)(g)<< 8)) | (((DWORD) (BYTE) (b))<< 16)))
R, G, B 세가지 인수를 받아들여 이 세 값을 합쳐 한가지 색상 값을 만듭니다.
R, G, B 값은 각각 빨간색(Red), 초록색(Green), 파란색(Blue)의 강도를 나타내며, 이 세 가지 색상의 값에 따라 만들어지는 색상은 달라집니다.
예를 들어 RGB(0,0,0)은 세 가지 색상이 모두 없으므로 검정색이 되며 RGB(255,255,255)는
세 가지 색상을 모두 섞은 것 이므로 흰색이 됩니다.
예제1) 붉은 색상(0-255)의 점을 3픽셀 마다 화면에 출력하기
View 클래스의 OnDraw 함수에 작성
for(int x = 0; x < 256; x++)
{
pDC->SetPixel(3*x, 10, RGB(x,0,0));
}
3) 선
선을 그리기 위해서는 두 개의 점이 필요하며 두 점을 이어야 선이 됩니다.
윈도우에서는 두 점의 좌표를 지정하여 선을 그리는 함수는 없으며, 현재위치(CP: Current Position)를 사용하여 선을 계속 이어주는 방식을 사용하여 선을 연결해갑니다.
선을 그리는데 사용되는 함수는 다음 두 가지 입니다.
CPoint MoveTo(int x, int y);
BOOL LineTo(int x, int y);
MoveTo는 현재 위치(CP)를 (x,y)좌표로 옮기며 LineTo는 현재위치에서 (x,y)좌표까지 선을 긋습니다.
POINT 구조체를 이용하는 아래의 함수가 Overloading 되어 있으므로 아래의 함수를 이용해도 됩니다.
CPoint MoveTo(POINT point );
BOOL LineTo(POINT point );
예제) View 클래스의 OnDraw에 작성
pDC->MoveTo(100,100);
pDC->LineTo(200,200);
4) 사각형
사각형을 그리는 함수에는 여러 가지가 있습니다.
BOOL Rectangle(int x1, int y1, int x2, int y2 );
BOOL RoundRect(int x1, int y1, int x2, int y2, int x3, int y3 )
void Draw3dRect( int x, int y, int cx, int cy, COLORREF clrTopLeft, COLORREF clrBottomRight );
void DrawDragRect( LPCRECT lpRect, SIZE size, LPCRECT lpRectLast, SIZE sizeLast, CBrush* pBrush = NULL, CBrush* pBrushLast = NULL );
void FillRect( LPCRECT lpRect, CBrush* pBrush );
void FillSolidRect( int x, int y, int cx, int cy, COLORREF clr );
사각형의 꼭지점 4개를 모두 인수로 받아들이지 않으므로 직사각형만 그릴 수 있습니다.
모양이 불규칙한 사각형을 그리고 싶다면 Polygon함수를 사용하여 다각형을 그려야 합니다.
BOOL Rectangle( int x1, int y1, int x2, int y2 );
BOOL Rectangle( LPCRECT lpRect );
첫 번째는 사각형을 나타내는 두 좌표를 인수로 받아들이며, 두 번째는 사각 영역을 나타내는 CRect객체의 포인터를 인수로 받아서 그립니다.
인수를 전달하는 방법만 다르며 내부적인 동작은 둘 다 동일하므로 프로그램의 상황에 따라 적당한 함수를 사용하면 됩니다.
RoundRect함수는 모서리가 둥근 사각형을 그리며 x3, y3는 모서리의 곡률을 조정하는 인수입니다.
이 인수의 값이 클수록 모서리가 둥글게 나타납니다.
void Draw3dRect(int x, int y, int cx, int cy, COLORREF clrTopLeft, COLORREF clrBottomRight);
void DrawDragRect( LPCRECT lpRect, SIZE size, LPCRECT lpRectLast, SIZE sizeLast, CBrush* pBrush = NULL, CBrush* pBrushLast = NULL );
Draw3dRect는 선 색이 다른 사각형이며 DrawDragRect는 2개의 이어진 사각형을 그려줍니다.
void FillRect( LPCRECT lpRect, CBrush* pBrush );
void FillSolidRect( int x, int y, int cx, int cy, COLORREF clr );
위는 브러시로 채워진 사각형을 그려주며 아래는 하나의 색상으로만 채워진 사각형이 그려집니다.
주의 할 점은 cx, cy는 사이즈 입니다.
예제)
View 클래스의 OnDraw 함수에 작성
CBrush pBrush(RGB(128,128,128));
RECT rt = { 200, 0, 300, 100};
RECT rt1 = {400, 0, 500, 100};
pDC->Rectangle(0, 0, 100, 100);
pDC->RoundRect(100, 0, 200, 100, 50, 50);
pDC->Draw3dRect(&rt,RGB(255,0,0), RGB(0,255,0));
pDC->FillSolidRect(300, 0, 100, 100, RGB(255,0,255));
pDC->FillRect(&rt1,&pBrush);
5) 원 및 다각형
원을 그리는 함수
BOOL Ellipse(int x1, int y1, int x2, int y2 );
인수로 전달받은 두 개의 좌표는 Rectangle에서와 같은 사각형의 두 꼭지점 좌표이며 Ellipse는 이 사각형에 내접하는 타원을 그립니다.
이 함수 외에도 호를 그려주는 Arc, ArcTo, PolyBezier, PolyBezierTo, Pie, Chord 다각형을 그려주는 Polygon 등의 함수가 있습니다.
BOOL Arc( int x1, int y1, int x2, int y2, int x3, int y3, int x4, int y4 );
BOOL Arc( LPCRECT lpRect, POINT ptStart, POINT ptEnd );
BOOL Pie( int x1, int y1, int x2, int y2, int x3, int y3, int x4, int y4 );
BOOL Pie( LPCRECT lpRect, POINT ptStart, POINT ptEnd );
BOOL Chord( int x1, int y1, int x2, int y2, int x3, int y3, int x4, int y4 );
BOOL Chord( LPCRECT lpRect, POINT ptStart, POINT ptEnd );
BOOL Polyline( LPPOINT lpPoints, int nCount );
BOOL Polygon( LPPOINT lpPoints, int nCount );
BOOL PolyBezier( const POINT* lpPoints, int nCount );
예제)아래의 코드를 View 클래스의 OnDraw함수에 작성해 보세요.
POINT ar[] ={250,50,150,200,350,200,250,50};
POINT ar1[] = {300,350,350,350,350,300,400,300,400,350,450,350,450,400,300,400,300,350};
pDC->Polyline (ar ,4);
pDC->Ellipse (350,20,500,100);
pDC->Polygon(ar1,9);
pDC->Chord(0,0,100,100,50,0, 50,50);
pDC->Pie(0,150,100,250,50,150,50,200);
pDC->Arc(0,300,100,400,50,300,50,350);
3. GDI 오브젝트
1) GDI 오브젝트 클래스
그래픽 출력에 사용되는 도구를 GDI오브젝트라고 하며 여기에는 펜, 브러시, 폰트 등이 포함됩니다.
선을 그으려면 당연히 좌표가 필요하며 LineTo 등의 함수를 호출할 때 인수로 그 좌표를 전달해줍니다.
그러나 선을 긋는데 좌표만 필요한 것이 아닙니다.
색상도 알아야 하며 선의 모양도 알아야 하며 선의 굵기도 알아야 합니다.
GDI는 이런 정보를 어디에서 얻는가 하면 바로 GDI오브젝트를 통해 얻으며 이런 GDI오브젝트를 모아 놓은 것이 DC입니다.
DC내부에는 선을 긋는데 필요한 정보인 펜, 그리고 면을 채우는데 필요한 정보인 브러시 등이 있으며, 이외에 비트맵, 글꼴, 팔레트, 영역, 경로 등이 있습니다.
DC가 처음 만들어 질 때, 즉 CDC클래스가 생성될 때 GDI오브젝트는 모두 디폴트 값을 가지고 있습니다.
그래서 사용자들은 그림을 그리기 전에 GDI오브젝트의 특성을 먼저 정의해 주어야 원하는
모양의 그림을 그릴 수 있습니다.
아무 지정이 없는 선은 검정색의 가는 선이 사용되며 면을 채울 때는 흰색이 사용됩니다.
MFC에서는 각각의 GDI오브젝트를 나타내는 클래스를 정의하고 있으며 모두 CGdiObject클래스의 파생클래스입니다.
GDI 오브젝트
클래스 |
설명 |
디폴트 |
CPen |
선을 그을 때 사용 |
검정색의 가는 선 |
CBrush |
면을 채울 때 사용 |
흰색 |
CBitmap |
비트맵 이미지 |
선택되지 않음 |
CFont |
문자 출력에 사용되는 글꼴 |
시스템 글꼴 |
CPalette |
팔레트 |
선택되지 않음 |
CRgn |
영역 |
선택되지 않음 |
만약 파란색 선을 긋고 싶다면 파란색 펜을 만들어 GDI에서 이 펜을 사용할 수 있도록 선택해준 후 선을 그어야 합니다.
GDI오브젝트를 선택하는 함수는 CDC 클래스에 정의된 SelectObject 함수입니다.
CPen* SelectObject(CPen* pPen );
CBrush* SelectObject(CBrush* pBrush );
펜을 하나 만든 후 그 펜의 포인터를 SelectObject함수의 인수로 넘겨주면 GDI의 펜이 선택되어 앞으로 선을 그을 때는 이 펜이 사용됩니다.
브러시의 경우도 마찬가지입니다.
스톡오브젝트
스톡 오브젝트란 윈도우에 미리 정의되어 있는 오브젝트를 말하며 윈도우가 운영체제 차원에서 제공해 주는 GDI오브젝트로 생성시키거나 파괴시키는 과정을 거치지 않고서도 곧바로 사용할 수 있습니다.
SelectStockObject함수를 사용하여 스톡오브젝트를 곧바로 DC에 선택할 수 있습니다.
virtual CGdiObject* SelectStockObject(int nIndex );
인수 nIndex로 스톡 오브젝트의 종류를 지정하며 다음과 같은 값들이 있습니다.
BLACK_BRUSH DKGRAY_BRUSH GRAY_BRUSH HOLLOW_BRUSH LTGRAY_BRUSH NULL_BRUSH WHITE_BRUSH |
BLACK_PEN NULL_PEN WHITE_PEN |
ANSI_FIXED_FONT ANSI_VAR_FONT DEVICE_DEFAULT_FONT OEM_FIXED_FONT |
'C & C++ > MFC Media' 카테고리의 다른 글
화면 갱신 OnPaint(), OnDraw(), Invalidate() (0) | 2011.04.27 |
---|---|
GDI 를 이용한 그래픽 출력을 위한 모든 도구, 함수의 집합 (0) | 2011.04.25 |
이미지 CxImage (0) | 2011.04.25 |
쓸만한 Rect 관련 API 함수 (0) | 2011.03.27 |
Flash.swf 을 MFC 다이얼로그에서 디스플레이하는 방법 (0) | 2011.01.26 |
댓글