Mixed-Mode DPI Scaling dan API yang sadar DPI

Sub-Process Dukungan Kesadaran DPI

SetThreadDpiAwarenessContext memungkinkan penggunaan mode penskalaan DPI yang berbeda dalam satu proses. Sebelum Windows 10 Anniversary Update, kesadaran DPI window s terikat dengan mode kesadaran DPI di seluruh proses (tidak menyadari DPI, sadar DPI Sistem, atau Per-Monitor sadar DPI). Tetapi sekarang, dengan SetThreadDpiAwarenessContext, jendela tingkat atas dapat memiliki mode kesadaran DPI yang berbeda dari mode kesadaran DPI di seluruh proses. Ini juga mempengaruhi jendela anak, karena mereka akan selalu memiliki mode kesadaran DPI yang sama dengan jendela induk mereka.

Penggunaan SetThreadDpiAwarenessContext memungkinkan pengembang memutuskan di mana mereka ingin memfokuskan upaya pengembangan mereka saat menentukan perilaku khusus DPI untuk aplikasi desktop. Misalnya, jendela tingkat atas utama aplikasi dapat diskalakan per monitor sementara jendela tingkat atas sekunder dapat diskalakan melalui penskalaan bitmap oleh sistem operasi.

Konteks Kesadaran DPI

Sebelum ketersediaan SetThreadDpiAwarenessContext kesadaran DPI tentang proses ditentukan baik dalam manifes biner aplikasi atau melalui panggilan ke SetProcessDpiAwareness selama inisialisasi proses. Dengan SetThreadDpiAwarenessContext, setiap utas dapat memiliki konteks kesadaran DPI individual yang mungkin berbeda dari mode kesadaran DPI di seluruh proses. Konteks kesadaran DPI dari utas diwakili dengan jenis DPI_AWARENESS_CONTEXT , dan berperilaku dengan cara berikut:

  • Utas dapat mengubah konteks kesadaran DPI-nya kapan saja.
  • Setiap panggilan API yang dilakukan setelah konteks diubah akan berjalan dalam konteks DPI yang sesuai (dan dapat divirtualisasi).
  • Ketika jendela dibuat, kesadaran DPI-nya didefinisikan sebagai kesadaran DPI tentang utas panggilan pada saat itu.
  • Ketika prosedur jendela untuk jendela dipanggil, utas secara otomatis dialihkan ke konteks kesadaran DPI yang digunakan saat jendela dibuat.

Skenario umum untuk penggunaan SetThreadDpiAwarenessContext adalah sebagai berikut: Mulailah dengan utas yang berjalan dengan satu konteks (seperti DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE) untuk sementara beralih ke konteks yang berbeda (DPI_AWARENESS_CONTEXT_UNAWARE), membuat jendela, lalu segera mengalihkan konteks utas kembali ke status sebelumnya. Jendela yang dibuat akan memiliki konteks DPI DPI_AWARENESS_CONTEXT_UNAWARE, sementara konteks alur panggilan akan dipulihkan ke DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE dengan panggilan berikutnya ke SetThreadDpiAwarenessContext. Dalam skenario ini, jendela yang terkait dengan utas panggilan akan berjalan dengan konteks per monitor (dan karenanya tidak direntangkan bitmap oleh sistem operasi) sementara jendela yang baru dibuat tidak akan sadar DPI (dan oleh karena itu akan secara otomatis bitmap direntangkan pada tampilan yang diatur ke >penskalaan 100%).

Gambar 1 menggambarkan bagaimana utas proses utama dijalankan dengan DPI_AWARENESS_CONTEXT_PER_MONITOR, mengalihkan konteksnya ke DPI_AWARENESS_CONTEXT_UNAWARE, dan membuat jendela baru. Jendela yang baru dibuat kemudian dijalankan dengan konteks kesadaran DPI DPI_AWARENESS_CONTEXT_UNAWARE setiap kali pesan dikirim ke dalamnya atau panggilan API dilakukan darinya. Segera setelah membuat jendela baru, utas utama dipulihkan ke konteks DPI_AWARENESS_CONTEXT_PER_MONITOR sebelumnya.

diagram memperlihatkan kesadaran dpi per monitor dalam tindakan

