Pengembangan Aplikasi Desktop DPI Tinggi di Windows

Konten ini ditujukan bagi pengembang yang ingin memperbarui aplikasi desktop agar dapat menangani perubahan faktor skala tampilan (titik per inci, atau DPI) secara dinamis, sehingga aplikasi tetap terlihat tajam di layar apa pun tempat aplikasi tersebut dirender.

Untuk memulai, jika Anda membuat aplikasi Windows baru dari awal, sangat disarankan agar Anda membuat aplikasi Universal Windows Platform (UWP). Aplikasi UWP secara otomatis—dan dinamis—menskalakan untuk setiap tampilan yang dijalankan.

Aplikasi desktop yang menggunakan teknologi pemrograman Windows yang lebih lama (pemrograman Win32 mentah, Formulir Windows, Windows Presentation Framework (WPF), dll.) tidak dapat menangani penskalakan DPI secara otomatis tanpa pekerjaan pengembang tambahan. Tanpa pekerjaan seperti itu, aplikasi akan tampak buram atau berukuran salah dalam banyak skenario penggunaan umum. Dokumen ini memberikan konteks dan informasi mengenai hal-hal yang perlu dilakukan untuk memperbarui aplikasi desktop agar dapat ditampilkan dengan benar.

Faktor Skala Tampilan & DPI

Seiring kemajuan teknologi tampilan, produsen panel tampilan telah mengemas peningkatan jumlah piksel ke dalam setiap unit ruang fisik pada panel mereka. Hal ini mengakibatkan kerapatan piksel per inci (DPI) pada panel layar modern menjadi jauh lebih tinggi dibandingkan sebelumnya. Sebelumnya, sebagian besar layar memiliki 96 piksel per inci ruang fisik linier (96 DPI); pada tahun 2017, tampilan dengan hampir 300 DPI atau lebih tinggi tersedia.

Sebagian besar kerangka kerja antarmuka pengguna desktop warisan memiliki asumsi bawaan bahwa DPI tampilan tidak akan berubah selama masa pakai proses. Asumsi ini tidak lagi berlaku, dengan DPI tampilan yang umumnya berubah beberapa kali sepanjang masa pakai proses aplikasi. Beberapa skenario umum di mana faktor skala tampilan/perubahan DPI adalah:

  • Penyiapan multi-monitor di mana setiap tampilan memiliki faktor skala yang berbeda dan aplikasi dipindahkan dari satu tampilan ke tampilan lain (seperti 4K dan tampilan 1080p)
  • Menyambungkan dan melepaskan sambungan laptop ber-DPI tinggi dengan layar eksternal ber-DPI rendah (atau sebaliknya)
  • Menyambungkan melalui Desktop Jauh dari laptop/tablet DPI tinggi ke perangkat DPI rendah (atau sebaliknya)
  • Membuat pengaturan faktor skala tampilan berubah saat aplikasi sedang berjalan

Dalam skenario ini, aplikasi UWP menggambar ulang dirinya sendiri untuk DPI baru secara otomatis. Secara bawaan, dan tanpa upaya tambahan dari pengembang, aplikasi desktop tidak. Aplikasi desktop yang tidak melakukan pekerjaan ekstra ini untuk merespons perubahan DPI mungkin tampak buram atau berukuran salah kepada pengguna.

Mode Kesadaran DPI

Aplikasi desktop harus memberi tahu Windows jika mendukung penskalakan DPI. Secara bawaan, sistem menganggap aplikasi desktop tidak mendukung DPI dan meregangkan jendelanya sebagai bitmap. Dengan mengatur salah satu mode kesadaran DPI yang tersedia berikut, aplikasi dapat secara eksplisit memberi tahu Windows bagaimana mereka ingin menangani penskalaan DPI:

Tidak Mendukung DPI

Aplikasi yang tidak mendukung DPI ditampilkan pada nilai DPI tetap, yaitu 96 (100%). Setiap kali aplikasi ini dijalankan pada layar dengan skala tampilan yang lebih besar dari 96 DPI, Windows akan meregangkan bitmap aplikasi ke ukuran fisik yang diharapkan. Ini menghasilkan aplikasi yang tampak buram.

