Windows Forms의 높은 DPI 지원

.NET Framework 4.7부터 Windows Forms는 일반적인 높은 DPI 및 동적 DPI 시나리오에 대한 향상된 기능을 포함합니다. 이러한 개체는 다음과 같습니다.

  • MonthCalendar 컨트롤 및 CheckedListBox 컨트롤과 같은 여러 Windows Forms 컨트롤의 크기 조정 및 레이아웃이 향상되었습니다.

  • 단일 패스 스케일링. .NET Framework 4.6 이전 버전에서는 다중 패스를 통해 스케일링이 수행되어 일부 컨트롤이 필요 이상으로 스케일링되었습니다.

  • Windows Forms 애플리케이션이 시작된 후 사용자가 DPI 또는 배율 인수를 변경하는 동적 DPI 시나리오를 지원합니다.

.NET Framework 4.7 이후의 .NET Framework 버전에서는 향상된 높은 DPI 지원이 옵트인 기능입니다. 애플리케이션에서 이 기능을 활용하도록 구성해야 합니다.

높은 DPI 지원을 위한 Windows Forms 앱 구성

높은 DPI 인식을 지원하는 새로운 Windows Forms 기능은 .NET Framework 4.7을 대상으로 하고 Windows 10 크리에이터스 업데이트로 Windows 운영 체제에서 실행되는 애플리케이션에서만 사용할 수 있습니다.

또한 Windows Forms 애플리케이션에서 높은 DPI 지원을 구성하려면 다음을 수행해야 합니다.

  • Windows 10 호환성을 선언합니다.

    이렇게 하려면 다음을 매니페스트 파일에 추가합니다.

    <compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
      <application>
        <!-- Windows 10 compatibility -->
        <supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}" />
      </application>
    </compatibility>
    
  • app.config 파일에서 모니터별 DPI 인식을 사용하도록 설정합니다.

    Windows Forms는 새 <System.Windows.Forms.ApplicationConfigurationSection> 요소를 도입하여 .NET Framework 4.7부터 추가된 새로운 기능 및 사용자 지정을 지원합니다. 높은 DPI를 지원하는 새로운 기능을 활용하려면 애플리케이션 구성 파일에 다음을 추가합니다.

    <configuration>
      <!-- ... other xml settings ... -->
    
      <System.Windows.Forms.ApplicationConfigurationSection>
        <add key="DpiAwareness" value="PerMonitorV2" />
      </System.Windows.Forms.ApplicationConfigurationSection>
    
    </configuration>
    

    중요

    이전 버전의 .NET Framework에서는 매니페스트를 사용하여 높은 DPI 지원을 추가했습니다. 이 방법은 app.config 파일에 정의된 설정을 재정의하므로 더 이상 권장되지 않습니다.

  • 정적 EnableVisualStyles 메서드를 호출합니다.

    애플리케이션 진입점에서 첫 번째 메서드 호출이어야 합니다. 예를 들면 다음과 같습니다.

    static void Main()
    {
        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);
        Application.Run(new Form2());
    }
    

높은 DPI 기능 개별 옵트아웃

DpiAwareness 값을 PerMonitorV2로 설정하면 .NET Framework 4.7 이상인 .NET Framework 버전에서 지원하는 모든 높은 DPI 인식 기능을 사용할 수 있습니다. 일반적으로 대부분의 Windows Forms 애플리케이션에 적합합니다. 그러나 하나 이상의 개별 기능을 옵트아웃할 수 있습니다. 이 작업을 수행하는 가장 중요한 이유는 기존 애플리케이션 코드가 해당 기능을 이미 처리하기 때문입니다. 예를 들어 애플리케이션에서 자동 스케일링을 처리하는 경우 다음과 같이 자동 크기 조정 기능을 사용하지 않도록 설정할 수 있습니다.

<configuration>
  <!-- ... other xml settings ... -->

  <System.Windows.Forms.ApplicationConfigurationSection>
    <add key="DpiAwareness" value="PerMonitorV2" />
    <add key="EnableWindowsFormsHighDpiAutoResizing" value="false" />
  </System.Windows.Forms.ApplicationConfigurationSection>

</configuration>

개별 키 및 해당 값 목록은 Windows Forms 구성 요소 추가를 참조하세요.

새 DPI 변경 이벤트

.NET Framework 4.7부터 세 개의 새 이벤트를 사용하여 동적 DPI 변경 내용을 프로그래밍 방식으로 처리할 수 있습니다.

  • DpiChangedAfterParent는 부모 컨트롤 또는 양식에 대한 DPI 변경 이벤트가 발생한 후에 컨트롤의 DPI 설정이 프로그래밍 방식으로 변경되면 발생합니다.
  • DpiChangedBeforeParent는 부모 컨트롤 또는 양식에 대한 DPI 변경 이벤트가 발생하기 전에 컨트롤의 DPI 설정이 프로그래밍 방식으로 변경되면 발생합니다.
  • DpiChanged는 양식이 현재 표시되어 있는 디스플레이 디바이스에서 DPI 설정이 변경되면 발생합니다.

새 도우미 메서드 및 속성

또한 .NET Framework 4.7에서는 DPI 스케일링에 대한 정보를 제공하고 DPI 스케일링을 수행할 수 있는 다양한 새로운 도우미 메서드와 속성이 추가되었습니다. 이러한 개체는 다음과 같습니다.

  • LogicalToDeviceUnits는 값을 논리 픽셀에서 디바이스 픽셀로 변환합니다.

  • ScaleBitmapLogicalToDevice는 디바이스에 대한 논리 DPI에 맞추어 비트맵 이미지를 스케일링합니다.

  • DeviceDpi는 현재 디바이스에 대한 DPI를 반환합니다.

버전 관리 고려 사항

.NET Framework 4.7 및 Windows 10 크리에이터스 업데이트를 실행하는 것 외에도 애플리케이션이 높은 DPI 개선 사항과 호환되지 않는 환경에서 실행될 수도 있습니다. 이 경우 애플리케이션에 대한 대체를 개발해야 합니다. 이를 통해 사용자 지정 그리기를 수행하여 스케일링을 처리할 수 있습니다.

이렇게 하려면 앱이 실행 중인 운영 체제도 확인해야 합니다. 다음과 같은 코드를 사용하여 수행할 수 있습니다.

// Create a reference to the OS version of Windows 10 Creators Update.
Version OsMinVersion = new Version(10, 0, 15063, 0);

// Access the platform/version of the current OS.
Console.WriteLine(Environment.OSVersion.Platform.ToString());
Console.WriteLine(Environment.OSVersion.VersionString);

// Compare the current version to the minimum required version.
Console.WriteLine(Environment.OSVersion.Version.CompareTo(OsMinVersion));

애플리케이션 매니페스트에서 지원되는 운영 체제로 나열되지 않은 경우 애플리케이션에서 Windows 10을 성공적으로 검색할 수 없습니다.

애플리케이션이 빌드된 .NET Framework 버전을 확인할 수도 있습니다.

Console.WriteLine(AppDomain.CurrentDomain.SetupInformation.TargetFrameworkName);

참고 항목