Selain dukungan untuk mode kesadaran DPI yang berbeda dalam satu proses yang ditawarkan SetThreadDpiAwarenessContext , fungsionalitas khusus DPI berikut telah ditambahkan untuk aplikasi desktop:

EnablenonClientDpiscaling

Catatan

Mode kesadaran Per Monitor V2 DPI secara otomatis mengaktifkan fungsionalitas ini, dan memanggil EnableNonClientDpiScaling karena itu tidak perlu dalam aplikasi yang menggunakannya.

Memanggil EnableNonClientDpiScaling dari dalam handler WM_NCCREATE jendela akan mengakibatkan area non-klien dari jendela tingkat atas secara otomatis menskalakan untuk DPI. Jika jendela tingkat atas sadar DPI per monitor (baik karena proses itu sendiri sadar DPI per monitor atau karena jendela dibuat dalam utas sadar DPI per monitor), bilah caption, bilah gulir, menu, dan bilah menu jendela ini akan diskalakan DPI setiap kali DPI jendela berubah.

Perhatikan bahwa area non-klien dari jendela anak, seperti bilah gulir non-klien kontrol pengeditan anak, tidak akan menskalakan DPI secara otomatis saat API ini digunakan.

Catatan

EnableNonClientDpiScaling harus dipanggil dari handler WM_NCCREATE .

API *ForDpi
  • Beberapa API yang sering digunakan seperti GetSystemMetrics tidak memiliki konteks HWND dan karenanya tidak memiliki cara untuk mengurangi kesadaran DPI yang tepat untuk nilai pengembaliannya. Memanggil API ini dari utas yang berjalan dalam mode atau konteks kesadaran DPI yang berbeda dapat mengembalikan nilai yang tidak diskalakan untuk konteks utas panggilan. GetSystemMetricForDpi, SystemParametersInfoForDpi, dan AdjustWindowRectExForDpi akan melakukan fungsionalitas yang sama seperti rekan tidak sadar DPI mereka, tetapi mengambil DPI sebagai argumen dan menyimpulkan kesadaran dpi dari konteks utas saat ini.

  • GetSystemMetricForDpi dan SystemParametersInfoForDpi akan mengembalikan nilai metrik sistem berskala DPI dan nilai parameter sistem sesuai dengan persamaan ini:

    GetSystemMetrics(...) @ dpi == GetSystemMetricsForDpi(..., dpi)

    Oleh karena itu, memanggil GetSystemMetrics (atau SystemParametersInfoForDpi), saat berjalan pada perangkat dengan nilai DPI sistem tertentu akan mengembalikan nilai yang sama dengan varian sadar DPI mereka (GetSystemMetricsForDpi dan SystemParametersInfoForDpi) akan, mengingat nilai DPI yang sama dengan input.

  • AdjustWindowRectExForDpi mengambil HWND dan akan menghitung ukuran persegi panjang jendela yang diperlukan dengan cara yang sensitif terhadap DPI.

GetDpiForWindow
GetDpiForWindow akan mengembalikan DPI yang terkait dengan HWND yang disediakan. Jawabannya akan tergantung pada mode kesadaran DPI HWND:
Mode Kesadaran DPI HWND Nilai kembali
Menyadari 96
Sistem DPI sistem
Per-Monitor DPI tampilan tempat jendela tingkat atas terkait berada di
(Jika jendela anak disediakan, DPI dari jendela induk tingkat atas yang sesuai akan dikembalikan)
GetDpiForSystem

Memanggil GetDpiForSystem lebih efisien daripada memanggil GetDC dan GetDeviceCaps untuk mendapatkan DPI sistem.

Komponen apa pun yang dapat berjalan dalam aplikasi yang menggunakan kesadaran DPI sub-proses tidak boleh berasumsi bahwa DPI sistem statis selama siklus hidup proses. Misalnya, jika utas yang berjalan di bawah konteks kesadaran DPI_AWARENESS_CONTEXT_UNAWARE mengkueri DPI sistem, jawabannya adalah 96. Namun, jika utas yang sama beralih ke konteks kesadaran DPI_AWARENESS_CONTEXT_SYSTEM dan mengkueri DPI sistem lagi, jawabannya bisa berbeda. Untuk menghindari penggunaan nilai DPI sistem cache (dan mungkin kedaluwarsa), gunakan GetDpiForSystem untuk mengambil DPI sistem relatif terhadap mode kesadaran DPI dari utas panggilan.