Message 란?
메세지는 사용자나 시스템의 특정 이벤트(내부적인 동작)에 의해 발생하는 변화의 정보를 담은 구조체이다.
Ex) 키보드의 입력, 마우스를 눌렀을 때, 마우스를 누르고 있을 때, 마우스를 뗏을 때, 윈도우를 축소시켰을 때 등등....
윈도우는 발생하는 메세지를 쌓아서 먼저 들어온 순서대로 처리하는데, 이를 메세지 큐라고 한다.윈도우는 위 과정을 거치며 쌓인 메세지 큐를 처리하는 과정을 반복하게 되는데, 이를 메세지 루프라고 한다. 발생하는 메세지의 종류는 아래에서 다룰 윈도우 프로시저에서 볼 수 있다.
(BOOL) GetMessage(LPMSG lpMsg, HWND hWnd, UINT wMsgFilterMin, UINT wMsgFilterMax) : 메세지에 WM_QUIT를 받아오면 false를 반환하고 그 외의 메세지는 true를 반환한다. 메세지 큐에 메세지가 발생할 때 까지 대기(블러킹)한다.
lpMsg | 메세지 큐에서 발생한 MSG(메세지)의 구조체에 대한 포인터 |
hWnd | 이벤트가 발생한 윈도우에 대한 핸들 |
wMsgFilterMin | 조사할 메세지의 최소 값 |
wMsgFilterMax | 조사할 메세지의 최대 값 |
https://learn.microsoft.com/ko-kr/windows/win32/api/winuser/nf-winuser-getmessage
(BOOL) PeekMessage(LPMSG lpMsg, HWND hWnd, UINT wMsgFilterMin, UINT wMsgFilterMax, UINT wRemoveMsg) : 메세지 큐에 메세지가 발생하면 true, 아니면 false를 반환한다. 대기하는 과정이 없기 때문에 논 블러킹이다.
lpMsg | 메세지 큐에서 발생한 MSG(메세지)의 구조체에 대한 포인터 |
hWnd | 이벤트가 발생한 윈도우에 대한 핸들 |
wMsgFilterMin | 조사할 메세지의 최소 값 |
wMsgFilterMax | 조사할 메세지의 최대 값 |
wRemoveMsg | 메세지를 처리하는 방법 (PM_매크로를 사용) |
https://learn.microsoft.com/ko-kr/windows/win32/api/winuser/nf-winuser-peekmessagea
RemoveMsg의 매개 변수에는 다음 값이 올 수 있다.
메세지를 처리하는 방법
PM_NOREMOVE | PeekMessage에서 처리한 후 큐에서 메시지가 제거되지 않습니다. |
PM_REMOVE | PeekMessage에서 처리한 후 큐에서 메시지가 제거됩니다. |
PM_NOYIELD | 시스템에서 호출자가 유휴 상태가 될 때까지 대기 중인 스레드를 해제하지 못하도록 합니다. 이 값을 PM_NOREMOVE 또는 PM_REMOVE 결합합니다. |
PM_QS_INPUT | 마우스 및 키보드 메시지를 처리합니다. |
PM_QS_PAINT | 그리기 메시지를 처리합니다. |
PM_QS_POSTMESSAGE | 타이머 및 바로 가기 키를 포함하여 게시된 모든 메시지를 처리합니다. |
PM_QS_SENDMESSAGE | 전송된 모든 메시지를 처리합니다. |
(BOOL) TranslateMessage (CONST MSG lpMsg) : 키보드 입력에 관련된 메세지를 받을 때 무슨 키를 입력받았는지 등의 상태를 받아서 메세지 큐에 덧붙입니다.
lpMsg | 메세지 큐에서 발생한 MSG(메세지)의 구조체에 대한 포인터 |
https://learn.microsoft.com/ko-kr/windows/win32/api/winuser/nf-winuser-translatemessage
(BOOL) DispatchMessage(CONST MSG lpMsg) : 메세지 값을 받아서 윈도우 프로시저 함수를 호출해준다.
lpMsg | 메세지 큐에서 발생한 MSG(메세지)의 구조체에 대한 포인터 |
https://learn.microsoft.com/ko-kr/windows/win32/api/winuser/nf-winuser-dispatchmessage
WndProc(윈도우 프로시저) 란?
WinMain함수는 특정 이벤트를 통해 발생한 메세지를 메세지 루프를 통해 받고 큐에 저장한다.
WndProc(윈도우 프로시저)는 위와 같은 메세지큐에 저장된 메세지를 처리하기 위한 메세지 처리 전용 함수이다.
윈도우 프로시저는 사용자가 호출할 수 없고 윈도우만이 호출할 수 있는데, 이러한 함수를 콜백 함수(CallBack Function)이라고 한다.
아래는 윈도우 프로시저 함수에 대한 문법 및 매개변수이다.
(LRESULT) CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) : CALLBACK은 함수 호출 규약(Calling Convention)으로, 생략해도 컴파일 할 때 자동으로 선택된다. 하지만 예외적으로 호환성을 위해 명시적으로 호출 규약을 지정해야 할 때가 있을수도 있다. wParam과 lParam은 부가적인 메세지를 받아온다. 예를 들면 키 입력에 관한 메세지를 받았을 때, 키보드의 무슨 값을 입력 받았는지, 마우스의 x, y좌표는 몇인지 등등의 정보이다.
hWnd | Window의 핸들 값 |
message | 처리하기 위해 호출 된 메세지(이벤트) |
wParam | 부가적인 메세지 정보 |
lParam | 부가적인 메세지 정보 |
https://learn.microsoft.com/ko-kr/windows/win32/api/winuser/nc-winuser-wndproc
매개변수로 받는 message중 주로 사용되는 메세지는 아래와 같다.
WM_KEYDOWN | 키보드를 눌렀을 때 발생되는 메세지. |
WM_KEYUP | 키보드를 눌렀다 뗄 때 발생되는 메세지. |
WM_LBUTTONDOWN | 마우스 왼쪽 버튼을 눌렀을 때 발생되는 메세지. |
WM_LBUTTONUP | 마우스 왼쪽 버튼을 눌렀다 뗄 때 발생되는 메세지. |
WM_RBUTTONDOWN | 마우스 오른쪽 버튼을 눌렀을 때 발생되는 메세지. |
WM_RBUTTONUP | 마우스 오른쪽 버튼을 눌렀다 뗄 때 발생되는 메세지. |
WM_MOUSEMOVE | 마우스가 움직일 때 발생되는 메세지. |
WM_MOUSEHWHEEL | 마우스 휠을 드래그할 때 발생되는 메세지. |
WM_CREATE | 윈도우가 처음 만들어질 때 발생되는 메세지. |
WM_CHAR | 키보드로부터 문자가 입력될 때 발생되는 메세지. |
그 외 매개변수는 아래 링크에서 확인
DC(Device_Context) 란?
출력에 필요한 모든 정보를 가진 데이터 구조체이다. 주로 그래픽 렌더링, 텍스트 출력, 비트맵 조작 등처럼 화면의 출력을 할 때 사용한다. DC는 할당받는 순간 메모리를 차지하기 때문에, 동적할당과 비슷하게 다 쓰고 난 후에는 메모리를 직접 해제해야 메모리 누수가 일어나지 않는다.
HDC GetDC(HWND hWnd) : 지정한 창(윈도우)에 대한 DC핸들을 반환받는다.
hWnd | DC핸들을 얻어 올 윈도우 핸들을 지정해준다. 0(NULL)을 넣어주면 전체 화면에 대한 핸들이 된다. |
https://learn.microsoft.com/ko-kr/windows/win32/api/winuser/nf-winuser-getdc
int ReleaseDC(HWND hWnd, HDC hDC) : 할당된 DC를 해제해준다. DC가 성공적으로 해제되면 1을 반환해주고, 아닐 경우 0을 반환해준다.
hWnd | DC를 해제할 윈도우 핸들을 지정해준다. 0(NULL)을 넣어주면 전체 화면에 대한 핸들이 된다. |
hDC | 해제할 DC에 대한 핸들을 지정해준다. |
https://learn.microsoft.com/ko-kr/windows/win32/api/winuser/nf-winuser-releasedc
[Windows API] Win32 API의 그래픽, GDI와 스톡 오브젝트(Stock Object) — CHAN-GPT (tistory.com)
개정: WinAPI 프로그래밍 강좌 - GDI.. : 네이버블로그 (naver.com)
GDI_Object(GDI 객체) 란?
펜, 브러쉬, 비트맵, 폰트 등 다양한 출력 객체를 다루는 데 사용하는 함수와 핸들의 모음이다.
아래는 GDI_Object와 관련된 각종 함수와 핸들이다. GDI_Object는 다 쓴 후에는 Default값으로 돌려놓아야 한다.
GDI_Object 핸들 종류
GDI_Object | 핸들 타입 | 기본 값(Defalt) |
펜(Pen) | HPEN | Type : Solid (실선) Width : 1 (두께) Color : BLACK (검은색) |
브러쉬(Brush) | HBRUSH | Color : White |
폰트(FONT) | HFONT | Font : Tahoma |
비트맵(Bitmap) | HBITMAP | - |
팔레트(PALETTE) | HPALETTE | - |
영역(RGN) | HRGN | - |
GDI_Object 종류
(HPEN) CreatePen(int iStyle, int cWidth, COLORREF color) : 펜의 속성을 반환하는 함수다. SelectObject() 함수를 사용할 때 HPEN 자료형으로 캐스팅해 사용할 수 있음.
iStyle (펜 매크로) | 선 스타일을 지정한다. (_PS로 시작하는 펜 매크로를 사용) |
cWidth (펜의 굵기) | 펜의 굵기를 지정한다. 0일 경우 디폴트 값(1)로 지정된다. |
color (RGB) | 펜의 색깔을 지정한다. RGB매크로를 통해 값(각 0~255의 값) 을 전달한다. |
CreatePen 함수(wingdi.h) - Win32 apps | Microsoft Learn
펜 매크로 종류
(* RGB매크로 : R,G,B 값을 입력하면 내부에서 비트시프트(R << 0, G << 8, B << 16)를 통해 B(1btye) G (1btye) R (1btye) 순의 3바이트 값에 저장된다.)
(HBRUSH) CreateSolidBrush(COLORREF color) : 브러쉬의 색깔을 반환하는 함수다. SelectObject() 함수를 사용할 때 HBRUSH 자료형으로 캐스팅해 사용할 수 있음.
color (RGB) | 브러쉬의 색깔을 지정한다. RGB매크로를 통해 값(각 0~255의 값) 을 전달한다. |
CreateSolidBrush 함수(wingdi.h) - Win32 앱 | 마이크로소프트 런(Microsoft T
이 외에 CreateHatchBrush, CreatePatternBrush 등이 있다.
(HGDIOBJ) GetStockObject(int i) : 윈도우가 기본적으로 제공하는 GID_Object이며, 스톡 오브젝트라고 한다. 사용 후 해지하지 않아도 된다는 특성이 있다. (해제해도 상관은 없음.)
i (스톡 매크로) | 스톡 매크로를 통해 GDI_Object를 지정할 수 있다. |
GetStockObject 함수(wingdi.h) - Win32 앱 | 마이크로소프트 런(Microsoft T
스톡 매크로 종류
값 | 의미 |
BLACK_BRUSH | 검은 브러시. |
DKGRAY_BRUSH | 짙은 회색 브러시입니다. |
DC_BRUSH | 단색 브러시입니다. 기본 색상은 흰색입니다. SetDCBrushColor 함수를 사용하여 색을 변경할 수 있습니다. |
GRAY_BRUSH | 회색 브러시. |
HOLLOW_BRUSH | 속이 빈 브러시(NULL_BRUSH에 해당). |
LTGRAY_BRUSH | 밝은 회색 브러시입니다. |
NULL_BRUSH | Null 브러시(HOLLOW_BRUSH에 해당). |
WHITE_BRUSH | 화이트 브러시. |
BLACK_PEN | 검은 펜. |
DC_PEN | 단색 펜 색상입니다. 기본 색상은 검은색입니다. SetDCPenColor 함수를 사용하여 색을 변경할 수 있습니다. |
NULL_PEN | Null 펜. null 펜은 아무 것도 그리지 않습니다. |
WHITE_PEN | 흰색 펜. |
ANSI_FIXED_FONT | Windows 고정 피치(고정 폭) 시스템 글꼴입니다. |
ANSI_VAR_FONT | Windows 가변 피치(비례 공간) 시스템 글꼴입니다. |
DEVICE_DEFAULT_FONT | 장치 종속 글꼴입니다. |
DEFAULT_GUI_FONT | 메뉴 및 대화 상자와 같은 사용자 인터페이스 개체의 기본 글꼴입니다. 대화 상자와 창에서 사용하는 글꼴을 얻기 위해 DEFAULT_GUI_FONT 또는 SYSTEM_FONT를 사용하지 않는 것이 좋습니다. 기본 글꼴은 Tahoma입니다. |
OEM_FIXED_FONT | OEM(주문자 상표 부착 방식) 종속 고정 피치(고정 폭) 글꼴입니다. |
SYSTEM_FONT | 시스템 글꼴. 기본적으로 시스템은 시스템 글꼴을 사용하여 메뉴, 대화 상자 컨트롤 및 텍스트를 그립니다. 대화 상자와 창에서 사용하는 글꼴을 얻기 위해 DEFAULT_GUI_FONT 또는 SYSTEM_FONT를 사용하지 않는 것이 좋습니다. 자세한 내용은 설명 섹션을 참조하세요.기본 시스템 글꼴은 Tahoma입니다. |
SYSTEM_FIXED_FONT | 고정 피치(고정 폭) 시스템 글꼴입니다. 이 스톡 개체는 3.0 이전의 16비트 Windows 버전과의 호환성을 위해서만 제공됩니다. |
DEFAULT_PALETTE | 기본 팔레트입니다. 이 색상표는 시스템 색상표의 정적 색으로 구성됩니다. |
(HGDIOBJ) SelectObject(HDC hdc, HGDIOBJ h) : hdc에 저장된 GDI_Object의 핸들 값을 h로 바꾼다. 이전 GDI핸들 값을 반환하기 때문에 디폴트 값을 저장하기 위해 대체로 호출과 동시에 변수에 이전 GDI핸들 값을 저장한다.
hdc (DC의 핸들) | DC의 핸들 |
h (DC에 전달할 GDI오브젝트 핸들) | DC에 전달할 GDI오브젝트 핸들 |
SelectObject 함수(wingdi.h) - Win32 apps | Microsoft Learn
아래 사진은 DC및 GDI_Object의 사용법이다.
사실 GDI_Object를 다 사용하고 디폴트 값으로 되돌리지 않는다고 에러가 뜨거나 동작이 안되진 않는다. 하지만 다 쓰고 디폴트 값으로 되돌리는게 올바른 사용법이므로 습관화해야한다.