GDI
비주얼C++ API - 5. API 그래픽
1. GDI
GDI는 그래픽 출력을 위한 모든 도구, 함수의 집합을 의미합니다.
GDI 사용을 위한 개체들을 모아놓은 것이 DC이며 GDI는 현재 DC에 선택된 GDI 개체를 사용합니다.
1) DC 생성
- WM_PAINT 메시지에서 DC 얻기
처리 루틴에서는 BeginPaint 함수로 얻으며 핸들을 해제할 때는 EndPaint 함수를 사용합니다.
BeginPaint는 WM_PAINT 메시지 내에서 그림 그리기 준비를 하는 전문적인 함수입니다.
PAINTSTRUCT 변수;
HDC dc변수;
case WM_PAINT:
hdc = BeginPaint (윈도우핸들, &변수);
그리기 작업;
EndPaint(윈도우핸들, &변수);
- 다른 메시지에서 DC얻기
HDC dc변수;
case 메시지:
dc변수 = GetDC(윈도우핸들);
그리기 작업;
ReleaseDC(윈도우핸들, dc변수);
- 윈도우 전체에 해당하는 DC를 얻기 위해서는 GetDC 대신에 GetWindowDC 함수를 이용하면 됩니다.
- 메모리 DC 생성
dc변수 = CreageCompatibleDC(기존 DC 변수);
2) 디폴트 GDI 개체
GDI 오브젝트 |
핸들 타입 |
설명 |
디폴트 |
펜 |
HPEN |
선을 그을 때 사용 |
검정색의 가는 선 |
브러시 |
HBRUSH |
면을 채울 때 사용 |
흰색 |
폰트 |
HFONT |
문자 출력에 사용 |
시스템 글꼴 |
비트맵 |
HBITMAP |
비트맵 이미지 |
선택되지 않음 |
팔레트 |
HPALETTE |
팔레트 |
선택되지 않음 |
영역 |
HRGN |
영역 |
선택되지 않음 |
2.Stock Object
스톡 오브젝트(Stock Object)는 Windows가 기본적으로 제공해 주는 내장 GDI 오브젝트를 의미합니다.
운영체제가 제공해 주므로 일부러 만들지 않아도 언제든지 사용할 수 있으며 사용하고 난 후에 파괴시켜 줄 필요도 없습니다.
형식
HGDIOBJ GetStockObject(int fnObject);
fnObject 인수에 사용하고자 하는 스톡 오브젝트를 기입해 주면 됩니다.
오브젝트 |
설명 |
BLACK_BRUSH |
검정색 브러시 |
GRAY_BRUSH |
회색 브러시 |
NULL_BRUSH |
투명 브러시 |
WHITE_BRUSH |
흰색 브러시 |
DKGRAY_BRUSH |
짙은 회색 브러시 |
LTGRAY_BRUSH |
옅은 회색 브러시 |
DC_BRUSH |
색상 브러시. SetDCBrushColor 함수로 설정 |
BLACK_PEN |
검정색 펜 |
WHITE_PEN |
흰색 펜 |
NULL_PEN |
투명 펜 |
DC_PEN |
색상 펜. SetDCPenColor 함수로 설정 |
ANSI_FIXED_FONT |
고정 폭 폰트 |
ANSI_VAR_FONT |
가변 폭 폰트 |
DEFAULT_PALETTE |
시스템 팔레트 |
위에서 DC_PEN과 DC_BRUSH는 윈도우 2000 이상에서만 사용가능 합니다.
3. 색상
Windows에서는 색상값을 표현하기 위해 COLORREF라는 자료형을 사용하는데 이는 다음과 같이 정의되어 있습니다.
typedef DWORD COLORREF;
COLORREF 형은 부호없는 32비트 크기의
색상을 설정하는 형식
COLORREF color = RGB(빨강, 녹색, 파랑)
각 색상 값은 0 - 255까지 가능합니다.
4. 펜
펜은 선을 그을 때 사용되는 GDI 오브젝트입니다.
펜을 변경하면 그려지는 선의 모양을 변경할 수 있습니다.
윈도우즈가 제공하는 스톡 펜은 흰색, 검정색, 투명색 세 가지 뿐이며 파란색, 노란색 등의 원색 펜은 없습니다.
이런 펜을 사용하고자 할 때는 직접 만들어서 사용해야 합니다.
형식
HPEN CreatePen(int fnPenStyle, int nWidth, COLORREF crColor);
fnPenStyle
그려질 선의 모양을 정의합니다.
이 값을 변경하면 실선뿐만 아니라 다양한 형태의 선을 만들 수 있습니다.
실선, 점선, 일점 쇄선 등등의 선 모양이 있습니다.
선의 모양은 PS_SOLID PS_DASH PS_DOT PS_DASHDOT PS_DASHDOTDOT 등이 있으며 정수 값을 매크로로 정의한 것이므로 정수를 사용해도 됩니다.
nWidth
선의 두께입니다.
디폴트 선의 굵기는 1이지만 이 값을 2나 3으로 변경해 주면 두꺼운 선을 그릴 수 있습니다.
단 이 값이 0일 경우는 무조건 1픽셀 두께의 선이 만들어집니다.
crColor
선의 색상을 지정합니다.
COLORREF 형이므로 RGB 매크로 함수를 사용하면 됩니다.
주의할 점이 있습니다.
선의 두께는 PS_SOLID 일 때만 적용됩니다.
선의 두께를 1로 지정하지 않으면 모양은 무시됩니다.
GDI 객체를 사용할 때의 규칙
- 생성한 모든 GDI 객체는 삭제되어야 합니다.
- 내장 객체는 삭제해서는 안됩니다.
- DC가 사용하고 있는 GDI 객체는 삭제되어서는 안됩니다.
GDI 오브젝트는 사용한 후 반드시 삭제해 주어야 합니다.
왜냐하면 GDI 오브젝트는 운영체제의 자원을 사용하기 때문입니다.
메모리를 할당한 후 반드시 해제해 주어야 하는 것과 마찬가지로 GDI 오브젝트도 사용이 끝나면 해제해 주어야 하는 것이 원칙입니다.
만약 해제해 주지 않으면 시스템의 자원을 계속해서 사용하게 될 것입니다.
GDI 오브젝트 사용하는 방법
SelectObject(DC핸들, HGDIOBJ hObject);
GDI 오브젝트 해제 형식
BOOL DeleteObject( HGDIOBJ hObject );
삭제하고자 할 때는 GDI 오브젝트의 핸들만 인수로 넘겨주면 됩니다.
이때 주의할 것은 DC에 현재 선택되어 있는 GDI 오브젝트는 삭제할 수 없다는 점입니다.
그래서 삭제를 하기 전에 먼저 DC에 선택된 객체를 선택 해제해주거나 아니면 DC 파괴후 해제해야 합니다.
예제) 선 변경 예제
GDI 객체를 해제하는 방법은 여러가지가 있습니다.
위처럼 복사해두고 지우는 방법도 있으며 복사하지 않고 DC 해제 후 DeleteObject를 호출하는 방법도 있습니다.
대시 선에서 배경 색 채우기
COLORREF SetBkColor( HDC hdc, COLORREF crColor );
int SetBkMode( HDC hdc, int iBkMode );
SetBkColor는 뒤의 배경색상을 지정하는 함수입니다.
COLORREF형의 인수를 취하므로 RGB 매크로 함수를 사용하여 원하는 색상을 지정하면 됩니다.
SetBkMode 함수는 배경색상을 사용할 방법을 설정합니다.
OPAQUE와 TRANSPARENT 두 가지 옵션 중 한가지를 선택할 수 있으며 디폴트는 OPAQUE입니다.
TRANSPARENT를 이용하면 색상이 적용되지 않습니다.
5. 브러시
브러시는 둘러싸여진 영역을 채우는 용도로 사용됩니다.
사각형의 안쪽이나 원의 내부 또는 다각형의 내부를 채울 때 현재 DC에 선택된 브러시가 사용됩니다.
스톡 오브젝트로는 회색, 흰색, 검정색 등의 단색 브러시가 있으므로 이 브러시들은 별도로 만들지 않아도 사용할 수 있습니다.
이 외의 브러시는 직접 만들어 사용해야 합니다.
브러시 만드는 형식
HBRUSH CreateSolidBrush( COLORREF crColor );
HBRUSH CreateHatchBrush( int fnStyle, COLORREF clrref );
HBRUSH CreatePatternBrush(HBITMAP hbmp);
CreateSolidBrush 함수는 단색의 브러시만을 만들 수있으며 브러시의 색상만 인수로 전달해 주면 됩니다.
CreateHatchBrush 함수는 색상뿐만 아니라 무늬도 같이 지정할 수 있다.
무늬의 종류
값 |
설명 |
HS_BDIAGONAL |
좌하향 줄무늬 |
HS_CROSS |
바둑판 모양 |
HS_DIACROSS |
좌하향 및 우하향 줄무늬 |
HS_FDIAGONAL |
우하향 줄무늬 |
HS_HORIZONTAL |
수평선 |
HS_VERTICAL |
수직선 |
정수값을 매크로로 지정한 것이므로 위의 이름이 아닌 정수 값을 이용해서 사용해도 무방합니다.
CreatePatternBrush 는 비트맵을 이용해서 채워주는 브러시입니다.
노란색의 솔리드 브러시와 펜 사용
SetPolyFillMode함수
int SetPolyFillMode(HDC hdc, int iPolyFillMode)
다각형을 그릴 때 채우기 모드를 설정하는 함수입니다.
iPolyFillMode옵션
AlTERNATE: 홀수 개의 선으로 교차하는 영역만 채워짐
WINDING 모드: 모든 영역이 칠해짐
예제)
6. GDI객체를 해제 하지 않을 때의 문제점
만일 GDI 객체를 만들고 해제 하지 않는다면 펜도 자원이므로 일정 개수 이상 사용할 수 없을 것입니다.
예제) 펜 오브젝트를 해제하지 않고 사용하는 경우
7. 투명 오브젝트
NULL PEN 과 NULL BRUSH를 사용하면 투명한 오브젝트를 생성할 수 있습니다.
예제)
8. ROP 모드
일반적으로 무엇인가가 그려져 있는 상황에서 다른 내용을 위에 그리게 되면 이전 내용은 없어지게 됩니다.
프로그래밍에서는 이전 출력 내용과의 관계를 설정할 수 있는데 이를 ROP 모드라고 합니다.
ROP 모드는 비트연산이 기본입니다.
그리기 모드를 변경하는 함수와 현재 설정된 그리기 모드를 구하는 함수는 다음과 같다.
int SetROP2(HDC hdc, int fnDrawMode );
첫 번째 인수는 그리기 모드를 변경(또는 조사)하고자 하는 DC의 핸들이며 SetROP2 함수의 두 번째 인수에는 ROP 모드 값을 주게 됩니다.
그리기 모드 |
설명 |
R2_BLACK |
항상 검정색 |
R2_WHITE |
항상 흰색 |
R2_NOP |
그리기를 하지 않음 |
R2_NOT |
원래의 그림을 반전 |
R2_COPYPEN |
이전 내용을 지우고 그림 |
R2_NOTCOPYPEN |
새 그림을 반전시켜 그림 |
R2_NOTXORPEN |
XOR연산의 반대 값을 가지고 그림 |
R2_MERGEPEN |
OR연산으로 두 그림을 합침 |
R2_MASKPEN |
AND연산으로 겹치는 부분만 그림 |
R2_XORPEN |
XOR연산으로 겹치는 부분만 반전시킴 |
int GetROP2(HDC hdc );
현재의 ROP 모드 값을 리턴시킴
Windows에서 사용하는 디폴트 그리기 모드는 R2_COPY 모드입니다.
따라서 항상 이전 내용이 지워진 후 그려지게 되는 것입니다.
9. 매핑 모드
화면에서 기준점과 기준점을 논리적인 단위를 설정하는 모드를 매핑모드라고 합니다.
윈도우에서 사용하는 매칭모드는 8가지가 있습니다.
MapMode |
논리 단위 |
MM_ANISOTROPIC |
사용자 지정(x!y) |
MM_HIENGLISH |
0.001 inch |
MM_HIMETRIC |
0.01mm |
MM_ISOTROPIC |
사용자 지정(x=y) |
MM_LOENGLISH |
0.01 inch |
MM_LOMETRIC |
0.1mm |
MM_TEXT |
Pixel |
MM_TWIPS |
1/1440 inch |
모드 설정은 SetMapMode(DC핸들, 매핑 모드)로 설정합니다.
좌표계
- screen 좌표: 이 좌표계는 현재 보고 있는 화면 전체에 대한 좌표계입니다.
WM_MOVE 메시지에서 이 좌표계로부터 현재 윈도우의 좌표를 얻어낼 수 있습니다.
또한 GetWindowRect()를 이용해서 위치와 크기를 알아낼 수 있습니다.
이 좌표계는 일반적으로 전체 화면에서 위치를 이용해서 특정 윈도우를 이동하거나 찾고자 하는 경우에 사용합니다.
CreateDC()를 이용해서 화면 전체에 대한 DC를 생성할 수 있습니다.
HDC CreateDC(LPCTSTR lpszDriver, LPCTSTR lpszDevice, LPCTSTR lpszOutput, CONST DEVMODE* lpInitData);
lpszDriver: 장치 드라이버 이름 - Display이면 모니터 전체(일반적으로 vendor 이름)
lpszDevice: 장치 이름(일반적으로 vendor의 모델 명)
lpszOutput: 출력 장치 이름(파일 명이나 포트 번호)
lpInitData: 프린터에 출력할 데이터
CreateDC(TEXT(“Display”),NULL, NULL, NULL)이면 모니터 전체 화면에 대한 DC 생성
이 DC는 DeleteDC(HDC hdc);로 해제해야 합니다.
예제)
- 윈도우 좌표계: 이 좌표계는 현재 프로그램 전체에 대한 좌표계입니다.
GetWindowDC()를 이용해서 DC를 생성하고 프로그램의 왼쪽 맨 상단이 0,0이 됩니다.
- 클라이언트 좌표계: 클라이언트 영역에 대한 좌표계입니다.
GetDC()나 BeginPaint()를 이용해서 DC를 생성합니다.
- 좌표 변환함수
ClientToScreen(HWND hWnd, LPPOINT lpPoint);
윈도우 핸들의 좌표를 스크린 좌표로 변환해주는 함수
ScreenToClient(HWND hWnd, LPPOINT lpPoint);
스크린 좌표를 hWnd의 좌표로 변환해주는 함수
10. 비트맵 출력
1) 메모리 DC
Windows는 비트맵을 곧바로 화면 DC로 출력하는 함수는 제공하지 않습니다.
Windows에서는 메모리 DC를 이용해서 비트맵을 출력합니다.
메모리 DC란 화면 DC와 동일한 특성을 가지며 그 내부에 출력 영역을 가진 메모리 영역입니다.
메모리에 있기는 하지만 화면 DC에서 사용할 수 있는 모든 출력을 메모리 DC에서도 할 수 있습니다.
메모리 DC에 먼저 그림을 그린 후 사용자 눈에 그려지는 과정은 보여주지 않고 메모리 DC에서 작업을 완료한 후 그 결과만 화면으로 출력 방법을 사용합니다.
비트맵도 일종의 GDI 오브젝트이지만 화면 DC에서는 선택할 수 없으며 메모리 DC만이 비트맵을 선택할 수 있습니다.
따라서 메모리 DC에서 먼저 비트맵을 읽어온 후 화면 DC로 출력하게 됩니다.
메모리 DC를 만드는 방법
HDC CreateCompatibleDC( HDC hdc );
인수로 화면 DC의 핸들을 주며 이 화면 DC와 동일한 특성을 가지는 DC를 메모리에 만들어 그 핸들 값을 반환해 줍니다.
호환되지 않는 DC끼리는 정보를 공유할 수 없기 때문에 화면 DC와 호환되는 메모리 DC를 만들어야 합니다.
메모리 DC를 만든 후에는 비트맵을 읽어온 후 이 비트맵을 메모리 DC에 선택해 줍니다. 선택하는 방법은 다른 GDI 오브젝트와 마찬가지로 SelectObject 함수를 사용하며 비트맵을 읽어올 때는 LoadBitmap 함수를 사용합니다.
HBITMAP LoadBitmap( HINSTANCE hInstance, LPCTSTR lpBitmapName );
첫 번째 인수는 비트맵 리소스를 가진 인스턴스의 핸들이며 두 번째 인수는 비트맵 리소스의 이름입니다.
읽어온 비트맵을 SelectObject 함수로 메모리 DC에 선택하면 메모리 DC의 표면에는 리소스에서 읽어온 비트맵이 그려져 있을 것입니다.
비트맵을 불러올 때 인스턴스 핸들을 필요로 하므로 HINSTANCE 자료형으로 전역 변수를 선언한 후 WinMain 함수에서 인스턴스 핸들값을 대입한 후 전역변수를 WndProc 함수에서는 사용해야 합니다.
2) 비트맵 출력함수
BOOL BitBlt( HDC hdcDest, int nXDest, int nYDest, int nWidth, int nHeight, HDC hdcSrc, int nXSrc, int nYSrc, DWORD dwRop );
첫 번째 인수는 복사 대상 DC이며 다음 네 개의 인수는 복사 대상의 시작하는 좌표와 폭과 높이 이며 PSrcDC가 복사원의 DC입니다.
xSrc, ySrc는 복사 원의 좌표이되 BitBlt는 비트맵의 크기를 변경시키지 않고 복사를 수행하므로 폭과 높이는 복사 대상에서 한번만 지정하고 복사원에서는 이 값을 그대로 사용합니다.
BitBlt의 마지막 인수 dwRop는 레스터 연산 방법을 지정하며 SRCCOPY를 쓰면 복사원을 그대로 복사 대상으로 복사합니다.
dwRop에 다른 값을 사용하면 기존 그림에 겹친다거나 반전시킬 수도 있습니다.
dwRop 연산
값 |
설명 |
BLACKNESS |
대상영역을 검정색으로 가득 채움 |
DSTINVERT |
화면을 반전 |
MERGECOPY |
소스 비트맵과 대상 화면을 AND 연산 |
MERGEPAINT |
소스 비트맵과 대상 화면을 OR 연산 |
SRCCOPY |
소스 영역을 대상 영역에 복사 |
WHITENESS |
대상영역을 흰색으로 채움 |
SRCAND |
AND 연산 |
SRCINVERT |
XOR 연산 |
SRCPAINT |
OR 연산 |
BOOL StretchBlt( HDC hdcDest, int nXOriginDest, int nYOriginDest, int nWidthDest, int nHeightDest, HDC hdcSrc, int nXOriginSrc, int nYOriginSrc, int nWidthSrc, int nHeightSrc, DWORD dwRop );
BitBlt와 마찬가지로 DC간의 복사를 수행하지만 복사 후에 크기를 변경할 수 있다는 점이 다릅니다.
인수를 보면 복사 대상과 복사원이 모두 폭과 높이를 가지고 있습니다.
복사원의 지정한 영역이 복사대상의 지정한 영역의 크기만큼 확대되거나 축소되어 출력됩니다.
그래픽 출력
전역 영역에서 HINSTANCE hInst를 선언하고 WinMain 함수에서 hInst에 hInstance를 대입하고 fly.bmp 파일을 리소스로 추가하고 수행해야 함
11. 폰트
1) 폰트 만들기
폰트를 만들기 위해서는 CreateFont 함수를 사용하며 이 함수가 반환해 주는 핸들을 HFONT형의 변수에 대입해 주면 됩니다.
CreateFont 함수의 형식
HFONT CreateFont( int nHeight, int nWidth, int nEscapement, int nOrientation, int fnWeight, DWORD fdwItalic, DWORD fdwUnderline, DWORD fdwStrikeOut, DWORD fdwCharSet, DWORD fdwOutputPrecision, DWORD fdwClipPrecision, DWORD fdwQuality, DWORD fdwPitchAndFamily, LPCTSTR lpszFace );
인수 |
설명 |
nHeight |
폰트의 높이를 논리적인 단위로 지정합니다. 이 값이 0일 경우는 디폴트 크기가 사용됩니다. |
nWidth |
폰트의 폭을 지정하되 이 값이 0이면 nHeight에서 지정한 높이에 따라 폭을 자동으로 결정합니다. 즉 이 값이 0이면 폰트의 종횡비(장평)가 일정합니다. |
nEscapement |
폰트의 각도를 0.1도 단위로 설정합니다. 이 각도는 문자가 출력될 X축과 문자열과의 각도이며 일상적인 360분법의 각도 체계를 사용합니다. |
nOrientation |
글자 한자와 X축과의 각도를 지정합니다. nEscapement가 전체 문자열의 기울기를 설정하는데 비해 이 인수는 개별 문자의 기울기를 설정합니다. |
fnWeight |
폰트의 무게를 0∼1000까지의 값으로 설정합니다. 쉽게 말해서 폰트의 두께를 설정합니다. 0∼1000까지의 값을 지정할 수 있으며 보통굵기인 FW_NORMAL이 400입니다. |
fdwItalic, fdwUnderline, fdwStrikeOut |
기울임체, 밑줄, 관통선 속성을 설정합니다. 데이터 형이 BYTE이지만 불린 형처럼 사용합니다. 속성을 주고 싶으면 0 이외의 값(TRUE)을 주고 속성을 주지 않으려면0(FALSE)을 줍니다. |
fdwnCharSet |
문자 셋을 설정합니다. 여러 가지 값이 있지만 실제 사용될 수 있는 옵션에는 ANSI_CHARSET 과 OEM_CHARSET이 있습니다. ANSI_CHARSET이 윈도우에서 사용하는 문자셋이고 OEM_CHARSET가 도스에서 사용하는 문자셋이라고 생각하면 됩니다. |
fdwOutPutPrecision |
출력 정확도를 설정합니다. |
fdwClipPrecision |
클리핑 정확도를 설정합니다. |
fdwQuality |
논리적 폰트를 물리적 폰트에 얼마나 근접 시킬 것 인가를 지정합니다. |
nPitchAndFamily |
폰트의 피치와 그룹을 설정합니다. |
lpszFacename |
글꼴의 이름을 나타내는 문자열을 설정합니다. |
예제) 폰트 생성 예제
위처럼 폰트를 생성해서 사용할 수도 있습니다.
하지만 위와 같은 방법은 의미없는 속성에도 값을 전달해야 하므로 매우 번거롭습니다.
이런 경우에는 CreateFintIndirect(LOGFONT lf)를 이용하여 작성하는 것이 바람직합니다.
LOGFONT 구조체의 멤버는 CreateFont의 매개 변수와 일치합니다.
하지만 지정하고자 하는 멤버에만 값을 전달하면 됩니다.
예제)
2) 글자의 색상 지정
폰트 오브젝트 외에 출력되는 문자열에 영향을 주는 여러 가지 함수가 있습니다.
COLORREF SetTextColor( HDC hdc, COLORREF crColor );
SetTextColor는 Text의 Color를 설정하는 함수입니다.
COLORREF SetBkColor( HDC hdc, COLORREF crColor );
int SetBkMode( HDC hdc, int iBkMode );
'C & C++ > MFC Media' 카테고리의 다른 글
배경 이미지 연속적으로 돌리기 (0) | 2011.04.28 |
---|---|
화면 갱신 OnPaint(), OnDraw(), Invalidate() (0) | 2011.04.27 |
GDI 를 이용한 화면출력 (0) | 2011.04.25 |
이미지 CxImage (0) | 2011.04.25 |
쓸만한 Rect 관련 API 함수 (0) | 2011.03.27 |
댓글