본문 바로가기
Win32 API/기초

Win32 API 기초 : Win32 API 기본 (2)

글: 시플마 2024. 6. 16.

main 함수에서

 

42번째 줄에 있는 코드는 단축키 정보를 의미합니다. 

 

리소스 뷰에서

 

Accelerator에서 IDC_CLIENT를 더블클릭하면 

아래와 같은 창이 뜹니다.

 

42번째 코드는 이러한 단축키를 로딩하여 대입하는 동작인 것이죠.

 

그리고 49번째 줄에 있는 if 문을 통해

단축키가 입력되었는지 검사하게 됩니다.

 

그래서 실제로 프로그램을 실행하고

 

단축키 Alt + ?를 입력하면 새로운 창이 뜹니다.

 

리소스 뷰에서 

 

Menu에서 IDC_CLIENT를 더블클릭하면

 

위와 같이 파일이 하나 열리는데 여기서 

도움말 - 정보를 클릭해 보면 

 

속성 창에서 메뉴 편집기가 나타납니다.

 

이때 ID를 보니 IDM_ABOUT으로 되어 있네요.

 

Accelerator에서 IDC_CLIENT를 클릭했을 때

확인할 수 있었던 ID와 같습니다. 

 

즉 단축키를 입력하였을 때, 해당 ID를 가진 창을

열게 되는 것이죠.

 

 


 

 

 

OS에서는 수많은 이벤트들을 관리합니다.

 

우클릭, 좌클릭, 드래그, 키 입력 등 말이죠.

 

이런 이벤트가 발생할 때마다 메시지 큐라는 곳에 

저장을 합니다. 

 

그래서 프로세스는 이러한 메시지 큐에 있는

메시지를 받아 그 메시지에 맞는 동작을 수행하죠.

 

'큐(Queue)'이기 때문에 먼저 발생한 메시지를 먼저

실행하고 이후 발생한 메시지를 순차적으로 실행합니다.

 

중요한 점은 OS는 수많은 프로세스를 관리하고 있습니다.

 

그래서 이벤트가 발생할 때 현재 포커싱 중인

프로세스를 기준으로 메시지를 실행합니다.

 

예를 들어 비주얼 스튜디오가 켜진 상태에서

그림판을 켠 후 드래그를 하면 그림이 그려지지만,

그림판을 내려 뒤에 있던 비주얼 스튜디오에 

드래그를 아무리 해도 그림판에 그림이 그려지지 않는 것처럼 말이죠.

 

 

다시 main 함수를 보시면

 

44번째 MSG형 객체 msg가 선언된 것이 보입니다.

 

이게 바로 메시지 객체입니다.

 

47번째 줄에서  GetMessage를 통해 메시지를 받아 처리를 할 때

msg의 주솟값을 받죠? 이유가 메시지를 받은 후에 

msg가 갖고 있는 멤버에, 받은 메세지의 정보를 대입하기 위해서입니다.

 

 

49번째 줄에서 객체 msg의 멤버 hwnd가 보이는데

hwnd가 바로 핸들입니다. 

 

하나의 프로세스는 여러 개의 창을 보유할 수 있습니다. 

 

기본으로 제공된 프로그램도 실행하면 Client 창과

정보 창을 띄울 수 있는 것처럼 말이죠.

(물론 창을 보유하지 않을 수도 있습니다.)

 

hwnd를 통해 구체적으로 어떤 윈도우에

이벤트가 발생했는지, 그런 정보까지 msg에 저장하는 것이죠.

 

 


 

 

 

윈도우가 만들어질 때, 해당 윈도우에서 발생할 수 있는 메시지를

처리해 주는 함수의 주솟값까지 받아서 윈도우를 만듭니다.

 

창 클래스를 등록해 주는 MyRegisterClass 함수를 보시면

 

72번째 줄에서 wcex의 멤버 IpfnWndProc에 WndProc를

대입하는 게 보이시나요?

 

WndProc는 main 함수가 있는 파일에서 볼 수 있듯이

 

전방 선언된 '함수'이죠.

 

이를 통해 윈도우를 만들기 위해 윈도우 정보를 등록하는 과정에서

해당 윈도우가 특정 이벤트에 반응하기 위한 함수의 주솟값까지 

