[Win32] 5. GDI 시스템 이해(1)

Sireal·2022년 3월 31일
0

C++/Win32/MFC

목록 보기
10/12
post-thumbnail

GDI를 공부하며 DC에 대해서도 공부해보자.

DC에 연결된 비트맵의 정보얻기

DC에 연결된 비트맵 핸들값 얻기

DC(Device Context)에는 여러가지 GDI Object 가 연결되어있음.

함수 원형
HGDIOBJ GetCurrentObject(HDC hdc, UINT uObjectType);

#include "wingdi.h"

HDC h_dc = ::GetDC(m_hWnd);		// DC 얻기. m_hWnd는 윈도우 핸들값
// DC에 연결된 GDI Object 중에서 비트맵 객체핸들값을 얻는다.
HGDIOBJ h_bitmap = ::GetCurrentObject(h_dc, OBJ_BITMAP);

GetCurrentObject()는 OBJ_BITMAP을 통해 HBITMAP을 얻음.
그거외에도
OBJ_BRUH -> HBRUSH,
OBJ_FONT -> HFONT,
OBJ_PAL -> HPALETTE,
OBJ_PEN -> HPEN
을 얻을 수 있음.

비트맵 핸들을 이용하여 비트맵 정보 얻기

위에서 얻어온 비트맵 핸들을 가져와서 GetObject()를 사용해서 BITMAP구조체 형식을 얻어올 수 있음.

HDC h_dc = ::GetDC(m_hWnd);
HGDIOBJ h_bitmap = ::GetCurrentObject(h_dc, OBJ_BITMAP);
BITMAP bmp_info;
::GetObject(h_bitmap, sizeof(BITMAP), &bmp_info); // 비트맵 정보를 얻어왔다!

// ... 작업생략데수 ...

// h_bitmap은 단순히 참조하기위해 핸들값만 받는 것이여서 해제할 필요X
::ReleaseDC(m_hWnd, h_dc); 	// 아까 사용하던 DC 반환

  • 위와같은 정보가 진짜 얻어짐. 신기하다!!!!
    • 참고로 bmBits는 현재 윈도우의 핸들을 사용했다면 NULL이 당연히 나옴. 신경 X

GetObject 함수에 대한 보충설명

wingdi.h에서 GetObject함수를 사용해봤음. 얘는 gdi32.lib을 사용함.
int GetObject(HGDIOBJ hgdobj, int cbBuffer, LPVOID lpvObject);
이 GetObject()함수로 여러 정보를 얻어올수 있다.

  • hgdiobj 핸들에 따라 뒤에서 사용하는 값들이 달라진다.

hgdiobj에 HBITMAP을 사용하는 경우

  • 'BITMAP 정보'를 얻어오는 거기 때문에, 2번째 인자는 BITMAP 구조체로 선언한 변수의 주소를 사용해서 받아온다.

hgdiobj에 HAPALETE를 사용하는 경우

  • '팔레트 수'를 얻어올때 사용함.
  • 2번째 인자에는 WORD크기를 명시, 그리고 WORD 주소로 받아오면됨
HBJOBJ h_pallete = ::GetCurrentObject(h_dc, OBJ_PAL);
WORD pal_count;
::GetObject(h_pallete, sizeof(WORD), &pal_count);

hgdiobj에 HPEN을 사용하는 경우

  • '펜객체 속성정보'를 얻어올때 사용.
  • 2번째인자는 LOGPEN 로..
HGDIOBJ h_pen = ::GetCurrentObject(h_dc, OBJ_PEN);
LOGPEN pen_info;
::GetObject(h_pen, sizeof(LOGPEN), &pen_info);

hgdiobj에 HRUSH를 사용하는 경우

  • '블러시 객체의 속성정보'를 얻을때 사용
  • 2번째 인자는 LOGBRUSH 로...
HGDIOBJ h_brush = ::GetCurrentObject(h_dc, OBJ_BRUSH);
LOGBRUSH brush_info;
::GetObject(h_brush, sizeof(LOGBRUSH), &brush_info);
// ... 작업생략데수 ...

hgdiobj에 HFONT를 사용하는 경우

  • '폰트 객체의 속성정보'를 얻을때 사용
  • 2번째 인자는 LOGFONT 로...
HGDIOBJ h_font = ::GetCurrentObject(h_dc, OBJ_FONT);
LOGFONT font_info;
::GetObject(h_font, sizeof(LOGFONT), &font_info);


