WIN32API FrameWork/한단계씩 직접 구현

01. 프레임워크에 사용될 WINAPI32 기본 생성 코드 알아보기

2022. 5. 15. 16:23

[WIN32API]

  • 어렵게 생각할 필요 없이, Windows에서 제공하는 함수의 집합이다.
    • 예를 들어 우리가 게임을 돌리고 있을 때 절전모드에 진입하는걸 막는다던지 하는 것들을 조정하도록 해 주는 것이다.
  • Window: 메시지 기반의 운영체제이다.
    • 우리가 마우스 조작, 키보드 조작 등을 하는 모든 행위를 '이벤트'라고 한다.
    • 이러한 이벤트가 발생 되면 윈도우즈라는 운영체제는 모든 행위의 이벤트들을 '메시지'로 바꾼다.
    • 마우스를 움직이거나 클릭, 키보드를 입력 등 모든 행위가 이벤트가 되고
    • 해당 이벤트를 메시지로 변경하여 들어오는 메시지에 따라 원하는 동작을 만들어주는 개념이다.
      • 모든 프로그램에는 메시지를 저장하는 메시지 큐가 존재하고 선입선출로 처리한다.
      • 모든 프로그램은 while문을 통해 메시지 큐를 받아 처리하는 형태이다.
      • 일반적인 프로그램에서는, 메시지가 들어오지 않으면 메시지가 들어올 때까지 무한루프를 돌면서 대기를 하고 있다가, 메시지가 들어오면 해당 메시지를 통해 이벤트를 생성하는 작업을 시작한다.
        • 이를 '데드타임' 이라고 한다.
      • 하지만, 게임에서는 이런 방식을 사용하기 힘들다.
        • 메시지가 들어오지 않아도 계속 게임은 돌아가기 때문
        • 게임에서는 메시지 큐에서 대기하면서 새 메시지가 들어오기를 기다리지 않는다.
        • 모인 메시지를 1번 받고, 받은 메시지를 통해 프레임을 그리고, 다시 메시지를 받는다. 이 작업을 계속 반복한다.
        • 후술할 GetMessage 함수와 관련됨.
      • 1바이트 문자열을 사용 = 멀티바이트
      • 2바이트 문자열을 사용 = 유니코드(윈도우즈 기본)
        • 프로젝트 우클릭 - 속성 - 고급 - 문자 집합에서 확인 가능.
        • 우리는 앞으로 유니코드 문자 집합을 사용한다.

새 프로젝트에서 Windows 데스크톱 마법사로 설정하고

 

이런 창이 뜬다. 여기서 데스크톱 마법사를 선택하고 만들어 준다.

  • 프로젝트를 만들 때 'Windows 데스크톱 마법사'로 만들면 된다.
    • 데스크톱 애플리케이션(.exe) 선택
      • cf) 동적 연결 라이브러리(.dll), 정적 연결 라이브러리(.lib)
        • 일종의 라이브러리라는 것을 만들어서,
          우리가 만든 소스코드를 다른 프로젝트에서도 갖다 쓸 수 있게 한 것.
      • 작성된 코드는, 사전 설정에서 '빈 프로젝트' 체크박스를 해제하여 나오는 빈 Windows라는 창을 띄워주는 기본 코드에 주석을 단 것이다.
      • 우리는 이 기본 코드들을 기반으로 2D게임의 프레임워크를 짜 나갈 예정이다.

 

일단 한 번 만들어보자.

그러면 이런 식의 기본 코드가 생성된다.

만들어진 코드를 바로 F5를 눌러 디버그모드로 실행시키면,

이런 빈 창이 만들어지는 코드이다.

  • 이번 글에서는 이 코드들 중에 게임프레임워크 안에서 사용할 코드들을 살펴보고, 해당 코드들만 가져와서 게임프레임워크의 기반으로 삼을 것이다.

 

 

 


HINSTANCE hInst;
  • 인스턴스 핸들
    • 윈32 API를 보면 변수명 앞에 H가 붙어있는 경우를 많이 볼텐데,
    • 이것은 '핸들'이다. -> 운영체제에서 만들어서 제공해준다.
    • 우리는 이 핸들을 이용하여 운영체제의 기능들을 사용할 수 있게 요청을 할 수 있다.
    • 윈도우에는 굉장히 많은 프로그램이 돌아가고 있다. 그 프로그램 간 구분을 위해서 핸들을 만드는 것이다.
    • 같은 프로그램을 여러개의 창을 띄워도 HINSTANCE는 하나만 할당된다.
    • 프로그램 식별 번호 라고 생각하면 될 듯.

