컴퓨터/Win32-API
본격적인 실습을 하기 전 기존에 간소화한 실습용 소스코드가 어떤 식으로 동작하는지 이해할 필요가 있습니다. 프로그램이 어떻게 동작하는지 이해를 해야만 어느 부분에 프로그래밍을 할 수 있을지 알게 됩니다.
소스코드를 동작시키면 WinMain함수가 동작하여 메시지 루프에 들어가게 됩니다. 이 과정 이후 WndProc함수에 작성한 내용들이 운영체제의 콜백 함수에 의해 실행되고 처리되게 됩니다.
정말 정말 간단하게 표현하면 위의 그림과 같습니다. WinMain에서 처음 윈도를 생성하고 초기 값을 가진 후 메시지 루프 영역에 도달하게 됩니다.
while (GetMessage(&msg, nullptr, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
이때부터 사용자가 만든 콜백 함수 WndProc를 호출하여 명령에 맞는 처리를 하게 됩니다.
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_PAINT:
{
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hWnd, &ps);
// TODO: 여기에 hdc를 사용하는 그리기 코드를 추가합니다...
EndPaint(hWnd, &ps);
}
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
예를 들어 사용자가 윈도 창에서 마우스 왼쪽 버튼을 클릭했을 때 명령 처리 등 거의 모든 부분이 이 콜백 함수 안에서 진행됩니다.
그래서 WndProc의 부분은 Switch문으로 되어 다양한 명령이 왔을 때 처리하도록 만들어집니다.
결국 WinMain은 프로그램이 시작되는 곳입니다. 그리고 프로그램이 시작된 이후에는 끊임없이 운영체제와 메시지를 주고받는 구조로 되어있습니다. 결국 운영체제에서 어떤 메시지가 들어왔을 때 어떤 처리를 해야 되는 것인가가 Win32 프로그래밍의 핵심이라고 할 수 있습니다.
그렇다면 메세지 루프 영역에서 어떻게 운영체제와 메시지를 주고받는지 이해해 볼 필요가 있습니다.
실습용 예제 소스코드를 보시면 다음과 같습니다.
MSG msg;
// 기본 메시지 루프입니다:
while (GetMessage(&msg, nullptr, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return (int) msg.wParam;
MSG구조체 변수 msg를 선언하고 GetMessage함수를 실행합니다.
BOOL GetMessage(
[out] LPMSG lpMsg,
[in, optional] HWND hWnd,
[in] UINT wMsgFilterMin,
[in] UINT wMsgFilterMax
);
지금은 단순하게 GetMessage 함수를 통해 &msg 즉 msg구조체 변수에 함수를 통해 메시지를 받고 BOOL타입으로 반환한다고 생각하시면 됩니다.
즉 특정 메세지를 받을 때까지 while루프를 돌겠다는 말입니다.
while루프에 진입하면 두 함수를 만나게 됩니다.
BOOL TranslateMessage( CONST MSG *lpMsg);
LONG DispatchMessage( CONST MSG *lpmsg);
지금은 어렵게 생각하지 말고 다음과 같이만 생각해 봅시다.
TranslateMessage - 사용자가 문자를 입력하는 것인지 확인하는 함수입니다. 단순히 아무 키나 입력하여 키보드를 누른다, 땐다 입력이 아닌 어떠한 특정 문자를 입력했는지 확인하는 함수입니다.
DispatchMessage - 이 부분에서 운영 체제로부터 받은 메시지를 WndProc로 전달하는 함수입니다.
결국 다음과 같은 루프로 계속해서 동작할 것입니다.
그럼 이제 WndProc가 실행되면 어떻게 동작하는지 확인해 보겠습니다.
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_PAINT:
{
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hWnd, &ps);
// TODO: 여기에 hdc를 사용하는 그리기 코드를 추가합니다...
EndPaint(hWnd, &ps);
}
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
4개의 매개변수를 받고 있습니다. 지금은 결국 운영체제로부터 message를 받아 message에 담긴 명령어를 처리한다고 생각하면 됩니다.
지금 예제 소스는 2가지 메시지 WM_PAINT, WM_DESTROY만 있지만 다양한 명령이 왔을 때 처리를 하기 위해서는 열심히 명령어에 따른 처리를 해주어야 됩니다.
다음 포스트에서는 실제 간단한 몇가지 명령어를 가지고 처리해보도록 하겠습니다.
Win32_API - 그래픽 개요 (0) | 2022.02.07 |
---|---|
Win32_API - 빈 프로젝트에서 WinMain으로 실행하기(with VisualStudio) (0) | 2022.02.04 |
Win32_API - HINSTANCE / HWND / HDC (0) | 2022.01.29 |
Win32_API - 시작2 (실습 초기 코드 만들기) (0) | 2022.01.28 |
Win32_API - 시작 (초기 소스 해석해보기) (0) | 2022.01.27 |
91년생 공학엔지니어의 개발일지
TODAY :
YESTER DAY :
TOTAL :
Commnet