1. GDI와 DC의 개념
GDI (Graphic Device Interface)
- 윈도우를 설치하면 비디오 카드와 맞는 디바이스 드라이버를 윈도우가 설정해 줌
- 그래픽을 출력하고자 하는 응용 프로그램은 윈도우에게 요청 을 하고, 윈도우는 디바이스 드라이버를 호출하면 디바이스 드라이버가 하드웨어를 구동시킴
- 하드웨어 종류에 관계없이 항상 동일한 명령어를 이용하여 그래픽을 출력할 수 있음 -> 하드웨어에 독립적인 작업 가능
- 윈도우가 하드웨어를 제어할 수 있도록 응용 프로그램에 제공 하는 모든 기능
- 응용 프로그램과 디바이스 드라이버의 중간 역할
- 응용 프로그램에 대한 장치 독립적인 그래픽 동작 수행
- (Application -> Windows -> Device Driver -> Graphic Card)
- GDI는 Windows 운영체제가 응용프로그램에 제공하는 그래픽 출력 API 입니다. (Windows가 하드웨어를 제어할 수 있도록 응용 프로그램에 제공하는 모든 기능[함수, 구조 등]을 일컬어 GDI라고 합니다.)
간편화 하기 위해 DC(Device Context)라는 개념을 도입 ->
Device Context(DC)
- 윈도우 프로그램은 윈도우 화면에 출력되는 모든 내용을 DC를 이용하여 출력
- 그래픽 객체들의 속성과 그래픽 모드를 정의하는 자료의 집합체
- 응용프로그램과 출력 장치(Hw)를 연결하는 역할
- 응용프로그램이 출력에 대한 허가를 얻고, 또한 그려지는 영역을 결정 하는 역할
- GDI에 의해 내부적으로 유지되는 데이터 구조-GDI 함수의 매개변수
- DC를 사용하는 이유? 독립적인 하드웨어 출력을 할 수 있어 출력장치에 상관없이 동일한 방법으로 출력을 설정
- DC란 윈도우 응용프로그램에서 화면 출력을 위해 출력 속성을 정의하는 구조체(struct). 즉, 화면 출력을 위해 여러 속성값들을 모아놓은 상자
DC를 얻는 방법
- DC는 한 순간에 하나의 펜, 브러시만 가질 수 있으므로 다른 펜/브러시를 사용하려면 새로운 것을 만들어서 DC를 설정해 야 함
- DC를 얻고 나면, 작업 완료 시 해제해야 함
4가지 DC를 얻는 방법
① OnDraw()함수, OnPaint()함수를 이용
- 그리기 작업을 수행하기 위해 DC를 인자로 받습니다. 예를 들어, MFC에서의 OnDraw() 함수는 CDC* pDC 매개변수를 가지며, 해당 매개변수를 통해 DC를 얻을 수 있습니다.
- 윈도우나 클라이언트 영역이 다시 그려져야 할 경우 수행 (Invalidate() 에 의해 호출됨 -> 화면 갱신)
- DC의 해제는 MFC 내부 코드에 존재(설정 하지 않아도 됨)
void CMyView::OnDraw(CDC* pDC) //인자로 CDC 클래스
{
// pDC를 사용하여 그리기 작업 수행
// ...
}
void CMyView::OnPaint() //인자는 없고 CPaintDC 클래스에서 객체 생성
{
CPaintDC dc(this); // 윈도우의 DC를 얻음
// dc를 사용하여 그리기 작업 수행
// ...
}
② GetDC() 함수를 이용
- GDI 함수 중 하나인 GetDC() 함수를 호출하여 DC를 얻을 수 있습니다. 일반적으로 윈도우 핸들(HWND)을 인자로 전달하여 해당 윈도우와 연결된 DC를 얻습니다.
- CDC 클래스의 인스턴스를 포인터 형태로 넘겨받아서 이용
- ReleaseDC() 함수를 호출하여 반드시 해제
- 이 방법으로 DC를 얻는 것은 일시적인 것으로 윈도우의 크기가 변하면 출력된 내용이 사라짐
- 왜??? 화면 변화가 생겼을 때 OnDraw() 함수나 OnPaint() 함수가 호출되면서 화면이 갱신되기 때문
CDC* pDC = GetDC(); // GetDC() 함수를 사용하여 DC를 얻음
// pDC를 사용하여 그리기 작업 수행
// ...
ReleaseDC(pDC); // DC 해제
③ CClientDC 클래스를 이용
- MFC에서 제공하는 CClientDC 클래스를 사용하여 DC를 얻을 수 있습니다. CClientDC 클래스는 클라이언트 영역을 그리기 위한 DC를 제공합니다. CClientDC 객체를 생성하고, 해당 객체의 멤버 변수로 DC를 얻을 수 있습니다.
- CDC 클래스의 파생 클래스
- Devie Context의 생성/해제 자동적 수행
-> 생성자 함수에서 GetDC() 함수 호출
-> 소멸자 함수에서 ReleaseDC() 함수 호출
- 윈도우에 대한 핸들 값 필요
- 일시적으로 윈도우의 클라이언트 영역에서 그래픽 개체를 사용할 경우 이용
- DC를 얻는 것은 일시적인 것으로 윈도우가 크기가 변하면 출력한 내용이 사라짐
//위의 예시에서 CMyView는 MFC의 CView 클래스를 상속받은 클래스로 가정
//SomeFunction() 함수에서는 CClientDC 객체를 생성하여 DC를 얻은 후, 해당 객체를 사용하여 클라이언트 영역에 그리기 작업을 수행
//함수를 빠져나가면서 CClientDC 객체가 소멸되면, DC는 자동으로 해제
void CMyView::SomeFunction()
{
CClientDC dc(this); // CClientDC를 사용하여 DC를 얻음
//현재 객체(this)를 통해 윈도우 핸들을 얻고, 그 핸들을 사용하여 CClientDC 객체를 생성하여 DC를 얻는 역할
// dc를 사용하여 클라이언트 영역에 그리기 작업 수행
// ...
}
④ CWindowDC 클래스를 이용
- 윈도우(프레임) 영역에 그래픽 요소를 출력하고자 할 때 사용
- GetWindowDC() 함수를 이용하여 CWindowDC 클래스의 인스턴스를 포인터 형태로 넘겨 받아 이용
- 작업 수행 후, ReleaseDC() 함수로 해제
CWindowDC *pDC = GetWindowDC(); // 윈도우 DC 얻음
… // 그래픽 출력
ReleaseDC(); // DC 반환
2. GDI 객체
- 화면에 그림을 그리거나 문자를 출력할 때 사용하는 객체
- 펜, 브러시, 폰트, 비트맵 등을 핸들링하는 핸들
GDI 기본 구성 요소
- 선과 곡선(Lines and Curves): 직선, 사각형, 타원, 호, 베지어 곡 선
- 채워진 영역(Filled Areas): 브러시 개체를 이용 – 색상, 패턴, 비 트맵 이미지
- 비트맵(Bitmaps): 디스플레이 장치의 픽셀과 일치하는 직사각 형 배열, 래스터 그래픽의 기본적인 도구
- 텍스트(Text)
화면에 그래픽 출력하기 위한 요소
객체를 사용하는 방법
① GDI 객체를 생성 - 펜, 브러쉬...
- 객체 클래스의 Create계열 함수 이용
② 객체를 DC에 등록
- SelectObject()함수를 이용
- DC를 쓰고 난 다음 원래 상태로 복원하기 위해 기존 설정된 객체는 포인터로 저장
③ DC를 사용하여 그래픽 출력
④ 이전 객체로 환원
⑤ 객체를 삭제
- GDI 객체 클래스의 DeleteObject() 함수 이용
GDI 객체-펜
- 선이나 영역의 경계선을 그릴 때 사용
- 선의 두께, 선이 색상, 선의 스타일을 설정
펜을 사용하는 방법
① CPen pen, *oldpen; // Pen 클래스의 인스턴스 생성, 기존 설정된 객체는 포인터로 저장
pen.CreatePen(PS_SOLID, 1,RGB(0,0,0)); // 실선이고 두께가 1인 검은색의 펜을 생성(객체 생성)
② oldpen = pDC->SelectObject(&pen);//객체 등록
③ pDC->Ellipse(0,0,10,10);//DC 사용해서 그래픽 출력
④ pDC->SelectObject(oldpen);//이전 객체로 환원
⑤ pen.DeleteObject();//객체 삭제
CreatePen() 함수
- CreatePen(): Pen을 생성하는 함수
- BOOL CreatePen(int nPenStyle, int nWidth,COLORREF crColor);
- nPenStyle : 펜의 스타일
- nWidth : 펜의 굵기
- crColor : 펜의 색상
펜의 스타일
GDI 객체-브러시
- 영역의 내부를 채울 때 사용
- 채울 색, 패턴 등이 사용
브러시를 사용하는 방법
① CBrush brush, *oldbrush; // Brush 클래스의 인스턴스 생성
brush.CreateSolidBrush(RGB(0,0,0)); // 검은색의 브러쉬를 생성
bush.CreateHatchBrush(HS_CROSS,RGB(0,0,0)); // 십자가 형태의 빗금을 가진 검은색 브러쉬 생성
② oldbrush = pDC->SelectObject(&brush);
③ pDC->Ellipse(0,0,10,10);
④ pDC->SelectObject(oldbrush);
⑤ brush.DeleteObject();
CreateSolidBrush() 함수
- 단일 색으로 칠하는 브러시를 생성하는 함수
CreateHatchBrush() 함수
- 일정한 패턴을 가진 해치 브러시를 생성하는 함수.
- 해치 브러쉬의 스타일
그래픽 함수들
- 선 그리기 MoveTo(int x, int y) 함수(시작 위치), LineTo(int x, int y)함수(끝 위치)
- 사각형 그리기 Rectangle(int x1, int y1, int x2, int y2) x1, y1=좌상단, x2, y2=우하단
- 원 그리기 Ellipse(int x1, int y1, int x2, int y2)
- 다각형 그리기 Polyline(LPPOINT lpPoints, int nCount) , Polygon(LPPOINT lpPoints, int nCount)
- 베지어 곡선 그리기 PolyBezier(const POINT* lpPoints, int nCount)
베지어 곡선 그리기
- 임의의 형태의 곡선을 표현하기 위해 수학적으로 만든 곡선
- 최초의 제어점인 시작점과 최후의 제어점인 끝점 그리고 그 사이에 위 치하는 내부 제어점의 이동에 의해 다양한 자유 곡선을 얻는 방법
래스터 오퍼레이션(Raster Operation)
- 새로 그려야 할 그림과 기존의 화면에 그려져 있는 그림을 합성하는 것
- 펜과 브러시에 적용되며 SetROP2()함수로 설정
- R2_COPYPEN : 배경의 화면을 무시하고 새로 그려지는 그림을 출력 (기본 옵션)
- R2_XORPEN : 배경의 화면을 유지하면서 움직이는 그림을 그릴 때 사용함
내장 GDI 객체
- 자주 사용되는 스타일의 GDI 객체는 윈도우가 내장하고 있어 따로 만들지 않고 윈도우에서 얻어서 사용 dc.SelectObject(GetStockObject(WHITE_BRUSH): 흰색 브러시 설정
- PEN: BLACK_PEN, WHITE_PEN, NULL_PEN
- BRUSH: BLACK_BRUSH, WHITE_BRUSH, GRAY_BRUSH, DKGRAY_BRUSH, LTGRAY_BRUSH, HOLLOW_BRUSH, NULL_BRUSH
- FONT: ANSI_FIXED_FONT, ANSI_VAR_FONT, DEVICE_DEFAULT_FONT, OEM_FIXED_FONT, SYSTEM_FONT
GDI 객체-비트맵
- CBitmap클래스를 이용하는 객체
- 비트맵을 생성하거나 읽어서 비트맵을 출력할 때 사용
- 비트맵의 래스터 오퍼레이션: BitBlt(), StretchBlt() ◼
- SRCCOPY : 배경 그림을 무시하고 비트맵 출력
- SRCAND : 배경 그림과 AND 연산
- SRCPAINT : 배경 그림과 OR 연산
비트맵을 사용하는 방법
① 화면 DC와 메모리 DC를 생성
② 화면 DC와 호환성을 갖는 DC를 만듬
③ 비트맵을 읽어 옴
④ 메모리 DC에 비트맵을 설정
⑤ 비트맵 블록을 전송
⑥ DC를 복원
① CClinetDC dc(this); // 비트맵이 출력된 화면 윈도우 DC 생성
CDC memdc; // 메모리의 DC 생성
② memdc.CreateCompatibleDC(&dc); // 현재 DC와 호환적인 메모리 DC 생성
③ CBitmap bitmap, *oldbitmap; // 비트맵의 인스턴스 생성
bitmap.LoadBitmap(IDB_BITMAP1); // 비트맵을 읽어 옴
④ Oldbitmap = memdc.SelectObject(&bitmap); // 메모리 DC에 비트맵을 설정
⑤ dc.BitBlt(0, 0, 450, 85, &memdc, 0, 0, SRCCOPY); // 비트맵을 출력
⑥ memdc.SelectObject(oldbitmap);
GDI 객체-폰트
- CFont 클래스를 이용하는 객체
- 문자를 출력할 때 사용하며 글자의 모양, 크기가 설정
- 폰트 관련 그래픽 함수
◼ TextOut(0, 0, “안녕하세요?”);
◼ SetTextColor(RGB(0,0,255)): 배경색은 그대로 두고 텍스트의 전경색을 설정
◼ SetBkColor(RGB(255,0,0)): 텍스트의 배경색을 설정
◼ SetBkMode(): 텍스트가 출력될 때 사각형으로 텍스트를 둘러싸는 배경색을 설정
◼ SetTextAlign(TA_LEFT|TA_TOP): 텍스트의 정렬방법 지정
직선, 곡선, 도형 그리기 실습
'윈도우프로그래밍' 카테고리의 다른 글
[윈도우 프로그래밍] 사용자 인터페이스 (0) | 2023.06.06 |
---|---|
[윈도우 프로그래밍 5장] 도큐먼트, 파일 입출력 (0) | 2023.06.05 |
[윈도우 프로그래밍] 대화상자 (0) | 2023.04.16 |
[윈도우 프로그래밍] 윈도우 프로그래밍의 이해 (0) | 2023.04.16 |
[윈도우 프로그래밍] MFC 개요 및 아키텍처 (0) | 2023.04.16 |