08.23

신승빈·2022년 8월 23일
0

KGCA 수업

목록 보기
28/128

Win API

사견

linux에서 win api를 대치하는 것은 무엇일까?
QT같은 GUI를 쓴다면 QT의 api를 알아봐야한다고 하는데(https://unix.stackexchange.com/a/25607), 그보다 더 근본적으로 하드웨어 콜을 통한 방법은 없을까?(https://stackoverflow.com/a/14162435/8106257)

프로젝트 구현 규격
class
{
public:
	bool Init();	//초기화
    bool Frame();	//실시간 연산
    bool Render();	//실시간 렌더링
    bool Release();	//해제, 소멸, 삭제
};

구현이 비어있더라도 꼭 선언

프로젝트 생성

빈프로젝트 시

#include <Windows.h>

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);

int APIENTRY wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLine, int nCmdShow)
{
	// WNDCLASSEXW의 lpszClassName과 CreateWindowW의 lpClassName은 동일해야 함
    LPCWSTR name = L"TEST";
    
    WNDCLASSEXW wcex;
    // WNDCLASSEX를 전부 지정하지 않을 경우 초기화 하는것이 좋음
    // 초기화하지 않을 경우 예측할 수 없는 행동 발생
    ZeroMemory(&wcex, sizeof(wcex));
    
    wcex.cbSize = sizeof(WNDCLASSEX);
    wcex.style = CS_HREDRAW | CS_VREDRAW;
    //윈도우 메시지를 받아서 처리하는 콜백 함수
    wcex.lpfnWndProc = WndProc;
    wcex.cbClsExtra = 0;
    wcex.cbWndExtra = 0;
    wcex.hInstance = hInstance;
    //wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
    wcex.hbrBackground = CreateSolidBrush(RGB(0, 0, 0));

    //내가 등록하고자 하는 이름
    // 이 값을 통해 OS는 창 클래스를 식별
    wcex.lpszClassName = name;

	// WNDCLASSEXW를 통해 운영체제에 생성하고자 하는 Window의 설계를 등록
    //1개의 HInstance를 가지고 여러개 등록 가능
    //다만 굳이 여러개를 만들 이유는 없을 듯
    RegisterClassExW(&wcex);

    // HWND
    // 생성된 window의 Handle
    
    // CreateWindowW
    // RegisterClassExW를 통해 운영체제에 등록한 Window를 생성
    // 첫번째 매개변수는 lpszClassName과 동일해아함
    
    // WS_OVERLAPPEDWINDOW -> dwStyle
    // 메뉴, 프레임, 최대화, 최소화 여부 등 설정
    // WS_SYSMENU를 설정하지 않으면 최대화, 최소화, 창닫기 버튼 비활성화 -> 일부 의존적인 속성이 있는 듯
    HWND hWnd = CreateWindowW(name, L"Title", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, nullptr, nullptr, hInstance, nullptr);

    if (!hWnd)
    {
        return FALSE;
    }

	//실제로 window를 그리는 함수
    ShowWindow(hWnd, nCmdShow);
    //무효화 영역을 바로 갱신시켜주는 함수라고는 하는데 주석처리 후 resize를 해도 별 문제 없이 수행되는 듯 함. 아직 차이를 모르겠음
    UpdateWindow(hWnd);

    MSG msg;

    // 메세지 큐에 메세지가 존재한다면 True
    // 읽은 메세지가 WM_QUIT이면 False
    while (GetMessage(&msg, nullptr, 0, 0))
    {
		TranslateMessage(&msg);
        // WndProc에 번역된 메세지 전달
		DispatchMessage(&msg);
    }

    return (int)msg.wParam;
}

// 내가 생성한 msg를 받을수도 있지만, OS가 생성한 msg도 받을 수 있음
// GetMessage()와 WndProc()에 breakPoint를 설정할 경우 GetMessage는 걸리지 않지만 WndProc에는 걸리는 경우를 확인할 수 있음
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    switch (message)
    {
    // WM_DESTROY 처리 필수
    // close box를 누르더라도 실제로 종료되는 것이 아닌 close box를 눌렀음을 알리는 이벤트만 전송
    case WM_DESTROY:
    	// 이 함수를 통해 실질적으로 프로그램이 종료됐음을 알림
        PostQuitMessage(0);
        break;
    default:
    	// 최대화, 최소화, 창이동, 화면크기 변경 등 불필요하다고 판단되는 event를 위임 가능
        return DefWindowProc(hWnd, message, wParam, lParam);
    }
    return 0;
}

변수 명명 규칙

APIENTRY = WINAPI = __stdcall
wWinMain

w = 유니코드, 없다면 멀티바이트
WinMain = WinAPI에서 main역할

LPCWSTR

LP = long pointer
C = const
W = 유니코드
STR = 문자열

HInstance

H = 핸들, 운영체제에서 넘겨주는 ID

WNDCLASSEXW

WND = windows
EX = extention, 확장, WNDCLASSEX도 존재
W = 유니코드

lpfnWndProc

lp = long pointer
fn = function
Wnd = window
Proc = procedure
윈도우 프로시저 함수 포인터

GetMessage()

Message Queue에 msg가 올 때까지 대기

/*
	while (GetMessage(&msg, nullptr, 0, 0))
    {
		TranslateMessage(&msg);
        // WndProc에 WM_DESTROY msg 전송
		DispatchMessage(&msg);
    }
*/
//  이런 구조로 수행
	MSG msg = { 0, };
    while (WM_QUIT != msg.message)
    {
        // 장점 : 메세지큐에 메세지가 없어도 반환됨.
        if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
        {
            TranslateMessage(&msg); // 메세지 번역
            DispatchMessage(&msg);  // 메세지 프로시져에 전달한다.
        }
        else
        {
            Frame();
            Render();
        }
    }

Game에서는 Window Message가 없을 때 작동해야 함(Idle Time, 유휴시간)
대신 PeekMessage함수 사용

기타 함수

GetWindowRect(); // 메뉴, 타이틀, 프레임, close box등 모든 것을 포함한 크기
GetClientRect(); // 부가적인 것을 제외한 화면의 크기

DX작업 시 Client영역의 값을 중요하게 사용

AdjustWindowRect(); // 원하는 client화면에 맞도록 window style을 포함하는 window 화면 계산
GetWindowLong(); // 해당하는 WindowHandle의 Stlye을 알 수 있음
SetWindowLong(); // 해당하는 WindowHandle의 Stlye 설정 가능

Long계열 함수는 GWL_에 따라 원하는 값을 얻을 수 있음(GWL_Style)

GetSystemMetrix(); // system의 전체 해상도 등 조회 가능
MoveWindow(); // 화면 이동, 크기 조절 가능
profile
이상을 길잡이 삼아 로망을 추구합니다.

0개의 댓글