OS

1. WinAPI

CE : 하랑 2024. 1. 22. 10:56

 

WIN API(application programming interface) => window를 사용하기 위한 모든 클래스 방법 함수 변수 뭐시기 등등등을 그냥 다 종합해서 인터페이스라고 부른다.


 

인터페이스 : 함수 클래스 멤버변수 멤버함수 등을 모조리 다 포함. 어떤 동작을 하는 코드를 사용하기 위한 모든 방법을 인터페이스라고 함.
ex) 소리를 재생하기 위한 함수가 있음 =>
"소리를 재생하기 위한 인터페이스를 제공했다, 소리를 재생하려면 xxx 클래스를 사용해야 한다.", "소리를 재생하려면 xxx클래스를 통한 인터페이스를 제공한다."
xxx 클래스에 xxxx 함수가 있다. xxx 클래스에는 xxxx 인터페이스가 존재한다.

 


윈도우는 우리에게 절대로 포인터를 주지 않는다. -> 정수를 준다.

ex) 윈도우가 프로그램을 켤때 너는 XXX번 프로그램이야를 우리에게 배정하는데 그 XXX번 프로그램을 의미하는 자료형 -> HINSTANCE hInstance

 

 

당연히 window창을 만드는 CreateWindow 함수를 호출하면 XXXX번 프로그램을 XXX번 윈도우를 띄운다는 의미로 우리에게 또 핸들을 주는데 -> HWND hwnd라고 한다.

 

윈도우가 우리에게 주는 주소값이나 동적할당포인터라고 생각하고 사용하면 된다.

윈도우 단축키를 사용하기 위한 명령어 -> 현대 게임에서는 잘 사용 안함

 HACCEL hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_WINDOWSPROJECT1));

 

 

중요

중단점을 걸어보면 이상하게 생각해야 할 부분

중단점이 적중되지 않는다 -> 걸리지 않는다.

 

Alt Tap을 하고 다른 창을 보고 있는 상황 -> Alt Tap을 하면 정지하는 게임의 유무

 

일반적인 게임이면 계속 cpu에 몬스터나 환경이나 랜더링에 대한 처리를 계속 요청

그런데 그러면 while문안에서 무조건 중단점이 걸려야 하는데 걸리지 않는다. -> 이유 : GetMessage라는 동기함수를 사용하기 때문

 

GetMessage : 윈도우에 어떠한 변화를 주면 뭔가를 한다.

 

일반적인 게임 -> 윈도우에 변화가 있건 변화가 없건 계속 몬스터는 움직여야 하고 계속 몬스터는 총알을 쏴야하는 행동을 한다.

 

게임인 경우 GetMessage를 사용하면 안된다.

 

GetMessage를 변경하기 전에

먼저 메시지 콜백방식이라는 것을 알아보고 처리

 

// 기본 메시지 루프입니다:
while (GetMessage(&msg, nullptr, 0, 0))
{
    if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }
}

 


 

GetMessage, PeekMessage

(1)GetMessage

- 메시지가 없으면 그자리에서 프로그램을 정지시키고 메시지가 올때까지 대기한다.

- EX) _getch() => 입력버퍼에 입력이 있을때까지 그자리에서 프로그램을 정지시키고 기다린다.

 

(2) PeekMessage => 메시지가 없으면 그냥 리턴

- 기본 메시지 루프로 사용

- PM_NOREMOVE를 사용하면 윈도우 메시지가 계속 쌓여서 처리가 안됩니다. 윈도우가 정지한 것처럼 보일것이다.

- PM_REMOVE를 사용하는데 메시지를 처리할수 있는 것만 처리하고 나머지는 다 버립니다.

// 윈도우 창 유지
unsigned __int64 EngineWindow::WindowMessageLoop()
{
	MSG msg = {};

	while (WindowLive)
	{
		// 기본 메시지 루프입니다:
		// 10개가 들어있을 
		if (PeekMessage(&msg, nullptr, 0, 0, PM_REMOVE))
		{
			TranslateMessage(&msg);
			DispatchMessage(&msg);
		}
	}

	return msg.wParam;
}



 

 


 

콜백 방식

- 기본적으로 함수 포인터를 이용한다.

- 윈도우  -> 함수포인터를 넣어주면 윈도우에 무슨일이 생겼을 때 그걸 내가 대신 실행해줄께 (프로그래머야 나는 네가 이 윈도우로 뭘하고 싶을지 알수가 없어 니가 나한테 알려줘야해)

 

ATOM MyRegisterClass(HINSTANCE hInstance)
{
    WNDCLASSEXW wcex;

    wcex.cbSize = sizeof(WNDCLASSEX);

    wcex.style          = CS_HREDRAW | CS_VREDRAW;
    wcex.lpfnWndProc    = WndProc; // 함수 포인터
    wcex.cbClsExtra     = 0;
    wcex.cbWndExtra     = 0;
    wcex.hInstance      = hInstance;
    wcex.hIcon          = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_WINDOWSPROJECT1));
    wcex.hCursor        = LoadCursor(nullptr, IDC_ARROW);
    wcex.hbrBackground  = (HBRUSH)(COLOR_WINDOW+1);
    wcex.lpszMenuName = nullptr;
    wcex.lpszClassName  = szWindowClass;
    wcex.hIconSm        = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));


    return RegisterClassExW(&wcex);
}

 

 


 

HINSTANCE, HWND, HDC 

(1) HINSTANCE => 프로그램 핸들

- 개념 내 프로그램 4800번이다 

EX)

윈도우님 4800번 윈도우 하나만 만들어주십쇼

윈도우님 4800번 뭐할일 있습니다 키보드 연결 끊어주세요.

 

(2) HWND => 윈도우 핸들

EX)

윈도우 4800번의 프로그램의 530번 윈도우 크기를 바꾸고 싶습니다.

 

(3) HDC => 윈도우에 그릴수 있는 권한

EX)

윈도우 4800번의 프로그램의 530번 230번 그림 권한에서 사각형 그리고 싶습니다.

원 그리고 싶습니다.

 

(4) 기타

HMENU

HCURSOR

HICON

 

Rectangle()

 

 DefWindowProc

일반적인 사용자가 정의할 수 없는 메시지는 나에게 넘기면 윈도우가 기본적으로 처리하는 방식으로  처리해 주겠다.

return DefWindowProc(hWnd, message, wParam, lParam);