-
유니티 화면 비율 고정 처리...14일지 2021. 10. 15. 02:05
WinAPI의 WM_SIZING 오버 로딩을 통한 화면 비율 고정
구글링을 하다 보니 WinAPI의 WM_SIZING를 오버 로딩하여 화면 비율을 조정하는 코드가 존재했다.
오버 로딩 한 코드만 따로 가져와서 보면 다음과 같다.
winProc 오버 로딩
IntPtr wndProc(IntPtr hWnd, uint msg, IntPtr wParam, IntPtr lParam) { // Check message type. // We are only interested in resize events, so ignore everything else. if (msg == WM_SIZING) { // Get window size struct. RECT rc = (RECT)Marshal.PtrToStructure(lParam, typeof(RECT)); // Calculate window border width and height. RECT windowRect = new RECT(); GetWindowRect(unityHWnd, ref windowRect); RECT clientRect = new RECT(); GetClientRect(unityHWnd, ref clientRect); int borderWidth = windowRect.Right - windowRect.Left - (clientRect.Right - clientRect.Left); int borderHeight = windowRect.Bottom - windowRect.Top - (clientRect.Bottom - clientRect.Top); // Remove borders (including window title bar) before applying aspect ratio. rc.Right -= borderWidth; rc.Bottom -= borderHeight; // Clamp window size. int newWidth = Mathf.Clamp(rc.Right - rc.Left, minWidthPixel, maxWidthPixel); int newHeight = Mathf.Clamp(rc.Bottom - rc.Top, minHeightPixel, maxHeightPixel); // Resize according to aspect ratio and resize direction. switch (wParam.ToInt32()) { case WMSZ_LEFT: rc.Left = rc.Right - newWidth; rc.Bottom = rc.Top + Mathf.RoundToInt(newWidth / aspect); break; case WMSZ_RIGHT: rc.Right = rc.Left + newWidth; rc.Bottom = rc.Top + Mathf.RoundToInt(newWidth / aspect); break; case WMSZ_TOP: rc.Top = rc.Bottom - newHeight; rc.Right = rc.Left + Mathf.RoundToInt(newHeight * aspect); break; case WMSZ_BOTTOM: rc.Bottom = rc.Top + newHeight; rc.Right = rc.Left + Mathf.RoundToInt(newHeight * aspect); break; case WMSZ_RIGHT + WMSZ_BOTTOM: rc.Right = rc.Left + newWidth; rc.Bottom = rc.Top + Mathf.RoundToInt(newWidth / aspect); break; case WMSZ_RIGHT + WMSZ_TOP: rc.Right = rc.Left + newWidth; rc.Top = rc.Bottom - Mathf.RoundToInt(newWidth / aspect); break; case WMSZ_LEFT + WMSZ_BOTTOM: rc.Left = rc.Right - newWidth; rc.Bottom = rc.Top + Mathf.RoundToInt(newWidth / aspect); break; case WMSZ_LEFT + WMSZ_TOP: rc.Left = rc.Right - newWidth; rc.Top = rc.Bottom - Mathf.RoundToInt(newWidth / aspect); break; } // Save actual Unity game area resolution. // This does not include borders. setWidth = rc.Right - rc.Left; setHeight = rc.Bottom - rc.Top; // Add back borders. rc.Right += borderWidth; rc.Bottom += borderHeight; // Trigger resolution change event. resolutionChangedEvent.Invoke(setWidth, setHeight, Screen.fullScreen); // Write back changed window parameters. Marshal.StructureToPtr(rc, lParam, true); } // Call original WindowProc function. return CallWindowProc(oldWndProcPtr, hWnd, msg, wParam, lParam); }단순히 코드를 보면 메뉴바의 크기를 잘라내기 위해 AdjustWindowRect를 사용하는 대신 windowRect와 clientRect를 각각 가져와 크기의 차이를 구한 뒤 화면 크기를 조절하고 메뉴바의 크기만큼을 더해서 위치나 크기가 틀어지지 않도록 처리한 것 같다.
그런데 단순하게 코드는 이해가 되지만 어떤 식으로 오버 로딩을 한 것인지 이해가 되지 않아 한동안 이 부분을 분석해야 할 것 같다.