ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 유니티 화면 비율 고정 처리...19
    일지 2021. 11. 17. 23:48

    화면 조정 시 위치 바뀌는 버그 수정 시도

    이전에 발생한 버그를 수정하기 위해 코드를 이것저것 수정해보고 있었는데, 일단 의심되는 건 WinProc을 교체하려고 했으나 교체되지 않고 기존 것에 추가로 적용이 되는 게 아닐까 하는 생각이 든다.

     

    그래서 변경 전 크기, 위치와 변경 후 크기, 위치가 각각 전달되면서 문제가 되는 게 아닐까 싶다.

     

    관련해서 서브 클래싱에 대한 정보를 찾게 되었는데 내용은 다음과 같다.

     

    창 프로시저 사용 - Win32 apps | Microsoft Docs

     

    창 프로시저 사용 - Win32 apps

    이 섹션에서는 창 프로시저와 관련된 다음 작업을 수행하는 방법을 설명합니다.

    docs.microsoft.com

     

    베이비들의 블로그 (zum.com)

     

    서브클래싱

    서브클래싱이란 쉽게 말해 윈도우 메세지를 가로채오는 것을 말한다.EDIT BOX → WM_KEYDOWN이런식으로 돌아가는데 내가 WM_KEYDOWN 메세지가 발생했을 때 다른 기능을 수행하고싶다하면EIDT BOX WM_KEYDOWN

    egloos.zum.com

     

    이것들을 확인해본 결과 WM_SIZE에 대한 처리를 새로운 WIN_PROC에서 받아서 수정한 뒤 기존 처리를 위해 전달하는 것으로 보인다.

     

    정확하게 동작하고 있는지 확인하기 위해 WM_SIZE인 경우 메시지를 전달하는 대신 바로 종료하도록 한다.

    그런데 빌드 후 실행한 결과 기존과 동일하게 사이즈가 변경되고 있는 것을 확인할 수 있었다.

     

    이 처리가 교체되는 게 아닌가 싶어서 모든 경우에 기존 함수를 호출하지 않도록 한 경우 모든 메시지가 막히며 조작 자체가 불가능하게 되었다.

     

    일단 마지막 시도로 Rect의 left와 top은 그대로 두고 크기만 바꿔서 right, bottom을 업데이트해주도록 했다.

     

    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:
                        newHeight = Mathf.RoundToInt(newWidth / aspect);
                        //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:
                        newWidth = Mathf.RoundToInt(newHeight * aspect);
                        //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:
                        newHeight = Mathf.RoundToInt(newWidth / aspect);
    					//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;
    
                rc.Right = rc.Left + newWidth + borderWidth;
                rc.Bottom = rc.Top + newHeight + borderHeight;
    
                // Add back borders.
                //rc.Right += borderWidth;
                //rc.Bottom += borderHeight;
    
                // Trigger resolution change event.
                resolutionChangedEvent.Invoke(newWidth, newHeight, Screen.fullScreen);
    
                // Write back changed window parameters.
                Marshal.StructureToPtr(rc, lParam, true);
            }
    
            // Call original WindowProc function.
            return CallWindowProc(oldWndProcPtr, hWnd, msg, wParam, lParam);
        }

     

    실행결과

     

    일단 원하는 대로 떨리지 않고 적절하게 크기가 바뀌는 것을 확인했다.

     

    그런데 최소, 최대 크기 설정에서 가로, 세로가 적절하지 않은 것 같으니 기존 동작을 확인해서 그대로 동작할 수 있도록 수정해 봐야겠다.

    댓글

Designed by Tistory.