Jump to content
과거의 기술자료(읽기 전용): https://tech.devgear.co.kr ×
과거의 기술자료(읽기 전용): https://tech.devgear.co.kr
  • [DelphiCon 요약] High-DPI 고해상도를 VCL에서 활용하기


    Kori

    << DelphiCon 2020 목록으로 이동

    DelphiCon 의 2020 시리즈 중, Leveraging High DPI in VCL Applications - Ray Konopka 의 한글 요약본입니다.  

    • 발표자 (Ray Konopka)는 CodeSite, Konopka Signature VCL로 유명한 Raize Software의 창업자이며, 월트 디즈니 어트렉션 테크놀러지의 수석 소프트웨어 엔지니어로서, 디즈니리조트, 디즈니랜드 등의 소프트웨어도 개발합니다.  도서 “델파이 컴포넌트 개발하기(Developing Custom Delphi Component)” 저자이기도 합니다.
    • 델파이는 델파이로 만듭니다. 델파이는 11.0 버전에서 IDE 자체에 HighDPI를 적용하였습니다. 그 결과, 델파이 사용자들이 더 쾌적하게 개발할 수 있게 되었습니다. (모니터가 4K 이상이라면 더욱 효과가 큽니다)
    • 여러분의 앱에서도 델파이 11.0과 같이 서로 다른 다중 모니터 특히 최근에 부쩍 많아진 High DPI 모니터 지원할 수 있습니다. 그 방법을 이 세션에서 설명합니다. 
    • 원본 비디오(YouTube) 보기 (54 min)를 권장합니다. 발표 자료도 참고하세요.

    목차


    High DPI 관련 핵심 개념

    • DPI (Dots Per Inch): 1인치에 들어가는 점(Dot)의 갯수 (역자 주: 점은 LCD모니터, 프린터 등 출력 장치의 물리적인 최소 표현 단위)
    • PPI (Pixels Per Inch): 1인치에 들어가는 픽셀(Pixel)의 갯수 (역자 주: 픽셀은 Pics+Element의 복합어이며, 디지털 이미지를 만들 때 사용되는 논리적인 최소 표현 단위)
    • 아주 오래전부터 “윈도우에서 표준 DPI는 96이다”라고 간주하면 안전했다.
      • 그래픽의 사실 상 표준이었던 픽셀 기반은 VGA 부터 sVGA, XGA…로 이어져 오면서 지켜져왔다.
    • DPI와 해상도(Resolution)가 서로 관련은 있지만, 항상 일치하는 것은 아니다. 지금은 더욱 그렇다.
      • 예전에는, 대체로 차이가 거의 없었다.
        • 얼마전까지는 대체로 모니터가 커지고 해상도가 높아져도, 이때에도 '점'의 크기 즉 DPI는 대체로 그대로 유지되면서 크기만 커졌다.
        • 따라서 , 모니터에서 해상도가 커지는 비율 만큼 '점'의 갯수도 같은 비율로 많아지게 된다.
      • 하지만 최근에는, High DPI 장비가 많아졌다

     이제는 개발자가 '단 하나의 DPI' 를 기준으로 잡지 못할 만큼 모니터의 DPI 너무 다양해졌다.

    화면 배율 (Display Scale Factor)

    • 예전에는, 96 DPI 가 거의 모든 모니터에서 사실 상 표준으로 지켜졌으므로, 1024, 1440 등 해상도가 커져도 UI 작성에 영향이 없었다.
      • 동일하게 96 DPI 인 경우,해상도가 커지면, 활용할 수 있는 면적이 그만큼 커진다는 점만 고려하면 충분했다.
      • 16 x 16 아이콘을 어느 해상도에서 사용해도 큰 문제는 없었다.
    • 이제는, High DPI 화면인 경우, 화면 요소들이 잘 보이도록하는 조치가 필요하다.
      • 예: 226 DPI인 새 노트북에서는 16 x 16 아이콘은 실제 크기가 3mm이다. 너무 작아서 거의 보이지도 않는다.
    스크린 해상도 DPI 해당 물리적 화면 크기
    1024 x 769 96 10.7” x 8"
    1440 x 900 96 15” x 9”.375
    2560 x 1440 109 23.4” x 13.2”
    3074 x 1920 226 (훨씬 높다) 13.6” x 8.”5 (얼마전에 구입한 노트북)

    표1. 얼마 전에 구입한 노트북이 경우, 물리적인 화면의 크기는 더 작은데 DPI는 훨씬 높다.

    개발자가 '단 하나의 DPI' 를 기준으로 정하기가 어려운 이유는?

    • 여러 모니터를 동시에 사용하고, 각 모니터의 해상도가 다양해졌다.
      • 사용자가 사용 중인 앱을 드래그하여 DPI가 다른 모니터로 옮기기도 한다.
      • 이제는 다중 모니터 사용에 거의 제한이 없다. (오래 전의 윈도우는 미리 정의된 해상도에 맞는 모니터만 연결할 수 있었다)
    • 사용자가 노트북이나 태블릿에 외부 모니터를 연결/해제하는 경우가 많다.
    • 사용자가 원격 데스트탑을 통해 앱을 사용하기도 한다.
    • 사용자가 컴퓨터 사용 중에 화면 배율(Display Scale Factor)을 변경하기도 한다.

    (데모) 윈도우 메모장을 통해 다중 모니터의 표현 이해하기

    (비디오 7분 30초부터 보기)

    DelphiCon-HighDPI1-MultiMonitor250.png
    윈도우 메모장의 250% 배율 화면: 메인 메뉴 사이의 간격이 매우 좁다.
    DelphiCon-HighDPI1-MultiMonitor100.png
    윈도우 메모장의 일반 배율(100%) 화면

    DPI, 해상도, 배율이 다른 모니터를 모두 잘 지원하기는 쉽지 않다. 

    윈도우 메모장을 보면,

    • High DPI를 전반적으로 무난하게 지원하고 있다.
      • 앱은 배율에 맞게 확대되면서도, 화면이 선명하고, 글자 폰트도 선명하다.
    • 하지만, High DPI에서 여백도 다르고, 본문의 문장의 길이도 다르다.
      • 무엇보다 메인 메뉴 간의 간격이 좁아져서 사용하기에 살짝 불편하다.

    High DPI에서 윈도우 앱은 "폰트" 확대/축소도 완벽하게 지원하기가 힘들다. "이미지"는 더욱 다루기가 어렵다.

    애플은 High DPI 처리가 단순 명확하다. 

    애플은 모든 화면 요소에서 물리적 표현 단위인 "포인트"를 사용한다.

    • 맥 OS와 iOS에서 PPI는 Point Per Inch를 의미한다. (Pixel Per Inch가 아니다)
    • 애플의 표준은 1인치 당 72 포인트이고, 잘 지켜지고 있다.
    • 따라서, 모니터에 맞게 확대/축소 시, 단순히 배율을 적용한다.

    역사적 배경

    • 그래픽 인쇄 분야에서는 DPI (인치당 표현되는 물리적인 점)이 중요하다.
    • 애플은 오래 전부터 이 분야에서 독보적이었다.

    윈도우는 High DPI를 다루기가 어렵다.

    (비디오 11분 47초부터 보기)

    마이크로소프트는 애플과 달리 논리적인 단위"픽셀"을 사용한다.

    Dialog Unit (DLU)

    • 마이크로소프트가 고안한 단위로써, 여러 디스플레이 장비를 다룰 수 있도록 윈도우를 설계하는 과정에 생겨났다.
    • 1 Dialog Unit = 윈도우 시스템 폰트 너비 평균의 1/4
    • Dialog Unit는 논리적인 단위이므로, 물리적인 장비에 따라 달라진다. (장비 의존성이 없고, 물리적 면적에 맵핑되지 않는다)
    • 수직 Dialog Unit와 수평 Dialog Unit가 일치하지 않을 수도 있다.

    문제는 지금은 아무도 더이상 Dialog Unit을 사용하지 않는다는 점이다.

    • 마이크로소프트의 개발도구 역시 마찬가지로, 닷넷, 윈폼, XAML 에서도 Dialog Unit을 사용하지 않는다.
    • 요즘 개발도구는 대부분 픽셀(Pixel)을 사용한다.  (마이크로소프트 개발도구도 마찬가지이다.)

    픽셀은 논리적 단위이며, 물리적 크기가 고정되어있지 않다.

    • 예전에는 거의 모든 모니터가 96 DPI 를 사용했다.
      • 물리적인 단위가 변하지 않으므로, 그것에 기반한 논리적인 단위인 픽셀 역시 실제로 물리적 크기가 고정된 것과 같았다.
    • 이제는 댜양한 DPI가 사용된다.
      • High DPI인 4K 모니터와 일반 모니터는 물리적인 단위인 DPI가 다르기 때문에 그것에 기반한 픽셀의 물리적인 실제 크기 역시 서로 다르다.

    윈도우에서는 논리적 크기인 픽셀과 화면의 물리적인 실제 크기를 연결할 방법이 있어야만, High DPI를 다룰 수 있다.

    윈도우에서 제공하는 DPI 확대/축소

    윈도우는 우리가 아무 조치를 하지 않아도 High DPI 화면에 알아서 표현한다.

    • 윈도우 메모장 데모에서 본 것 처럼 꽤 괜찮지만 여전히 완벽하지는 않다.

    개발한 윈도우용 앱이 High DPI 를 잘 지원하기 위해서, 개발자가 관여 해야 한다.

    픽셀 크기의 기준을 정하고, 윈도우10 에서 제공하는 DPI 배율 확대/축소(Scaling) 기능을 활용하자.

    • 윈도우는 최신 버전으로 오면서 High DPI 지원이 점점 좋아졌고, 윈도우10에서 상당히 향상되었다.
    • 개발자는 DPI 인식 방식을 각 앱 별로 매니페스트(Manifest)에 기록하여 윈도우에게 알려줄 수 있다.

    델파이의 DPI Awareness 옵션 5가지 (2020.11 현재)

    (비디오 18분 17초부터 보기)

    위치: 델파이에서 Project > Options > Application > Manifest > DPI Awareness 옵션

    Unaware (DPI 인식 안함) 

    • 방식: 윈도우 비트맵은 가장 일반적인 96 dpi를 기준으로 각 모니터에 맞게 확대/축소하여 렌더링한다.
    • 장점
      • 모든 화면 요소를 단순하게 확대/축소하므로, 요소의 위치나 크기가 잘못되지 않는다.
    • 단점
      • 화면이 선명하지 않다.
      • 특히 해상도 낮은 이미지를 High DPI 모니터에서 보면 픽셀이 그대로 드러난다.
    • 의견: 무난한 선택이지만, 보기에 좋지 않기 때문에 최고의 선택은 아니다. (데모 보기)

    System aware (시스템 DPI 반영)

    • 방식:사용자가 윈도우를 시작할 때 로그인한 모니터의 DPI를 사용하여 윈도우가 알아서 확대/축소하여 렌더링한다.
    • 장점: (언급되지 않음)
    • 단점
      • 사용자가 윈도우를 시작한 주 모니터에 따라, 렌더링 기준이 달라진다. 
      • 사용자가 폼을 다른 모니터로 옮기거나 화면 배율(확대/축소)을 변경하면, 화면이 그다지 좋지 않다.
    • 의견: 권장하기 어렵다. (데모 보기)

    Per Monitor (모니터 별 DPI 반영)

    • 방식: DPI 변경을 최상위 창에 공지하여 DPI가 다른 모니터에서 앱을 따로 다룰 수 있도록 한다.
      • 마이크로소프트가 윈도우8.1부터 채택했다
    • 장점: 윈도우가 모든 것을 임의로 확대/축소하지 않게 되었다.
    • 단점: 실제로는 잘 지원하지 못하고 화면이 틀어진다. (뒤에서 살펴보겠다)
    • 의견: 특별한 이유가 없다면, 사용하지 않는 것이 좋다. (데모 보기)

    GDI Scaling (GDI 확대/축소)

    • 델파이 10.4에서 VCL용으로 추가되었다. (10.3에서도 가능하긴 했지만 사용하기 불편했다)
      • 윈도우 10 Creators 업데이트 (1703)에서 도입된 기술이 반영된 것이다.
    • 방식: 폰트와 기본 도형 등 모든 것을 GDI 프레임워크가 알아서 DPI에 맞게 확대/축소한다.
      • 디스플레이 배율값과 동일하게 오브젝트를 확대/축소한다.
      • 모니터에 맞게, GDI가 알아서 알맞은 폰트를 사용한다.
        • 원래 10pt인 폰트에 만약 @200% 텍스트가 적용되면, 렌더링할 때 GDI는 실제로 20pt 폰트를 사용한다.
    • 장점
      • 이미지을 제외한 모든 화면 요소를 GDI가 알아서 깔끔하게 표현한다.
      • 개발자가 가장 쉽고 빠르게 High DPI를 잘 지원하는 앱을 만들 수 있다.
    • 단점
      • 개발자가 각 앱별로 별도의 매니페스트를 변경/배포해야 한다.
      • 한 단어 안에서 글자 간격이 불규칙하고 글자가 너무 가깝게 겹칠 수도 있다.
        • 폰트를 잘 선택하여 해결할 수도 있다.
      • 아이콘 등 이미지는 단순히 늘어나거나 줄어들기 때문에 High DPI에서 깨끗하게 표현되지 못한다.
      • 개발자가 관여할 여지가 전혀 없으므로, High DPI 이슈를 개발자가 해소하지 못한다.
    • 의견: 이미지에 색상이나 곡선이 많지 않거나 위의 단점이 문제 되지 않는다면, 최고는 아니지만 대안이 될 수 있다. (데모 보기)

    Per Monitor V2 (모니터 별 DPI 반영 버전 2)

    • 델파이 10.4부터 제공된다. (역자 주: 델파이 10.3 에도 이 옵션이 있었다)
      • GDI Scaling과 마찬가지로, 윈도우10 Creators 업데이트 (1703) 이후 버전에서 작동한다.
    • 방식
      • 자동 스케일링을 통해 해당 DPI에 맞게 이미지를 제외하고, 모든 것이 확대/축소된다.
      • 또한, DPI 변경을 최상위 창에 공지하여 DPI가 다른 모니터에서 앱을 따로 다룰 수 있도록 한다.
    • 장점:
      • 앱에서 DPI 변경을 인지할 수 있어서, 개발자가 미리 대응할 수 있다.
      • 자동으로 테마가 그리는 윈도우 비트맵은 모두 DPI에 맞게 확대/축소 된다.
        • 비클라이언트 (NonClient) 영역까지도 해당된다.
        • 체크 박스, 라디오 버튼등 공통 콘트롤, 파일 찾기, 폰트 설정 등 윈도우 대화상자 모두가 해당된다.
    • 의견: High DPI를 가장 잘 다룰 수 있는 선택이다. (데모 보기)

    (데모) 델파이 프로젝트에서 지정한 DPI Awareness 옵션 별 결과 비교

    Unaware

    (비디오 25분 40초부터 보기)

    1_unaware_250.png
    High DPI 모니터

    • 실제로 High DPI를 활용하지는 못한다.
    • 앱에서는 폼의 크기는 425 x 405로 인식하고, 폼 전체가 배율에 맞게 단순하게 늘어난다.
      • 모든 요소가 제자리에 있고, 모든 것이 일반 모니터에서와 동일하게 작동한다.
      • 하지만, 폼 전체의 표현이 깔끔하지 않고, 글자와 이미지 곡선에서는 픽셀이 드러난다.
    1_unaware_100.png
    일반 모니터 (96 DPI)

    ( Unaware 설명 보기)

    System aware

    (비디오 28분 15초부터 보기)

    2_system_aware_250.png
    High DPI 모니터 (사용자가 윈도우 로그인을 한 주 모니터)
    • 아이콘 이미지가 매우 작다 (High DPI에서도 여전히 16x16 크기로 표현되기 때문)
    • 폰트 등 화면 요소들이 선명하게 표현되지는 않는다.
    • 폼 크기는 1055x1002로 High DPI를 활용한다.

    2_system_aware_100.png
    일반 모니터 (96 DPI)

    • 96 DPI 모니터에서도 폼 크기는 1055x1002이다.
    • 주모니터인 High DPI를 기준으로 96 DPI와 차이만큼 그대로 축소된다.
    • 그 결과, 모든 것이 크기도 작아지고 선명하지 않다.

    (System aware 설명 보기)

    Per Monitor

    (비디오 30분 01초부터 보기)

    3_per_monitor_250.png
    High DPI 모니터

    • High DPI에서 폰트 등 화면 요소들이 훨씬 깔끔하게 표현된다.
    • 아이콘 이미지가 매우 작다 (High DPI에서도 여전히 16x16 크기로 표현된다)
    • 폼 크기는 1055x1002로 High DPI를 활용한다.

    3_per_monitor_100.png
    일반 모니터 (96 DPI)

    HighDPI에서 잘 보이던 요소들이 96 DPI에서는 크기와 위치가 가 알맞게 적용되지 않는다.

    • 스크롤 바 크기가 훨씬 굵어졌다.
    • 체크 박스와 라디오 버튼 윗부분이 잘렸다.
    • 툴바의 아이콘 간격이 틀어졌다.

    이유는, DPI 변경을 앱의 폼에게 전달하지 못하기 때문이다.

    • 스크롤 바와 같은 윈도우 공통 콘트롤에서도 변경전의 DPI를 그대로 반영된다. 

    (Per Monitor 설명 보기)

    GDI Scaling

    (비디오 32분 11초부터 보기)

    4_GDI_Scaling_250.png
    High DPI 모니터

    개발자가 앱이 GDI Scaling을 사용하도록 별도로 매니페스트를 변경/배포 함으로써,
    가장 쉽고 빠르게 GDI를 지원할 수 있으므로 최고는 아니지만 대안이 될 수 있다.

    • 폼은 자신의 크기가 425x405인 줄 알고 있다. 즉 96 DPI 인 줄 안다.
    • 하지만, GDI가 알아서 모든 화면 요소를 High DPI에서 선명하게 표현한다.
      • 폰트, 메뉴간의 간격, 윈도우 콘트롤 등 (단, 이미지는 제외)
    • 폰트는 배율에 맞게 더 큰 폰트가 적용되어서 깨끗하게 표현된다.
    • 아이콘 이미지가 선명하지 않다. (여기서는 아이콘의 16x16 이미지를 단순히 늘렸다)
    • 이미지에 색상이나 곡선이 많지 않은 앱이라면 보기 좋지 않을 수 있다.

    4_GDI_Scaling_100.png
    일반 모니터 (96 DPI)

    GDI Scaling은 완벽하지 않지만 멀티 모니터를 대체로 잘 지원한다.

    (GDI Scaling 설명 보기)

    Per Monitor V2

    (비디오 35분 04초 부터 시청)


    High DPI 모니터5_per_monitor_v2_250.png

    델파이 10.4부터 제공되며, 가장 완벽하게 High DPI를 지원할 수 있는 옵션이다.

    • High DPI에서 화면 요소가 선명하다는 GDI Scaling의 장점을 그대로 가진다.
      • 폰트, 배치, 윈도우 콘트롤 (스크롤 바 등)이 선명하다.  
    • 아이콘 이미지가 매우 작다. (High DPI에서도 여전히 16x16 크기로 표현된다)
    • UI 콘트롤을 동적으로 생성할 때에는 제대로 표현되지 않는다.
    5_per_monitor_v2_100.png
    일반 모니터 (96 DPI)

    (Per Monitor V2 설명 보기)

    TImageCollection

    • 서로 다른 해상도를 가진 이미지들을 공유하는 저장소
      • 예: 아이콘 이미지를 16x16, 32x32 등 여러 해상도에 맞게 보관할 수 있다.
    • 비시각적 컴포넌트이므로 어디든지 넣고 공유할 수 있다.
      • 데이터 모듈이나 메인 폼 등 원하는 곳에 올려두고 쓸 수 있다.
    • 명명 규칙을 맞추어서 이미지 이름을 정하면, 알맞은 이미지가 자동으로 로딩된다.
      • Size in the file name 옵션이 선택되어 있는 지 확인할 것 (ImageCollection 에디터)
      • 다음 3가지 구분자 중 한가지 사용 가능 (-, _, @)
      • 파일명 예시: File-Open-16.png , Edit-Paste-48.png 

    TVirtualImageList

    • 해당 폼의 DPI를 파악하여 각 폼에서 알맞은 이미지를 TImageCollection에서 가져와서 사용하도록 한다.
    • 각 폼마다 각자 TVirtualImageList를 가지고 있어야 한다. 
      • 데이터 모듈이나 메인폼에 올려두고 공유하여 다른 폼에서 사용할 수는 없다.
      • 각 폼은 다른 모니터에서 표현될 수 있고, 모니터에 따라 DPI가 다르게 적용될 수 있기 때문이다.
    • AutoFill 프로퍼티
      • AutoFill을 True로 지정하면, TImageCollection 안의 모든 이미지 중에서 알맞은 것을 TVirtualImageList로 가져온다.
      • 만약, TVirtualImageList에서 TImageCollection 안의 이미지 중 몇가지만 사용하고 싶으면, 
        AutoFill을 False로 지정하고, 원하는 이미지만 선택할 수 있다.

    (데모) Per Monitor V2 옵션에서 TImageCollection와 TVirtualImageList를 사용하기

    (영문 비디오 42분 01초부터 보기

    한국어 더빙 비디오에서 이부분 부터 재생되는 비디오

     

    Per Monitor V2 옵션에서 UI 콘트롤을 동적으로 생성할 때 알맞게 표현하기 위한 VCL 함수들

    VCL의 새 함수(들) 단, (윈도우 10 최근 버전의 API를 활용하므로) 윈도우 10 최근 버전 이후에서 만 작동한다.

    • Vcl.Controls.GetSystemMetricsForWindow()
      • 윈도우에 새로 추가된 API인 GetSystemMetrics()와 GetSystemMetricsForDPI()를 호출한다.
      • 이전 버전에서 호출을 시도해도 안전하다.
    • TControl.GetSystemMetrics()
      • 개발자가 편하게 사용하도록 VCL에서 TControl에 GetSystemMetrics가 추가되었다.
        (DPI 확인은 대체로 콘트롤에서 필요하기 때문이다)
      • 폼 등 모든 TControlGetSystemMetricsForWindow 를 호출할 수 있다.
      • 혹시, 이미 윈도우 API에서 직접 GetSystemMetrics를 사용한 코드가 있다면,
        WinAPI.Windows.GetSystemMetrics로 변경하여 기존 유닛을 그대로 사용해도 된다.
    • TControl.CurrentPPI 프로퍼티

    (데모) Per Monitor V2 옵션에서, UI 콘트롤을 동적으로 생성할 때 알맞게 표현하기

    (영문 비디오 50분 49초부터 보기)

    한국어 더빙 비디오에서 이부분 부터 재생되는 비디오

     

    // 처음 한번 알맞은 크기와 위치에 동적으로 생성되고나면, DPI가 다른 화면에서 표현될 때에도 알맞게 표현된다.
    procedure TFrmMain.btnAddClick(Sender: TObject);
    var
      X, Y, W, H: Integer;
    begin
      B := TButton.Create( Self );
      B.Parent := pnlPreview;
    
      // (변경 전, 10 pixel로 지정)
      // X := 10;
    
      // (변경 후)
      // VCL.Controls 유닛에 있는 TControl.CurrentPPI 프로퍼티를 사용하여 해당 PPI를 가져와서,
      // 96 DPI일 때 10 pixel을 기준으로 하고, MulDiv 함수를 사용하여 해당 PPI에 맞게 다시 지정한다.
      // (참고: Muldiv는 앞의 두 숫자를 곱하고 이어서 세번째 숫자로 나눈 후에 Integer로 반올림하는 델파이 함수) 
      // 일단 이렇게 생성되고 나면, 다른 콘트롤과 마찬가지로 DPI가 다른 모니터로 옮겨져도 알맞게 맞추어진다.
      X := MulDiv ( 10, CurrentPPI, 96 ); // = 10 * CurrentPPI / 96
      Y := MulDiv ( 10, CurrentPPI, 96 );
      W := MulDiv ( 75, CurrentPPI, 96 );
      H := MulDiv ( 25, CurrentPPI, 96 );
    
      B.SetBounds( X, Y, W, H );
     end;

    6_per_monitor_v2_250_Final.png
    Per Monitor V2 매니페스트와 추가된 API를 사용하여 High DPI에서 완벽하게 표현된 결과. end.

    << DelphiCon 2020 목록으로 이동

     

     


    User Feedback

    Recommended Comments

    There are no comments to display.


×
×
  • Create New...

중요한 정보

이용약관 개인정보보호정책 이용규칙 이 사이트가 더 잘 작동하기 위해 방문자의 컴퓨터에 쿠키가 배치됩니다. 쿠키 설정 변경에서 원하는 설정을 할 수 있습니다. 변경하지 않으면 쿠키를 허용하는 것으로 이해합니다.