Kesadaran DPI Sistem

Aplikasi desktop yang mengenali DPI sistem biasanya menerima DPI monitor utama yang terhubung pada saat pengguna masuk ke sistem. Selama inisialisasi, mereka menjabarkan UI mereka dengan tepat (kontrol ukuran, memilih ukuran font, memuat aset, dll.) menggunakan nilai DPI Sistem tersebut. Dengan demikian, aplikasi yang DPI-aware terhadap Sistem tidak dikenai penskalaan DPI (bitmap diregangkan) oleh Windows pada layar yang dirender pada DPI tunggal tersebut. Ketika aplikasi dipindahkan ke layar dengan faktor skala yang berbeda, atau jika faktor skala layar berubah, Windows akan menskalakan jendela aplikasi sebagai bitmap, sehingga tampilannya tampak kabur. Pada dasarnya, aplikasi desktop yang sadar terhadap DPI sistem hanya ditampilkan dengan tajam pada satu faktor skala layar, dan akan menjadi buram setiap kali DPI berubah.

kesadaran DPI Per-Monitor dan Per-Monitor (V2)

Disarankan agar aplikasi desktop diperbarui untuk menggunakan mode sadar DPI per monitor, sehingga dapat langsung ditampilkan dengan benar setiap kali DPI berubah. Ketika aplikasi melaporkan ke Windows bahwa aplikasi ingin berjalan dalam mode ini, Windows tidak akan meregangkan bitmap aplikasi ketika DPI berubah, sebagai gantinya mengirim WM_DPICHANGED ke jendela aplikasi. Setelah itu, aplikasi sepenuhnya bertanggung jawab untuk menangani penyesuaian ukurannya sendiri agar sesuai dengan DPI baru. Sebagian besar kerangka kerja UI yang digunakan oleh aplikasi desktop (Windows kontrol umum (comctl32), Formulir Windows, Windows Presentation Framework, dll.) tidak mendukung penskalaan DPI otomatis, mengharuskan pengembang untuk mengubah ukuran dan memposisikan ulang konten jendela mereka sendiri.

Ada dua versi kesadaran Per-Monitor bahwa aplikasi dapat mendaftarkan dirinya sebagai: versi 1 dan versi 2 (PMv2). Mendaftarkan proses untuk berjalan dalam mode kesadaran PMv2 akan menghasilkan hal berikut:

  1. Aplikasi menerima pemberitahuan ketika DPI berubah (baik HWND tingkat atas maupun HWND anak)
  2. Aplikasi melihat piksel mentah dari setiap tampilan
  3. Aplikasi tidak pernah diskalakan sebagai bitmap oleh Windows
  4. Area non-klien otomatis (keterangan jendela, bilah gulir, dll.) Penskalakan DPI dengan Windows
  5. Dialog Win32 (dari CreateDialog) yang secara otomatis diskalakan oleh Windows berdasarkan DPI
  6. Aset bitmap yang digambar tema dalam kontrol umum (kotak centang, latar belakang tombol, dll.) secara otomatis dirender pada faktor skala DPI yang sesuai

Saat berjalan dalam mode kesadaran Per-Monitor v2, aplikasi akan diberi tahu ketika DPI mereka telah berubah. Jika aplikasi tidak mengubah ukuran dirinya sendiri untuk DPI baru, antarmuka pengguna aplikasi akan tampak terlalu kecil atau terlalu besar (tergantung pada perbedaan nilai DPI sebelumnya dan baru).

Note

Dukungan Per-Monitor V1 (PMv1) sangat terbatas. Disarankan agar aplikasi menggunakan PMv2.

Tabel berikut menunjukkan bagaimana aplikasi akan dirender dalam skenario yang berbeda:

Mode Kesadaran DPI Versi Windows Diperkenalkan Tampilan aplikasi DPI Perilaku pada perubahan DPI
Tidak sadar N/A Semua tampilan adalah 96 DPI Peregangan gambar bitmap (buram)
System Vista Semua tampilan memiliki DPI yang sama (DPI tampilan utama pada saat sesi pengguna saat ini dimulai) Peregangan bitmap (kabur)
Per-Monitor 8.1 DPI tampilan tempat jendela aplikasi berada
  • HWND tingkat atas diberi tahu tentang perubahan DPI
  • Tidak ada penskalaan DPI dari elemen UI apa pun.