int APIENTRY wWinMain(_In_ HINSTANCE hInstance,
                     _In_opt_ HINSTANCE hPrevInstance,
                     _In_ LPWSTR    lpCmdLine,
                     _In_ int       nCmdShow)
  • 여태까지의 콘솔 프로그램의 main() 함수에 대응되는 함수이다.
    • 방금 살펴본 HINSTANCE를 첫 번째 인자로 받고 있는 것을 볼 수 있다.
    • 나머지 인자는 프레임워크에서 사용하지 않는다.

ATOM MyRegisterClass(HINSTANCE hInstance)
{
  •  우리가 프로그램을 실행하면 윈도우즈는 기본적으로 레지스트리를 들고 있다.
  • 이 함수는 레지스트리에 등록할 윈도우 구조체를 만들고, 해당 구조체를 반환해 준다

 

WNDCLASSEXW wcex;
  • 구조체를 선언한다

 

wcex.cbSize = sizeof(WNDCLASSEX);
  • 사이즈를 저장하는 변수. 사용처는 불명

 

wcex.style          = CS_HREDRAW | CS_VREDRAW;
  • 아래에 윈도우가 어떤 형태의 윈도우를 생성할지를 설정할 수 있다.
  • CS_HREDRAW: Horizontal Redraw | CS_VREDRAW Vertical Redraw
  • 가로세로 영역 크기가 바뀌었을 때 클라이언트 영역을 전부 다시 그려주는 기능

 

wcex.lpfnWndProc    = WndProc;
  • WndProc(Window Procedure) 전역함수 -> 함수 포인터
  • 이벤트 -> 메시지 -> 메시지 큐 -> 메시지를 인자로 집어넣어서 처리해줄 함수를 지정
  • 메시지 큐에서 꺼내온 메시지를 인자로 전달하며 호출할 함수의 함수 주소를 등록한다.
  • 이런 식으로 함수 포인터를 등록해놓고 호출하는 방식을 '콜백'이라고 한다.

 

wcex.cbClsExtra     = 0;
wcex.cbWndExtra     = 0;
  • 안 쓰임

 

wcex.hInstance      = hInstance;
  • 맨 위에서 언급했던 HINSTANCE를 등록한다.

 

wcex.hIcon          = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_MY220428WIN32API));
  • 기본 아이콘 설정

 

wcex.hCursor        = LoadCursor(nullptr, IDC_ARROW);
  • 커서 변경. 
    • ex)IDC_WAIT: 대기

 

wcex.hbrBackground  = (HBRUSH)(COLOR_WINDOW+1);
  • 배경화면 색상

 

wcex.lpszMenuName   = MAKEINTRESOURCEW(IDC_MY220428WIN32API);
  • 창 이름 표시줄 하단에 뜨는 드롭다운 메뉴 설정.
  • nullptr을 등록해주면 드롭다운 메뉴가 뜨지 않는다.
  • 게임에서는 일반적으로 드롭다운 메뉴를 사용하지 않으므로 nullptr을 쓸 것임.

 

//wcex.lpszClassName  = szWindowClass;
wcex.lpszClassName = TEXT("Tutorial");
  • 기본 설정은 프로젝트 '리소스 파일' 안의 StringTable에 들어있는 데이터를 불러와서 이름을 지정해주지만,
    굳이 그렇게 할 필요 없이 여바로 지정해주어도 된다.
  • 등록할 클래스의 이름을 유니코드 문자열로 만들어서 지정한다.
        유니코드 형태의 문자열로 설정하려면 L"(문자열)" 형식으로 하면 된다.
  • 하지만 TEXT("문자열")로 하는 것이 더 좋다.
        TEXT 매크로는 프로젝트 설정이 유니코드로 되어있을 경우 유니코드 문자열로 만들어지고
        멀티바이트로 되어있을 경우 멀티바이트 문자열로 만들어지게 된다.

 