GetBitmapBits, SetBitmapBits

GetBitmapBits(): 비트맵에 그려진 그림을 다른 형식의 이미지로 변환하거나 가져올때 사용

SetBitmapBits(): GDI도움없이 그림을 그리거나 패턴을 변겨할때 사용

비트맵의 '비트패턴'에 접근하려면?

비트맵 내부에 비트패턴을 바꾸고싶다..
GetBitmapBits, SetBitmapBits를 사용해서 비트패턴을 가져오고, 설정할수 있다.

비트패턴 크기 계산

폭*높이*색상수
즉,
폭 300, 높이 200, 32비트 색상이면 240,000Bytes 메모리로구성되어있다고 보면됨

아래코드는 폭300, 높이200, 32비트색상을 사용하는 '비트패턴'을 복사해 오거나 새로운 값을 설정하기 위해서 필요한 메모리를 할당하는 코드다.

// 300*200*4 크기로 메모리 할당
unsigned int *p_pattern = new unsigned int[300*200];

delete[] p_pattern; // 사용하던 메모리 해제

GetBitmapBits()

비트맵의 비트패턴을 복사해오는 함수
LONG GetBitmapBits(HBITMAP hbmp, LONG cbBuffer, LPVOID lpvBits);

  • hbmp : 비트패턴을 복사할 비트맵의 핸들값
  • cbBuffer : 비트패턴이 복사될 메모리주소 명시
  • 반환값 : 실제로 복사한 비트패턴의 크기가 반환됨.
	HBITMAP h_bitmap = CreateBitmap(300, 200, 1, 32, NULL);
	unsigned int *p_pattern = new unsigned int[300*200];
	int copy_size = GetBitmapBits(h_bitmap, 300 * 200 * 4, p_pattern);

	delete[] p_pattern;
	DeleteObject(h_bitmap);

SetBitmapBits()

비트맵에 새로운 '비트패턴'을 설정하는 함수
LONG SetBitmaptBits(HBITMAP hbmp, DWORD cb, const VOID *pvBits);

  • hbmp : 비트패턴을 생성할 비트맵의 핸들값
  • cb : 설정할 바이트수
  • pvBits : 비트패턴에 설정할 새로운 비트패턴이 저장도니 메모리주소
  • 반환값 : 실제로 설정한 비트패턴의 크기 반환
	HBITMAP h_bitmap = CreateBitmap(300, 200, 1, 32, NULL);
	unsigned int *p_pattern - new unsigned int[300 * 200];
	for (int i = 0; i < 300 * 200; i++) {
		*(p_pattern + i) = 0xFF0000FF;
	}
	int copy_size = SetBitmapBits(h_bitmap, 300 * 200 * 4, p_pattern);

	delete[] p_pattern;
	DeleteObject(h_bitmap);


GetSystemMetrics()

컴퓨터 해상도와 같은 특성을 생각하며 프로그래밍해야한다.
해상도와 같은 하드웨어적인 정보를 얻어서 사용할 때 사용하는 함수가
GetSystemMetrics() 함수이다.

GetSystemMetrics()

시스템정보를 반환한다.
Winuser.h 에 선언되어있다.
int GetSystemMetrics(int nIndex);

  • nIndex 에 사용가능한 상수값들은 SM_ 으로 시작하는 상수이며, 100가지가 넘김
    • 필요한 정보가 있다면 그때그때 보면서 사용하면 된다.
    • SM_CXSCREEN : 화면의 X축(가로해상도, Pixel단위) 반환
    • SM_CYSCREEN : 화면의 Y축(세로해상도, Pixel단위) 반환
    • SM_CXFULLSCREEN : 전체화면 X축 반환
    • SM_CYFULLSCREEN : 전체화면 Y축 반환
    • SM_CYCAPTION : 일반 윈도우의 캡션(타이틀)바 높이를 얻는다.
      • 기본값은 23. 특별히 만져줬다면 다름
    • SM_CMONITORS : 현재 시스템의 모니터 개수 반환
    • SM_NETWORK : 현재시스템 네트워크 상태 반환
  • 이런식으로 사용한다.
#include <Winuser.h>

int cx = GetSystemMetrics(SM_CXSCREEN);
int cy = GetSystemMetrics(SM_CYSCREEN);

GetSystemMetrics() 단점