Per-Monitor V2 Windows 10 Creators Update (1703) DPI tampilan tempat jendela aplikasi berada
  • HWND tingkat atas dan anak diberi tahu tentang perubahan DPI

Penskalaan DPI secara otomatis untuk:
  • Area nonklien
  • Bitmap yang digambar tema dalam kontrol umum (comctl32 V6)
  • Dialog (CreateDialog)

Per Monitor (V1) Kesadaran DPI

Mode kesadaran DPI Per-Monitor V1 (PMv1) diperkenalkan pada Windows 8.1. Mode kesadaran DPI ini sangat terbatas dan hanya menawarkan fungsionalitas yang tercantum di bawah ini. Disarankan agar aplikasi desktop menggunakan mode kesadaran Per-Monitor v2, yang didukung pada Windows 10 1703 atau lebih tinggi.

Dukungan awal untuk kesadaran tiap monitor hanya menyediakan hal-hal berikut bagi aplikasi:

  1. HWND tingkat teratas diberi tahu tentang perubahan DPI serta diberikan ukuran baru yang disarankan
  2. Windows tidak akan meregangkan bitmap antarmuka pengguna aplikasi
  3. Aplikasi melihat semua tampilan dalam piksel fisik (lihat virtualisasi)

Pada Windows 10 1607 atau lebih tinggi, aplikasi PMv1 juga dapat memanggil EnableNonClientDpiScaling selama WM_NCCREATE untuk meminta agar Windows menskalakan area non-klien jendela dengan benar.

Dukungan Penskalaan DPI per Monitor berdasarkan Kerangka Kerja/Teknologi UI

Tabel di bawah ini menunjukkan tingkat dukungan kesadaran DPI per monitor yang ditawarkan oleh berbagai kerangka kerja UI Windows per Windows 10 1703:

Kerangka Kerja / Teknologi Support Versi OS Penskalan DPI yang ditangani oleh Bacaan Lebih Lanjut
Universal Windows Platform (UWP) Penuh 1607 Kerangka kerja UI Universal Windows Platform (UWP)
Win32 Mentah/Kontrol Umum V6 (comctl32.dll)
  • DPI mengubah pesan pemberitahuan yang dikirim ke semua HWND
  • Aset yang digambar oleh tema tampil dengan benar dalam kontrol standar
  • Penskalaan DPI otomatis untuk dialog
1703 Application Sampel GitHub
Formulir Windows Penskalaan DPI per monitor otomatis terbatas untuk beberapa kontrol 1703 Kerangka kerja UI Dukungan High DPI di Formulir Windows
Kerangka Kerja Presentasi Windows (WPF) Aplikasi WPF native akan diskalakan menurut DPI; WPF yang dihosting dalam kerangka kerja lain dan kerangka kerja lain yang dihosting dalam WPF tidak akan diskalakan secara otomatis 1607 Kerangka kerja UI Sampel GitHub
GDI None N/A Application Lihat Penskalaan GDI High-DPI
GDI+ None N/A Application Lihat Penskalaan GDI High-DPI
MFC None N/A Application N/A

Memperbarui Aplikasi yang Ada

Untuk memperbarui aplikasi desktop yang ada untuk menangani penskalaan DPI dengan benar, aplikasi ini perlu diperbarui sehingga, minimal, bagian penting dari UI-nya diperbarui untuk merespons perubahan DPI.

Kebanyakan aplikasi desktop berjalan dalam mode kesadaran DPI tingkat sistem. Aplikasi yang sadar DPI sistem biasanya menyesuaikan skala ke DPI layar utama (layar tempat area notifikasi berada saat sesi Windows dimulai). Ketika DPI berubah, Windows akan meregangkan antarmuka pengguna aplikasi-aplikasi ini dalam bentuk bitmap, yang sering mengakibatkan tampilannya menjadi buram. Saat memperbarui aplikasi yang mendukung DPI sistem agar menjadi mendukung DPI per monitor, kode yang menangani tata letak UI perlu diperbarui agar dijalankan tidak hanya selama inisialisasi aplikasi, tetapi juga setiap kali pemberitahuan perubahan DPI (WM_DPICHANGED pada Win32) diterima. Ini biasanya melibatkan meninjau kembali asumsi apa pun dalam kode yang menyatakan bahwa UI hanya perlu diskalakan satu kali.