wcex.hIconSm        = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));
  • 윈도우 창 좌측 상단에 뜨는 작은 아이콘을 지정한다.

 

return RegisterClassExW(&wcex);
  • 구조체 생성이 완료되면 이 구조체를 등록해주는 함수를 호출하며 리턴한다.

 


    // 애플리케이션 초기화를 수행합니다:
    if (!InitInstance (hInstance, nCmdShow))
    {
        return FALSE;
    }
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
  • 이 함수에서 창을 생성할 준비(초기화)하고 띄운다. 실패하면 winmain 함수에 FALSE가 반환되며 프로그램이 종료된다.

 

hInst = hInstance;
  • 전역변수로 선언된 HINSTANCE hInst 변수에 창의 HINSTANCE 번호를 저장한다.

 

   HWND hWnd = CreateWindowW(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
      CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, nullptr, nullptr, hInstance, nullptr);
  • HWND = Handle WiNdoW 윈도우 핸들
  • 1번 인자는 윈도우 클래스에 등록할 이름이다.
       * 
  • 2번 인자는 타이틀바에 표시할 이름이다.
    1. 1, 2번 인자의 기본값인 szWIndowClass와 szTitle 대신 그냥 문자열을 넣어 생성해줄수도 있다.
  • 3번 인자는 이 윈도우 창이 어떻게 생성될지를 결정하는 선택 인자이다.
    1. 현재 인자를 WS_OVERLAPPEDWINDOW의 정의로 타고 들어가보면 여러가지 옵션이 조합되어 있는 것을 알 수 있다. 
  • 4, 5번 인자는 윈도우 창이 생설될 화면에서의 위치를 지정한다.
       픽셀로 지정한다. 
    • 예를 들어 1920, 1080 해상도라면 거기에서 원하는 값을 넣어주면해당 위치에 나오게 된다.
    • 4번은 가로좌표, 5번은 세로좌표.
  • 6번, 7번 인자는 윈도우창의 가로, 세로의 크기를 지정한다.
    • 픽셀단위로 지정을 해준다.
  • 8번 인자는 부모 윈도우가 있다면 부모 윈도우의 핸들을 지정한다.
    • 없으면 nullptr을 지정한다.
  • 9번 인자는 메뉴가 있다면 메뉴 핸들을 넣어주고 없으면 nullptr을 지정한다.
  • 10번 인자는 윈도우 인스턴스를 지정하여 이 윈도우 인스턴스에 속한 
       윈도우 창이 만들어지게 된다.
  • 11번 인자는 필요 없음.
    • 이런 식으로 윈도우 창을 만들어주고 정상적으로 만들어졌다면 
         생성된 윈도우 창의 핸들이 반환되어 HWND hWnd 변수에 등록된다.

 

   if (!hWnd)
   {
      return FALSE;
   }
  • 위에서 hWnd 변수가 정상적으로 등록되지 않으면 false를 반환하고 프로그램을 종료한다.

 

ShowWindow(hWnd, SW_SHOW);
  • 윈도우 창을 띄운다.
  • 1번인자: 방금 생성한 hWnd 변수
  • 2번인자
    • SW_SHOW(창을 보여준다), SW_HIDE(창울 숨긴다 - 백그라운드)를 넣어줄 수도 있다.
    • cf)SW_HIDE 외에도 윈도우 서비스를 통해 창을 표시하지 않을 수도 있다.

 

UpdateWindow(hWnd);
  • 이 함수를 호출하여 클라이언트 영역이 제대로 갱신되었다면 0이 아닌 값을 반환한다.
  • 갱신이 실패했을 경우 0을 반환한다.

 

	return TRUE;
}
  • 위의 모든 과정이 정상적으로 진행되었다면 TRUE를 반환한다.

 


MSG msg;
  • 운영체제가 만들어 준 메시지를 얻어오기 위한 구조체를 선언한다.

 

