Catatan: Silakan lihat jawaban lain karena mengandung teknik yang sangat berharga. Jawaban saya di sini hanya memberikan peringatan dan peringatan agar tidak mengasumsikan kesadaran DPI itu mudah.
Saya biasanya menghindari penskalaan yang sadar DPI TForm.Scaled = True
. Kesadaran DPI hanya penting bagi saya ketika menjadi penting bagi pelanggan yang menelepon saya dan bersedia membayarnya. Alasan teknis di balik sudut pandang itu adalah bahwa kesadaran DPI atau tidak, Anda membuka jendela ke dunia yang terluka. Banyak kontrol VCL standar dan pihak ketiga tidak berfungsi dengan baik di DPI Tinggi. Pengecualian penting bahwa bagian VCL yang membungkus Windows Common Control bekerja sangat baik pada DPI tinggi. Sejumlah besar pihak ketiga dan kontrol kustom Delphi VCL built-in tidak berfungsi dengan baik, atau sama sekali, pada DPI tinggi. Jika Anda berencana untuk mengaktifkan TForm.Scaled pastikan untuk menguji pada 96, 125, dan 150 DPI untuk setiap formulir dalam proyek Anda, dan setiap pihak ketiga dan kontrol bawaan yang Anda gunakan.
Delphi sendiri ditulis dalam bahasa Delphi. Bendera kesadaran DPI Tinggi telah diaktifkan, untuk sebagian besar formulir, meskipun baru-baru ini seperti di Delphi XE2, pembuat IDE sendiri memutuskan untuk TIDAK mengaktifkan tanda manifes Kesadaran DPI Tinggi itu. Perhatikan bahwa di Delphi XE4 dan yang lebih baru, flag kesadaran DPI TINGGI diaktifkan, dan IDE terlihat bagus.
Saya menyarankan agar Anda tidak menggunakan TForm.Scaled = true (yang merupakan default di Delphi jadi kecuali Anda telah memodifikasinya, sebagian besar formulir Anda memiliki Scaled = true) dengan flag High DPI Aware (seperti yang ditunjukkan dalam jawaban David) dengan Aplikasi VCL yang dibangun menggunakan desainer bentuk delphi built-in.
Saya telah mencoba di masa lalu untuk membuat sampel minimal dari jenis kerusakan yang dapat Anda lihat saat TForm.Scaled benar, dan saat penskalaan bentuk Delphi mengalami kesalahan. Gangguan ini tidak selalu dan hanya dipicu oleh nilai DPI selain 96. Saya tidak dapat menentukan daftar lengkap hal-hal lain, yang mencakup perubahan ukuran font Windows XP. Tetapi karena sebagian besar gangguan ini hanya muncul di aplikasi saya sendiri, dalam situasi yang cukup kompleks, saya memutuskan untuk menunjukkan beberapa bukti yang dapat Anda verifikasi sendiri.
Delphi XE terlihat seperti ini saat Anda menyetel DPI Scaling ke "Fonts @ 200%" di Windows 7, dan Delphi XE2 juga rusak pada Windows 7 dan 8, tetapi gangguan ini tampaknya telah diperbaiki pada Delphi XE4:
Ini sebagian besar adalah kontrol VCL Standar yang berperilaku buruk pada DPI tinggi. Perhatikan bahwa kebanyakan hal belum diskalakan sama sekali, sehingga pengembang Delphi IDE telah memutuskan untuk mengabaikan kesadaran DPI, serta mematikan virtualisasi DPI. Pilihan yang sangat menarik.
Matikan virtualisasi DPI hanya jika menginginkan sumber rasa sakit tambahan baru ini, dan pilihan yang sulit. Saya sarankan Anda biarkan saja. Perhatikan bahwa kontrol umum Windows sebagian besar tampaknya berfungsi dengan baik. Perhatikan bahwa kontrol penjelajah data Delphi adalah pembungkus C # WinForms di sekitar kontrol umum Windows Tree standar. Itu kesalahan microsoft murni, dan memperbaikinya mungkin memerlukan Embarcadero untuk menulis ulang kontrol pohon Net asli asli untuk penjelajah data mereka, atau untuk menulis beberapa kode DPI-periksa-dan-ubah-properti untuk mengubah ketinggian item dalam kontrol. Bahkan Microsoft WinForms tidak dapat menangani DPI tinggi dengan bersih, otomatis dan tanpa kode kludge khusus.
Pembaruan: Factoid yang menarik: Meskipun delphi IDE tampaknya tidak "divirtualisasi", ia tidak menggunakan konten manifes yang ditunjukkan oleh David untuk mencapai "non-DPI-virtualisasi". Mungkin itu menggunakan beberapa fungsi API saat runtime.
Pembaruan 2: Menanggapi bagaimana saya akan mendukung 100% / 125% DPI, saya akan membuat rencana dua fase. Tahap 1 adalah menginventarisir kode saya untuk kontrol khusus yang perlu diperbaiki untuk DPI tinggi, dan kemudian membuat rencana untuk memperbaikinya atau menghentikannya secara bertahap. Tahap 2 akan mengambil beberapa area kode saya yang dirancang sebagai formulir tanpa manajemen tata letak dan mengubahnya menjadi formulir yang menggunakan beberapa jenis manajemen tata letak sehingga DPI atau perubahan ketinggian font dapat bekerja tanpa pemotongan. Saya menduga bahwa pekerjaan tata letak "antar-kontrol" ini akan jauh lebih kompleks di sebagian besar aplikasi daripada pekerjaan "intra-kontrol".
Pembaruan: Pada tahun 2016, Delphi 10.1 Berlin terbaru bekerja dengan baik di workstation 150 dpi saya.
SetProcessDPIAware
.Pengaturan Anda di file .dfm akan ditingkatkan dengan benar, selama
Scaled
ituTrue
.Jika Anda menetapkan dimensi dalam kode, maka Anda perlu menskalakannya dengan
Screen.PixelsPerInch
dibagiForm.PixelsPerInch
. GunakanMulDiv
untuk melakukan ini.Ini adalah apa bentuk ketekunan kerangka lakukan saat
Scaled
iniTrue
.Faktanya, Anda dapat membuat argumen yang meyakinkan untuk mengganti fungsi ini dengan versi yang mengkodekan nilai 96 untuk penyebutnya. Hal ini memungkinkan Anda untuk menggunakan nilai dimensi absolut dan tidak khawatir tentang perubahan artinya jika Anda kebetulan mengubah penskalaan font di mesin pengembangan dan menyimpan ulang file .dfm. Alasan yang penting adalah bahwa
PixelsPerInch
properti yang disimpan dalam file .dfm adalah nilai mesin tempat file .dfm terakhir disimpan.Jadi, melanjutkan tema, hal lain yang harus diperhatikan adalah jika proyek Anda dikembangkan pada beberapa mesin dengan nilai DPI yang berbeda, Anda akan menemukan bahwa penskalaan yang digunakan Delphi saat menyimpan file .dfm menghasilkan kontrol yang berkeliaran di serangkaian pengeditan. . Di tempat kerja saya, untuk menghindari hal ini, kami memiliki kebijakan ketat bahwa formulir hanya diedit pada 96dpi (penskalaan 100%).
Bahkan, versi saya
ScaleFromSmallFontsDimension
juga memberikan kelonggaran untuk kemungkinan font bentuk berbeda saat runtime dari yang ditetapkan pada waktu desain. Pada mesin XP, formulir aplikasi saya menggunakan Tahoma 8pt. Pada Vista dan 9pt Segoe UI digunakan. Ini memberikan derajat kebebasan yang lain. Penskalaan harus memperhitungkan hal ini karena nilai dimensi absolut yang digunakan dalam kode sumber diasumsikan relatif terhadap garis dasar Tahoma 8pt pada 96dpi.Jika Anda menggunakan gambar atau mesin terbang apa pun di UI Anda, maka ini juga perlu diskalakan. Contoh umum adalah mesin terbang yang digunakan pada bilah alat dan menu. Anda akan ingin menyediakan mesin terbang ini sebagai sumber daya ikon yang ditautkan ke executable Anda. Setiap ikon harus berisi berbagai ukuran dan kemudian pada waktu proses Anda memilih ukuran yang paling sesuai dan memuatnya ke dalam daftar gambar. Beberapa detail tentang topik tersebut dapat ditemukan di sini: Bagaimana cara memuat ikon dari sumber daya tanpa mengalami aliasing?
Trik berguna lainnya adalah untuk menentukan dimensi dalam unit relatif, relatif terhadap
TextWidth
atauTextHeight
. Jadi, jika Anda ingin sesuatu berukuran sekitar 10 garis vertikal, Anda dapat menggunakan10*Canvas.TextHeight('Ag')
. Ini adalah metrik yang sangat kasar dan siap karena tidak memungkinkan adanya spasi baris dan sebagainya. Namun, seringkali yang perlu Anda lakukan hanyalah dapat mengatur agar GUI dapat diskalakan dengan benarPixelsPerInch
.Anda juga harus menandai aplikasi Anda sebagai aplikasi dengan DPI tinggi . Cara terbaik untuk melakukannya adalah melalui manifes aplikasi. Karena alat build Delphi tidak mengizinkan Anda menyesuaikan manifes yang Anda gunakan, ini memaksa Anda untuk menautkan sumber daya manifes Anda sendiri.
Skrip sumber daya terlihat seperti ini:
dimana
Manifest.txt
berisi manifes sebenarnya. Anda juga perlu memasukkan bagian comctl32 v6 dan mengaturrequestedExecutionLevel
keasInvoker
. Anda kemudian menautkan sumber daya yang dikompilasi ini ke aplikasi Anda dan memastikan bahwa Delphi tidak mencoba melakukan hal yang sama dengan manifesnya. Dalam Delphi modern, Anda dapat mencapainya dengan menyetel opsi proyek Tema Waktu Proses ke Tidak Ada.Manifes adalah cara yang tepat untuk mendeklarasikan aplikasi Anda sebagai aplikasi dengan DPI tinggi. Jika Anda hanya ingin mencobanya dengan cepat tanpa mengotak-atik manifes Anda, hubungi
SetProcessDPIAware
. Lakukan itu sebagai hal pertama yang Anda lakukan saat aplikasi Anda berjalan. Lebih disukai di salah satu bagian inisialisasi unit awal, atau sebagai hal pertama dalam file .dpr Anda.Jika Anda tidak mendeklarasikan aplikasi Anda sebagai DPI yang tinggi, maka Vista dan yang lebih baru akan menampilkannya dalam mode lama untuk semua font yang diskalakan di atas 125%. Ini terlihat sangat mengerikan. Cobalah untuk menghindari jatuh ke dalam jebakan itu.
Pembaruan DPI Windows 8.1 per monitor
Mulai Windows 8.1, sekarang ada dukungan OS untuk pengaturan DPI per monitor ( http://msdn.microsoft.com/en-ca/magazine/dn574798.aspx ). Ini adalah masalah besar untuk perangkat modern yang mungkin memiliki layar berbeda yang terpasang dengan kemampuan yang sangat berbeda. Anda mungkin memiliki layar laptop DPI sangat tinggi, dan proyektor eksternal DPI rendah. Mendukung skenario seperti itu membutuhkan lebih banyak pekerjaan daripada yang dijelaskan di atas.
sumber
Penting juga untuk diperhatikan bahwa menghormati DPI pengguna hanyalah sebagian dari pekerjaan Anda yang sebenarnya:
Selama beberapa dekade, Windows telah memecahkan masalah ini dengan gagasan melakukan tata letak menggunakan Dialog Units , bukan piksel. Sebuah "unit dialog" didefinisikan sehingga karakter rata - rata font adalah
Delphi memang dikirimkan dengan gagasan (buggy)
Scaled
, di mana formulir mencoba untuk menyesuaikan secara otomatis berdasarkanItu tidak menyelesaikan masalah ketika pengguna menggunakan font yang berbeda dari yang Anda desain formulir dengan, misalnya:
6.21px x 13.00px
, pada 96dpi)pengguna menjalankan Tahoma 8pt (di mana karakter rata-rata
5.94px x 13.00px
, pada 96dpi)Seperti halnya dengan siapa pun yang mengembangkan aplikasi untuk Windows 2000 atau Windows XP.
atau
5.94px x 13.00px
, pada 96dpi)6.67px x 15px
, pada 96dpi)Sebagai pengembang yang baik, Anda akan menghormati preferensi font pengguna Anda. Ini berarti Anda juga perlu menskalakan semua kontrol pada formulir Anda agar sesuai dengan ukuran font baru:
Scaled
tidak akan menangani ini untuk Anda.Ini menjadi lebih buruk ketika:
10.52px x 25px
Sekarang Anda harus mengukur semuanya
Scaled
tidak akan menangani ini untuk Anda.Jika Anda pintar, Anda dapat melihat betapa menghormati DPI tidak relevan:
Anda tidak boleh melihat pengaturan DPI pengguna, Anda harus melihat ukuran fontnya . Dua pengguna berjalan
menjalankan font yang sama . DPI hanyalah satu hal yang mempengaruhi ukuran font; preferensi pengguna adalah yang lain.
StandardizeFormFont
Clovis memperhatikan bahwa saya mereferensikan fungsi
StandardizeFormFont
yang memperbaiki font pada formulir, dan menskalakannya ke ukuran font baru. Ini bukan fungsi standar, tapi seluruh rangkaian fungsi yang menyelesaikan tugas sederhana yang tidak pernah ditangani Borland.Windows memiliki 6 font berbeda; tidak ada "pengaturan font" tunggal di Windows.
Tapi kita tahu dari pengalaman bahwa formulir kita harus mengikuti pengaturan Font Judul Ikon
Setelah kita mengetahui ukuran font kita akan skala bentuk untuk , kita mendapatkan tinggi font saat form ( dalam pixel ), dan skala oleh faktor itu.
Misalnya, jika saya menyetel formulir ke
-16
, dan formulir saat ini di-11
, maka kita perlu menskalakan seluruh formulir dengan:Standarisasi terjadi dalam dua tahap. Pertama, skala formulir dengan rasio ukuran font baru: lama. Kemudian ubah kontrol (secara rekursif) untuk menggunakan font baru.
Inilah tugas untuk benar-benar menskalakan formulir. Ia bekerja di sekitar bug dalam
Form.ScaleBy
metode Borland sendiri . Pertama, ia harus menonaktifkan semua jangkar di formulir, lalu melakukan penskalaan, lalu mengaktifkan kembali jangkar:dan kemudian kita harus benar-benar menggunakan font baru secara rekursif :
Dengan jangkar dinonaktifkan secara rekursif:
Dan jangkar diaktifkan kembali secara rekursif:
Dengan pekerjaan benar-benar mengubah font kontrol kiri menjadi:
Itu jauh lebih banyak kode daripada yang Anda kira; aku tahu. Yang menyedihkan adalah tidak ada pengembang Delphi di dunia, kecuali saya, yang benar-benar membuat aplikasinya benar.
sumber
Ini hadiah saya. Sebuah fungsi yang dapat membantu Anda dengan posisi horizontal elemen dalam tata letak GUI Anda. Gratis untuk semua.
sumber