받아 놓는 것임을 알 수 있습니다.

 

 

다시 main 함수로 돌아와서 보시면

 

49번째 줄의 if 문을 통해 단축키 관련 메시지인지 확인한 후,

51 ~ 52번째 줄의 코드를 통해 어떤 윈도우인지 파악하고

해당 윈도우의 처리기에서 처리를 하도록 호출을 진행합니다.

 

그래서 결과적으로 메시지가 발생한 윈도우의

WndProc 함수(Procedure 함수)가 호출됩니다.

 

이후 WndProc 함수를 통해

 

switch 문에서 어떤 메시지였냐에 따라

분기점이 설정되어 메시지에 따른 동작을 하게 되는 겁니다.

 

WndProc 함수에서 윈도우가 가질 수 있는 모든 메시지를 

처리할 수 없으므로 몇 가지 특정사항을 제외한

나머지 메시지는 157번째 줄에서 볼 수 있듯이

DefWindowProc(디폴트 윈도우 프로시저)로 처리합니다.

 

여기에 필요하다면 case를 더 추가하거나 수정하여 

메시지를 커스텀하는 것이죠.

 

 


 

 

다시 main 함수를 봅시다.

 

47번째 줄에서 while 문의 조건이 GetMessage입니다.

 

GetMessage는 true 또는 false를 반환하고 true면

while 문을 진행, false면 while 문이 종료되겠죠?

 

아래 return 구문이 있기 때문에 while 문이 종료된다는 것은

곧 프로세스가 종료됨을 의미합니다.

 

아무런 메시지를 받지 않은 상태에서는 GetMessage는

아무것도 반환하지 않으므로 while 문이 계속 반복될 겁니다.

 

정상 작동할 수 있는 메시지를 받으면 while 문 안 코드가 실행된 후

다시 while 문을 계속 반복하는 상태가 되겠죠.

 

그럼 언제 GetMessage가 false를 반환하며 while 문을

빠져나오고 프로세스가 종료될까요?

 

바로 객체 msg의 멤버 message가 WM_QUIT과 같을 때입니다.

 

WM_QUIT이 나왔다는 것은 프로세스가 소유하고 있는

윈도우가 모두 종료되어 프로세스가 종료될 수 있다는 의미입니다.

 

이 상태가 되면 GetMessage가 false를 반환하여 while 문을

빠져나오고 프로세스가 종료되는 것입니다.

 

 


 

 

그럼 이번에는 WndProc 함수를 작동시켜 봅시다.

 

윈도우에 사각형을 그릴 건데 

이를 위해 Rectangle 함수를 사용하겠습니다.

 

무엇인지는 모르겠지만 첫 번째 인자로 hdc를 넣으라고 하네요.

 

그리고 정수 네 개를 인자로 받는데

각각 왼쪽, 상단, 오른쪽, 하단의 좌푯값입니다.

 

아래 코드처럼

 

왼쪽 상단의 좌표와

오른쪽 하단의 좌푯값을 설정하고 실행하겠습니다.

 

실행하여 확인해 보니

 

정말 사각형이 윈도우에 그려진 모습을 확인할 수 있습니다. 

 

 

Rectangle 함수에 인자로 주었던 좌푯값은 

픽셀(Pixel)을 기준으로 합니다. 

 

위 사진에서 보이는 점 하나하가 바로 픽셀 한 개입니다.

첫 번째 빨간 점의 좌표는 ( 0, 0 )입니다.

 

사각형은 0부터 하여 X 축으로 10까지 이동한 위치와

0부터 하여 Y 축으로 10까지 이동한 위치에 점을 찍고

 

0부터 하여 X 축으로 110까지 이동한 위치와

0부터 하여 Y 축으로 110까지 이동한 위치에 점을 찍어

만들어진 것입니다.

 

해당 사각형은 가로 100, 세로 100개의 픽셀로 이루어진

정사각형이라고 볼 수 있습니다.

 

 

모니터의 해상도를 얘기할 때 

FHD 모니터의 경우 1920 x 1080이라고 얘기합니다.

 

이는 가로 1920개의 픽셀과

세로 1080개의 픽셀로 화면을 표현하는 것이죠.

 

 

 


강의 출처 : https://www.youtube.com/watch?v=Q47cpjahcYg