while (GetMessage(&msg, nullptr, 0, 0))
    {
  • Call by Adress 방식의 함수.
  • GetMessage: 메시지 큐에서 메시지를 꺼내오는 함수이다.
    • 단, 메시지 큐가 비어있을 경우 메시지가 들어올 때까지 빠져나올 수 없다.
    • 이렇게 멈춰서 대기하고 있는 것을 블로킹 모드라고 하며
    • 큐가 비어서 멈춰있는 시간을 윈도우 데드타임이라고 한다.
    • 게임의 경우에는 잘 쓰이지 않는다.    
  • 그렇기에 게임의 경우에는 PeekMessage라는 함수를 사용한다.
    • 메시지 큐에서 메시지를 꺼낸 뒤 데드타임동안 프레임을 그리는 것이다.

 

    TranslateMessage(&msg);
    DispatchMessage(&msg);
}
  • TranslateMessage - DispatchMessage: 일종의 한 세트
  • 메시지큐에서 꺼내온 메시지를 TranslateMessage 함수로 넘겨주면 문자 키인지 F1, 방향키 같은 키인지를 판단해준다.
  • 이러한 키들은 WM_KEYDOWN으로 메시지가 인식이 되고,
    문자 키는 WM_CHAR로 인식이 된다.
  • 키를 누르면 문자키의 경우 WM_CHAR도 만들어져야 하기 떄문에,
    여기에서 WM_KEYDOWN이 일어나면 문자키의 경우 WM_CHAR메시지를 추가로 만들어서 메시지 큐에 넣어준다.
  • 이 함수가 없을 경우 문자 키를 눌렀을 때 WM_CHAR가 발생하지 않으므로반드시 써 줘야 한다.

 

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
	switch (message)
    {
    case WM_DESTROY:
        // 윈도우가 종료될때 들어오는 메세지이다.
        m_Loop = false;
        PostQuitMessage(0);
        break;
    default:
        return DefWindowProc(hWnd, message, wParam, lParam);
    }
    return 0;
}
  • 메시지의 처리 방법을 넣을 함수이다.
  • 일단 당장은 모든 코드가 필요하지 않다. 위의 코드들만 남겨놓자.

 

 

이로써 대략적인 기본 코드 분석은 끝났고,

다음 글부터 이 코드들을 가져와 프레임워크를 짜 볼 것이다.

'WIN32API FrameWork > 한단계씩 직접 구현' 카테고리의 다른 글

05. PeekMessage 함수와 Run() 루프  (0) 2022.05.15
04. crtdbg 헤더를 통한 메모리 누수 잡기  (0) 2022.05.15
03. 창이 생성될때의 사이즈 설정하기  (0) 2022.05.15
*** 공부 방법 ***  (0) 2022.05.15
02. 프레임워크 기본 설정 및 간단한 구현  (0) 2022.05.15
'WIN32API FrameWork/한단계씩 직접 구현' 카테고리의 다른 글
  • 04. crtdbg 헤더를 통한 메모리 누수 잡기
  • 03. 창이 생성될때의 사이즈 설정하기
  • *** 공부 방법 ***
  • 02. 프레임워크 기본 설정 및 간단한 구현
hyrule
hyrule
hyrule
C++ 프로그래밍 공부
hyrule
전체
오늘
어제
  • 분류 전체보기 (205)
    • C++기초 (50)
    • WIN32API FrameWork (109)
      • 한단계씩 직접 구현 (82)
      • 원본 (15)
      • 코드별 설명 개별저장(검색용) (12)
    • 자습 (21)
    • C++ TIPS (11)
    • 연습 노트 (3)
    • ETC (6)
    • DX2D StarCraft 모작 (1)

블로그 메뉴

  • 홈
  • 방명록

공지사항

인기 글

태그

  • Windows 11
  • hello
  • C++
  • notion
  • 스타크래프트
  • Tistory

최근 댓글

최근 글

hELLO · Designed By 정상우.
hyrule
01. 프레임워크에 사용될 WINAPI32 기본 생성 코드 알아보기
상단으로

티스토리툴바

개인정보

  • 티스토리 홈
  • 포럼
  • 로그인

단축키

내 블로그

내 블로그 - 관리자 홈 전환
Q
Q
새 글 쓰기
W
W

블로그 게시글

글 수정 (권한 있는 경우)
E
E
댓글 영역으로 이동
C
C

모든 영역

이 페이지의 URL 복사
S
S
맨 위로 이동
T
T
티스토리 홈 이동
H
H
단축키 안내
Shift + /
⇧ + /

* 단축키는 한글/영문 대소문자로 이용 가능하며, 티스토리 기본 도메인에서만 동작합니다.