컴퓨터의 단순한 상태 값이나 설정값만 받아올수 있다.
상세한 정보를 얻으려면 다른 함수를 호출해야한다.

  • 색상수 를 얻고싶으면 GetDeviceCaps() 와 같은 함수를 호출해야함.

GetDC()와 ReleaseDC()

그림그리기 작업을 하려면 GDI를 사용해하는데, DC핸들러가 필요하다.

Recatangle(h_dc, 50, 50, 100,100);

GetDC() - DC구성하기

화면전체 또는 특정Window에 그림을 그리기 위해 사용할 DC를 만드는 함수

HDC GetDC(HWND hWnd);
  • DC의 정보를 얻어서 GDI함수를 사용하면 화면에 그림이 그려짐.
  • ※ 주의 ※ : GetDC()로 얻어온 DC핸들러의 Bitmap 객체는 SelectObject()를 이용해서 다른 Bitmap객체로 변경 불가함
  • hWnd 매개변수에 NULL을 하면 전체화면으로 그려짐.

화면 전체에 그림그리기

HDC h_screen_dc = ::GetDC(NULL);	// 화면  DC를 얻는다.
Reatangle(h_screen_dc, 50, 50, 100, 100); // 사각형을 그린다.

  • 이렇게 전체화면의 시작(0,0) 에서 네모가 생성됐다.(신기하다!!)
HDC h_screen_dc = ::GetDC(hWnd);	// 현재윈도우의 DC를 얻는다.
Reatangle(h_screen_dc, 50, 50, 100, 100); // 사각형을 그린다.

ReleaseDC() - DC 제거하기

  • DC는 사용 개수 제한이 있음. GetDC를 남용하다보면 더이상 사용못함.
  • DC를 사용하면 무조건 반환해줘야함

ReleaseDC() 의 원형이다.
int Release(HWND hWnd, HDC nDC);

HDC h_cd = ::GetDC(hWnd); // m_hWnd에 해당하는 윈도우의 DC값을 얻는다.
Rectangle(h_dc, -50, -50, 50,50); // 사각형을 그린다.
::Release(m_hWnd, h_dc); h_dc를 제거한다.

DC를 여러 개 생성하기

HDC h_dc1 = ::GetDC(m_hWnd);
HDC h_dc2 = ::GetDC(m_hWnd);

Rectangle(h_dc1, 50, 50, 100, 100);
Rectangle(h_dc2, 100, 100, 150, 150);

::ReleaseDC(m_hWnd, h_dc1);
::ReleaseDC(m_hWnd, h_dc2);

  • 오옹!!!! 된다!!
  • 이렇게 하나의 윈도우에 여러 DC를 사용해서 여러 그림을 그릴수 있다.
    • ※주의※ : 이렇게 사용하면 그래픽자원에 무리를 줌.
    • 일반적으로 보통 윈도우 한개에 DC 하나만 사용함.

점단위 좌표를 기억하는 자료형(DataType)

pixel(점) 단위 조표를 사용하는 대표적인 것중하나가 마우스 좌표다.

점 단위 좌표 저장

int x, y; : (x,y) 좌표를 다룬다.

  • short x, y; : 근데 4K 해상도를 넘기는게 아니면 short형도 ㄱㅊ다.

GetCursorPos() : 커서위치 반환

BOOL GetCurosorPos(LPPOINT lpPoint);

  • LPPOINT 형식으로 받아온다.
    typedef tagPoINT FAR *LPPOINT; 이런 구조체로 되어있다.
    • 16비트 시스템 에선 NEAR 키워드를 사용했는데 지금은 그냥 FAR키워드를 사용한다.

struct gatPOIT *PPOINT;

struct tagPOINT{
	LONG x;
    LONG y;
};
  • 이런식으로 되어있음

!!그냥 이렇게 쓰면 된다!!

POINT pos;
GetCursorPos(&pos); // 마우스 커서의 좌표를 얻음(화면좌표)

CPoint - MFC에서 제공되는 C++클래스

CPoint pos;
GetCursorPos(&pos); // 마우스 커서의 좌푤르 얻음 (화면 좌표)

POINT vs CPoint

  • 단순한 점좌표만 저장사용할거면 POINT
  • 다른 점과 위치 또는 거리에 대한 개념을 계산하거나 비교하자만 CPoit
profile
🚄계속 앞으로🚄

0개의 댓글