그래픽 작업을 할 때는 그리는 영역의 정확한 크기를 아는 것이 중요합니다. 지난 수업에서 우리는 창을 만들고 크기를 500 x 400으로 설정했습니다. 그러나 Direct3D가 그리는 영역은 해당 창의 경우 500 x 400이 아닙니다 .
- 그리기 영역의 실제 크기를 알아보고, 이를 보다 정확하게 설정하는 기능을 알아보자
CreateWindowEx()를 호출했을 때, 우리는 500과 400을 사용하여 윈도우의 크기를 설정했습니다. 그러나 이것은 클라이언트 의 크기와 다릅니다 . 클라이언트 영역은 테두리를 포함하지 않는 윈도우의 부분입니다.

여기에서 볼 수 있듯이, 창 크기는 테두리의 가장자리에서 확장되는 반면, 클라이언트 크기는 테두리의 내부로 확장됩니다. 렌더링할 때, 우리는 창의 클라이언트 영역에만 그림을 그릴 것입니다. 따라서 정확한 크기를 아는 것이 중요합니다.
이것이 정확히 왜 중요한가요? Direct3D를 사용하여 그릴 때 생성할 이미지의 크기를 지정하라는 메시지가 표시됩니다. 창의 클라이언트 영역이 이 이미지와 크기가 다르면 클라이언트 영역에 맞게 늘어나거나 줄어듭니다.