Selain itu, dalam kasus pemrograman Win32, banyak API Win32 tidak memiliki DPI atau konteks tampilan sehingga mereka hanya akan mengembalikan nilai relatif terhadap DPI Sistem. Mungkin berguna untuk menelusuri kode Anda guna mencari beberapa API ini dan menggantinya dengan varian yang mendukung DPI. Beberapa API yang umum dan memiliki varian yang mendukung DPI adalah:

Versi DPI tunggal Versi per-monitor
GetSystemMetrics GetSystemMetricsForDpi
AdjustWindowRectEx AdjustWindowRectExForDpi
SystemParametersInfo SystemParametersInfoForDpi
GetDpiForMonitor GetDpiForWindow

Ada baiknya juga mencari ukuran yang dikodekan secara permanen di basis kode Anda yang mengasumsikan DPI konstanta, menggantinya dengan kode yang memperhitungkan penskalaan DPI dengan benar. Di bawah ini adalah contoh yang menggabungkan semua saran ini:

Contoh:

Contoh berikut memperlihatkan kasus Win32 yang disederhanakan untuk pembuatan HWND turunan. Panggilan ke CreateWindow mengasumsikan bahwa aplikasi berjalan pada 96 DPI (USER_DEFAULT_SCREEN_DPI konstanta), dan ukuran atau posisi tombol tidak akan benar pada DPI yang lebih tinggi:

case WM_CREATE: 
{ 
    // Add a button 
    HWND hWndChild = CreateWindow(L"BUTTON", L"Click Me",  
        WS_CHILD|WS_VISIBLE|BS_PUSHBUTTON,  
        50,  
        50,  
        100,  
        50,  
        hWnd, (HMENU)NULL, NULL, NULL); 
} 

Kode yang diperbarui di bawah ini menunjukkan:

  1. Kode pembuatan jendela DPI menskalakan posisi dan ukuran HWND anak untuk DPI jendela induknya
  2. Menanggapi perubahan DPI dengan memposisikan ulang dan mengubah ukuran HWND anak
  3. Ukuran yang dikodekan secara permanen dihapus dan diganti dengan kode yang merespons perubahan DPI
#define INITIALX_96DPI 50 
#define INITIALY_96DPI 50 
#define INITIALWIDTH_96DPI 100 
#define INITIALHEIGHT_96DPI 50 

// DPI scale the position and size of the button control 
void UpdateButtonLayoutForDpi(HWND hWnd) 
{ 
    int iDpi = GetDpiForWindow(hWnd); 
    int dpiScaledX = MulDiv(INITIALX_96DPI, iDpi, USER_DEFAULT_SCREEN_DPI); 
    int dpiScaledY = MulDiv(INITIALY_96DPI, iDpi, USER_DEFAULT_SCREEN_DPI); 
    int dpiScaledWidth = MulDiv(INITIALWIDTH_96DPI, iDpi, USER_DEFAULT_SCREEN_DPI); 
    int dpiScaledHeight = MulDiv(INITIALHEIGHT_96DPI, iDpi, USER_DEFAULT_SCREEN_DPI); 
    SetWindowPos(hWnd, hWnd, dpiScaledX, dpiScaledY, dpiScaledWidth, dpiScaledHeight, SWP_NOZORDER | SWP_NOACTIVATE); 
} 
 
... 
 
case WM_CREATE: 
{ 
    // Add a button 
    HWND hWndChild = CreateWindow(L"BUTTON", L"Click Me",  
        WS_CHILD|WS_VISIBLE|BS_PUSHBUTTON, 
        0, 
        0, 
        0, 
        0, 
        hWnd, (HMENU)NULL, NULL, NULL); 
    if (hWndChild != NULL) 
    { 
        UpdateButtonLayoutForDpi(hWndChild); 
    } 
} 
break; 
 
