ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • C# WinForms에서 레이아웃 깨지는 문제 해결 방법. 디스플레이 해상도, 텍스트 배율 안 따라게 하기
    닷넷/WinForms 2022. 2. 22. 17:37
    반응형

    사용자들이 윈폼에서 레이아웃이 깨진다고 표현하는 현상은 사용자의 디스플레이 상태가 개발 환경과 다른 경우 종종 일어날 수 있는 일이다.

    해상도에 따라서 레이아웃이 깨진다면, Form 속성에 AutoScaleMode를 이용하면 깨지지 않게 할 수 있다.

    AutoScaleMode에서 Inherit은 클래스의 부모 확장 모드에 따라 배율을 제어한다. 부모가 없는 경우 자동 스케일링이 비활성화된다. 즉, 부모 폼이 있다면 자식 폼이 부모 폼의 AutoScaleMode를 따라간다.

     

    AutoScaleMode를 Font로 했을 때 텍스트 배율 100% 화면

    Font는 클래스가 사용하고 있는 글꼴의 치수에 상대적인 축척(일반적으로 시스템 글꼴)을 제어한다.

    윈폼에서 AutoScaleMode는 기본적으로 Font로 설정되어 있어서 개발 도중에도 폰트를 바꾼다거나 크기를 바꾸게 되면 이에 따라서 레이아웃이 깨지거나 틀어지는 현상이 발생 한다.

     

    AutoScaleMode를 Dpi로 했을 때 텍스트 배율 100% 화면

    Dpi는 디스플레이 해상도를 기준으로 한 척도 조절, 일반적인 해상도는 96과 120 DPI이다.

    해상도에 따라서 폼 크기가 커지거나 작아질 수 있다.

    비율적으로 바뀌기 때문에 컨트롤이 폼 크기를 넘어가서 안 보이게 되는 경우 폼에 AutoScroll 속성을 true로 설정하여 스크롤로 보게끔 조절 할 수 있다.

     

    AutoScaleMode를 None으로 했을 때 텍스트 배율 100% 화면

    폰트에 따라서 바뀌게도 하고 싶지 않고, 해상도에 따라서도 바뀌게도 하고 싶지 않으면 None으로 설정 한다.

     

    이때, AutoScaleMode를 None으로 했을 때 문제점은 텍스트 배율을 변경하는 경우에 발생한다.

    Windows 7에서 디스플레이 텍스트 배율 선택 화면

     

    Windows 10에서 텍스트 배율 선택 화면

     

    AutoScaleMode를 None으로 했을 때 텍스트 배율 150% 화면

    레이아웃의 전체적인 크기는 고정이 되지만 글자 크기는 디스플레이의 텍스트 배율을 따라가게 되기 때문이다.

     

    2주 동안 테스트 하고 나온 결론은 125% 일 때만 텍스트 배율에 영향을 받으며 두 번째로 참고한 코드는 원하는대로 사용하기에는 불필요한 계산이다.
    따라서 폰트사이즈 변경에 대한 내용을 수정했다.
    2022-03-17

     

    이 문제를 해결 하는 방법은 스택오버플로우의 아래 질문에 달린 답변으로 텍스트 배율을 찾은 다음 현재 폰트 크기에서 나누기를 하여 해결 할 수 있었다.

    https://stackoverflow.com/questions/9373260/detect-windows-font-size-100-125-and-150

    텍스트 배율(DPI scale)을 찾는 코드

     

    https://stackoverflow.com/questions/45426291/change-the-font-size-of-all-controls-in-the-application-win-forms/60563007#60563007

    여기서는 컨트롤들의 폰트 사이즈를 변경해주는 메소드 그대로 가져 온 다음, amount에는 시스템 상의 텍스트 배율에 따라 100%일 때는 0, 125%일 때는 크기가 100%때와 똑같은 크기가 되어야 하므로 -2, 150%는 -3으로 값이 들어가게, amountInPercent는 false로 하여 메소드를 사용 한다.

     

    public void ReSetFontSize(System.Windows.Forms.Control.ControlCollection ctrls)
    {
        float scale = 1f;
        using (RegistryKey key = Registry.CurrentUser.OpenSubKey("Control Panel\\Desktop\\WindowMetrics"))
        {
            if (key != null)
            {
                Object o = key.GetValue("AppliedDPI");
                if (o != null)
                {
                    int value = (int)o;
                    scale = (float)value / 96f;
                }
            }
        }           
    
        if (scale == 1.25)
        {
            SetAllControlsFontSize(Controls, 1.27f);
        }
    }
    
    
    private void SetAllControlsFontSize(System.Windows.Forms.Control.ControlCollection ctrls, float scale)
    {
        foreach (Control ctrl in ctrls)
        {
            if (ctrl.Controls != null) SetAllControlsFontSize(ctrl.Controls, scale);
            if (ctrl != null)
            {
                Font oldFont = ctrl.Font;
                ctrl.Font = new Font(oldFont.Name, oldFont.Size / scale);
            }
        }
    }

     

    그렇게 만들어진 코드를 위와 같이 폼 생성자나 Form_Load, Form_Shown 같은 이벤트에 써주면 

    AutoScaleMode를 None으로 했을 때 텍스트 배율 150% 화면이지만 컨트롤들의 글자 크기는 100%와 똑같다.

    폼, 레이아웃의 크기와 글자크기를 디스플레이의 해상도와 텍스트 배율에 따라가지 않게 만들 수 있다.

    반응형

    댓글

Designed by Tistory.