보시다시피 오른쪽 스크린샷에는 몇 가지 명백한 왜곡이 있습니다. 이는 클라이언트 영역에 맞게 이미지를 축소했을 때 생성되었습니다.
AdjustWindowRect() 함수
창 크기를 설정한 다음 클라이언트 크기를 결정하는 것보다 클라이언트 크기를 미리 결정한 다음 적절한 창 크기를 계산하는 것이 이상적입니다. 이를 위해 창을 만들기 전에 AdjustWindowRect() 함수를 사용합니다.
이것은 정말 간단한 기능입니다. 이 기능이 하는 일은 클라이언트 영역의 원하는 크기와 위치를 취하고, 그 클라이언트 크기를 만드는 데 필요한 창 위치와 크기를 계산하는 것입니다.
해당 함수의 프로토타입은 다음과 같습니다.
BOOL AdjustWindowRect(LPRECT lpRect,
DWORD dwStyle,
BOOL bMenu);
첫 번째 매개변수는 RECT 구조체에 대한 포인터입니다. 가리키는 RECT에는 원하는 클라이언트 영역의 좌표가 들어 있습니다. 함수가 호출되면 RECT가 수정되어 대신 창 영역의 좌표가 들어 있습니다.
두 번째 매개변수는 창 스타일입니다. 이 함수는 이 정보를 사용하여 창 테두리의 크기를 결정합니다.
세 번째 매개변수는 BOOL 값으로, 함수를 통해 메뉴를 사용하는지 여부를 알려줍니다. 메뉴는 기술적으로 클라이언트 영역의 일부가 아니므로 고려해야 합니다.
이 함수는 실제 코드에서 어떻게 보일까요? 살펴보겠습니다. 다음은 CreateWindowEx()에 대한 호출을 수정한 것입니다.
RECT wr = {0, 0, 500, 400}; // 크기는 설정하지만, 위치는 설정하지 않음
AdjustWindowRect(&wr, WS_OVERLAPPEDWINDOW, FALSE); // 크기 조정
// 창을 생성하고 그 결과를 핸들로 사용
hWnd = CreateWindowEx(NULL,
L"WindowClass1",
L"Our First Windowed Program",
WS_OVERLAPPEDWINDOW,
300, // 창의 x 위치
300, // 창의 y 위치
wr.right - wr.left, // 창 너비
wr.bottom - wr.top, // 창 높이
NULL,
NULL,
hInstance,
NULL);
RECT wr = {0, 0, 500, 400};
간단한 문장입니다. 우리는 rect(저는 이것을 'wr'로 명명했습니다. 창 rect)를 만들고, 원하는 클라이언트 영역의 크기로 초기화합니다. 우리는 'left'와 'top' 값에 위치를 넣지 않습니다. 왜냐하면 우리가 하는 일에 그것들이 필요하지 않기 때문입니다.
AdjustWindowRect(&wr, WS_OVERLAPPEDWINDOW, FALSE);
RECT가 초기화된 후 AdjustWindowRect() 함수를 호출합니다. RECT 주소, 창 스타일, FALSE로 채워서 메뉴가 없음을 나타냅니다.
wr.right - wr.left,
wr.bottom - wr.top,
AdjustWindowRect()가 호출되면 창 너비는 오른쪽과 왼쪽의 차이가 되고, 높이는 아래쪽과 위쪽의 차이가 됩니다.
창의 너비와 높이에 대한 두 가지 표현식을 사용하면 창의 정확한 크기를 알 수 있습니다.
현재까지의 전체 코드이다!!
// 기본 Windows 헤더 파일 포함
#include <windows.h>
#include <windowsx.h>
// WindowProc 함수 프로토타입
LRESULT 콜백 WindowProc(HWND hWnd,
UINT message,
WPARAM wParam,
LPARAM lParam);
// 모든 Windows 프로그램의 진입점
int WINAPI WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
// 함수로 채워진 창의 핸들
HWND hWnd;
// 이 구조체는 창 클래스에 대한 정보를 보관합니다
WNDCLASSEX wc;
// 사용을 위해 창 클래스를 지웁니다
ZeroMemory(&wc, sizeof(WNDCLASSEX));
// 필요한 정보로 구조체를 채웁니다
wc.cbSize = sizeof(WNDCLASSEX);
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = WindowProc;
wc.hInstance = hInstance;
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH)COLOR_WINDOW;
wc.lpszClassName = L"WindowClass1";
// 윈도우 클래스 등록
RegisterClassEx(&wc);
// 클라이언트 영역 RECT의 크기를 계산
wr = {0, 0, 500, 400}; // 크기는 설정하지만 위치는 설정하지 않음
AdjustWindowRect(&wr, WS_OVERLAPPEDWINDOW, FALSE); // 크기 조정
// 창 생성 및 결과 핸들로 사용
hWnd = CreateWindowEx(NULL,
L"WindowClass1", // 창 클래스 이름
L"Our First Windowed Program", // 창 제목
WS_OVERLAPPEDWINDOW, // 창 스타일
300, // 창의 x 위치
300, // 창의 y 위치
wr.right - wr.left, // 창 너비
wr.bottom - wr.top, // 창 높이
NULL, // 부모 창이 없음, NULL
NULL, // 메뉴를 사용하지 않음, NULL
hInstance, // 애플리케이션 핸들
NULL); // 여러 창과 함께 사용, NULL
// 화면에 창 표시
ShowWindow(hWnd, nCmdShow);
// 메인 루프로 이동:
// 이 구조체는 Windows 이벤트 메시지를 보관합니다
MSG msg;
// 큐의 다음 메시지를 기다리고 결과를 'msg'에 저장합니다.
while(GetMessage(&msg, NULL, 0, 0))
{
// 키 입력 메시지를 올바른 형식으로 변환합니다
.TranslateMessage(&msg);
// 메시지를 WindowProc 함수로 보냅니다
.DispatchMessage(&msg);
}
// WM_QUIT 메시지의 이 부분을 Windows로 반환합니다
.return msg.wParam;
}
// 이것은 프로그램의 주요 메시지 핸들러입니다
.LRESULT 콜백 WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
// 정렬하여 주어진 메시지에 대해 실행할 코드를 찾습니다
.switch(message)
{
// 이 메시지는 창이 닫힐 때 읽힙니다.case
WM_DESTROY:
{
// 응용 프로그램을 완전히 닫습니다
.PostQuitMessage(0);
return 0;
} break;
}
// switch 문에서
반환하지 않은 모든 메시지를 처리합니다.DefWindowProc (hWnd, message, wParam, lParam);
}
어렵긴하다...;; 그래도 하나하나씩 알아가는 재미가 있는 듯 하다..ㅋㅋ
'DirectX11' 카테고리의 다른 글
DirectX11 - Tutorial 5 (실시간 메시지 루프) (0) | 2024.08.03 |
---|---|
DirectX11 - Tutorial 3 (창 만들기) (0) | 2024.08.03 |
DirectX11 - Tutorial 2 (Hello World) (0) | 2024.08.03 |
DirectX11 - Tutorial 1 (동작 순서) (0) | 2024.08.03 |