case WM_DPICHANGED: 
{ 
    // Find the button and resize it 
    HWND hWndButton = FindWindowEx(hWnd, NULL, NULL, NULL); 
    if (hWndButton != NULL) 
    { 
        UpdateButtonLayoutForDpi(hWndButton); 
    } 
} 
break; 

Saat memperbarui aplikasi yang peka terhadap DPI sistem, beberapa langkah umum yang perlu diikuti adalah:

  1. Tandai proses agar mendukung DPI per monitor (V2) melalui manifes aplikasi (atau metode lain, bergantung pada kerangka kerja UI yang digunakan).
  2. Buat logika tata letak UI dapat digunakan kembali dan pindahkan keluar dari kode inisialisasi aplikasi sehingga dapat digunakan kembali ketika perubahan DPI terjadi (WM_DPICHANGED dalam kasus pemrograman Windows (Win32).
  3. Membatalkan validasi kode apa pun yang mengasumsikan bahwa data sensitif DPI (DPI/font/ukuran/dll.) tidak perlu diperbarui. Ini adalah praktik yang sangat umum untuk menyimpan ukuran font dan nilai DPI pada inisialisasi proses. Saat memperbarui aplikasi untuk menjadi sadar DPI per monitor, data sensitif DPI harus dievaluasi ulang setiap kali DPI baru ditemui.
  4. Saat terjadi perubahan DPI, muat ulang (atau rasterisasi ulang) semua aset bitmap agar sesuai dengan DPI baru atau, sebagai opsi, ubah ukuran aset yang saat ini dimuat dengan peregangan bitmap ke ukuran yang sesuai.
  5. Cari API yang tidak mendukung DPI per monitor dan ganti dengan API yang mendukung DPI per monitor (jika berlaku). Contoh: ganti GetSystemMetrics dengan GetSystemMetricsForDpi.
  6. Uji aplikasi Anda pada sistem multi-tampilan/multi-DPI.
  7. Untuk jendela tingkat atas apa pun di aplikasi yang tidak dapat Anda perbarui untuk skala DPI dengan benar, gunakan penskalaan DPI mode campuran (dijelaskan di bawah) untuk memungkinkan peregangan bitmap dari jendela tingkat atas ini oleh sistem.

Penskalaan DPI Mode Campuran (Penskalaan DPI Subproses)

Saat memperbarui aplikasi untuk mendukung kesadaran DPI per monitor, terkadang dapat menjadi tidak praktis atau tidak mungkin untuk memperbarui setiap jendela dalam aplikasi sekaligus. Ini hanya bisa disebabkan oleh waktu dan upaya yang diperlukan untuk memperbarui dan menguji semua UI, atau karena Anda tidak memiliki semua kode UI yang perlu Anda jalankan (jika aplikasi Anda mungkin memuat UI pihak ketiga). Dalam situasi ini, Windows menawarkan cara untuk mempermudah transisi ke dunia kesadaran per-monitor dengan memungkinkan Anda menjalankan beberapa jendela aplikasi Anda (hanya jendela tingkat atas) dalam mode kesadaran DPI aslinya, sementara Anda memusatkan waktu dan tenaga untuk memperbarui bagian-bagian antarmuka pengguna Anda yang lebih penting.

Di bawah ini adalah ilustrasi yang menunjukkan seperti apa tampilannya: Anda memperbarui UI aplikasi utama ("Jendela Utama" pada ilustrasi) agar berjalan dalam mode sadar DPI per monitor, sementara jendela lain tetap berjalan dalam mode yang digunakan saat ini ("Jendela Sekunder").

perbedaan dalam penskalaan dpi antara mode kesadaran

Sebelum pembaruan Windows 10 Anniversary Update (1607), mode kesadaran DPI dari suatu proses merupakan properti yang berlaku untuk seluruh proses. Dimulai di Windows 10 Anniversary Update, properti ini sekarang dapat diatur per jendela tingkat atas. (Jendela turunan harus tetap sesuai dengan skala jendela induknya.) Jendela tingkat atas didefinisikan sebagai jendela yang tidak memiliki induk. Ini biasanya merupakan jendela "reguler" dengan tombol minimalkan, maksimalkan, dan tutup. Skenario yang ditujukan untuk kesadaran DPI sub-proses adalah memiliki UI sekunder yang diskalakan oleh Windows (bitmap direntangkan) saat Anda memfokuskan waktu dan sumber daya Anda untuk memperbarui UI utama Anda.

Untuk mengaktifkan kesadaran DPI sub-proses, panggil SetThreadDpiAwarenessContext sebelum dan sesudah panggilan pembuatan jendela apa pun. Jendela yang dibuat akan dikaitkan dengan kesadaran DPI yang Anda tetapkan melalui SetThreadDpiAwarenessContext. Gunakan panggilan kedua untuk memulihkan kesadaran DPI utas saat ini.

Meskipun penggunaan penskalaan DPI subproses memungkinkan Anda mengandalkan Windows untuk melakukan sebagian penskalaan DPI untuk aplikasi Anda, hal ini dapat meningkatkan kompleksitas aplikasi Anda. Penting bahwa Anda memahami kelemahan pendekatan ini dan sifat kompleksitas yang diperkenalkannya. Untuk informasi selengkapnya tentang kesadaran DPI subproses, lihat Penskalaan DPI mode campuran dan API yang sadar DPI.

Menguji Perubahan Anda

Setelah Anda memperbarui aplikasi agar mendukung DPI per monitor, penting untuk memvalidasi bahwa aplikasi Anda merespons perubahan DPI dengan benar dalam lingkungan dengan DPI campuran. Beberapa hal spesifik yang perlu diuji meliputi:

  1. Memindahkan jendela aplikasi bolak-balik antara tampilan nilai DPI yang berbeda
  2. Memulai aplikasi Anda pada tampilan nilai DPI yang berbeda
  3. Mengubah faktor skala untuk monitor Anda saat aplikasi sedang berjalan
  4. Mengubah tampilan yang Anda gunakan sebagai tampilan utama, keluar dari Windows, lalu menguji ulang aplikasi Anda setelah masuk kembali. Ini sangat berguna dalam menemukan kode yang menggunakan ukuran/dimensi yang dikodekan secara permanen.

Kesalahan Umum (Win32)

Tidak menggunakan persegi panjang yang disarankan yang disediakan dalam WM_DPICHANGED

Saat Windows mengirim pesan WM_DPICHANGED jendela aplikasi Anda, pesan ini menyertakan persegi panjang yang disarankan yang harus Anda gunakan untuk mengubah ukuran jendela Anda. Sangat penting bahwa aplikasi Anda menggunakan persegi panjang ini untuk mengubah ukurannya sendiri, karena ini akan:

  1. Pastikan bahwa kursor mouse akan tetap berada di posisi relatif yang sama pada Jendela saat menyeret antar tampilan
  2. Mencegah jendela aplikasi masuk ke siklus perubahan dpi rekursif di mana satu perubahan DPI memicu perubahan DPI berikutnya, yang memicu perubahan DPI lainnya.

Jika Anda memiliki persyaratan khusus aplikasi yang mencegah Anda menggunakan persegi panjang yang disarankan yang Windows sediakan dalam pesan WM_DPICHANGED, lihat WM_GETDPISCALEDSIZE. Pesan ini dapat digunakan untuk memberikan Windows ukuran yang diinginkan yang ingin Anda gunakan setelah perubahan DPI terjadi, sambil tetap menghindari masalah yang dijelaskan di atas.

Kurangnya dokumentasi tentang virtualisasi

Ketika HWND atau proses berjalan dalam mode tidak mendukung DPI atau mendukung DPI sistem, tampilannya dapat diperbesar dengan perentangan bitmap oleh Windows. Ketika ini terjadi, Windows menskalakan dan mengonversi informasi sensitif DPI dari beberapa API ke ruang koordinat utas panggilan. Misalnya, jika utas yang tidak sadar DPI mengkueri ukuran layar saat berjalan pada tampilan DPI tinggi, Windows akan memvirtualisasi jawaban yang diberikan kepada aplikasi seolah-olah layar berada di 96 unit DPI. Atau, ketika utas yang sadar DPI Sistem berinteraksi dengan tampilan di DPI yang berbeda dari yang digunakan ketika sesi pengguna saat ini dimulai, Windows akan menskalakan beberapa panggilan API ke ruang koordinat yang akan digunakan HWND jika berjalan pada faktor skala DPI aslinya.

Saat Anda memperbarui aplikasi desktop ke skala DPI dengan benar, mungkin sulit untuk mengetahui panggilan API mana yang dapat mengembalikan nilai virtual berdasarkan konteks utas; informasi ini saat ini tidak cukup didokumenkan oleh Microsoft. Perlu diketahui bahwa jika Anda memanggil API sistem apa pun dari konteks utas yang tidak mendukung DPI atau yang mendukung system DPI, nilai yang dikembalikan mungkin divirtualisasikan. Dengan demikian, pastikan utas Anda berjalan dalam konteks DPI yang Anda harapkan saat berinteraksi dengan layar atau masing-masing jendela. Saat mengubah konteks DPI utas untuk sementara menggunakan SetThreadDpiAwarenessContext, pastikan untuk memulihkan konteks lama setelah selesai agar tidak menyebabkan perilaku yang tidak semestinya di bagian lain aplikasi Anda.

Banyak API Windows tidak memiliki konteks DPI

Banyak API Windows warisan tidak menyertakan konteks DPI atau HWND sebagai bagian dari antarmuka mereka. Akibatnya, pengembang sering harus melakukan pekerjaan tambahan untuk menangani penskalaan informasi sensitif DPI apa pun, seperti ukuran, titik, atau ikon. Sebagai contoh, pengembang yang menggunakan LoadIcon harus meregangkan bitmap ikon yang dimuat atau menggunakan API alternatif untuk memuat ikon berukuran benar untuk DPI yang sesuai, seperti LoadImage.

Dimulai dengan Windows 11 (Build 22000), aplikasi yang membuat kursor dari data dalam memori dapat menggunakan SetThreadCursorCreationScaling untuk mengaktifkan penskalaan DPI per monitor otomatis, mirip dengan kursor yang dimuat dari sumber daya modul.

Pengaturan ulang paksa DPI awareness untuk seluruh proses

Secara umum, mode kesadaran terhadap DPI pada proses Anda tidak dapat diubah setelah inisialisasi proses. namun, Windows dapat mengubah secara paksa mode kesadaran DPI dari proses Anda jika Anda mencoba melanggar persyaratan bahwa semua HWND di pohon jendela memiliki mode kesadaran DPI yang sama. Di semua versi Windows, mulai Windows 10 versi 1703, tidak dimungkinkan untuk memiliki HWND yang berbeda dalam satu pohon HWND yang berjalan dalam mode kesadaran DPI yang berbeda-beda. Jika Anda mencoba membuat hubungan induk anak yang melanggar aturan ini, kesadaran DPI tentang seluruh proses dapat diatur ulang. Ini dapat dipicu oleh:

  1. Panggilan CreateWindow saat jendela induk yang diteruskan memiliki mode kesadaran DPI yang berbeda dari utas pemanggil.
  2. Panggilan SetParent ketika kedua jendela terkait dengan mode kesadaran DPI yang berbeda.

Tabel di bawah ini menunjukkan apa yang terjadi jika Anda mencoba melanggar aturan ini:

Pengoperasian Windows 8.1 Windows 10 (1607 dan yang lebih lama) Windows 10 (1703 dan yang lebih baru)
CreateWindow (In-Proc) N/A Anak mewarisi (mode campuran) Anak mewarisi (mode campuran)
CreateWindow (Cross-Proc) Atur ulang paksa (proses milik pemanggil) Anak mewarisi (mode campuran) Atur ulang paksa (dari proses pemanggil)
SetParent (In-Proc) N/A Reset paksa (dari proses saat ini) Gagal (ERROR_INVALID_STATE)
SetParent (Lintas-Proses) Setel ulang paksa (dari proses jendela anak) Setel ulang paksa (dari proses jendela anak) Setel ulang paksa (pada proses jendela anak)

Referensi API DPI Tinggi

Penskalaan DPI Mixed-Mode dan API yang mendukung DPI.