دعم DPI العالي في WinForms ── أسباب الضبابية والانهيار على شاشات 4K والمعالجة الواقعية
· آخر تحديث: · غو كومورا · WinForms, DPI العالي, Windows, .NET, C#, .NET Framework, صيانة الأنظمة القديمة, UI, الاستشارات التقنية
سجل التعديلات (2 تحديثات، آخر تحديث 2 Sep، 2026)
سجل بالتغييرات التي أُجريت على هذا المقال. وحيثما حُفظت نسخة سابقة، تبقى متاحة للقراءة عبر رابط دائم يحمل معرّف DOI.
- أُعيدَت الترجمة العربية كترجمة كاملة عن النص الياباني الأصلي، وأُضيفَت خريطة المعرفة.
- أعيدت الترجمة كترجمة كاملة عن النص الياباني الأصلي. كانت النسخة العربية السابقة مختصراً يسقط أبواباً وجداول ورسوم Mermaid وتعليقات الأشكال وFAQ. أُعيدت هذه العناصر وفق الأصل الياباني، والادّعاءات التقنية مطابقة للنسخة اليابانية.
- النشر الأول
الاستشهاد بهذا المقال(DOI: 10.5281/zenodo.21621605)
هذا المقال محفوظ على Zenodo. يرد أدناه معرّف DOI الذي يشير دائمًا إلى أحدث نسخة، ومعرّف DOI المثبَّت على النسخة التي تقرؤها.
غو كومورا (2026). دعم DPI العالي في WinForms ── أسباب الضبابية والانهيار على شاشات 4K والمعالجة الواقعية. شركة كومورا سوفت ذ.م.م.. https://doi.org/10.5281/zenodo.21621605 https://comcomponent.com/ar/blog/winforms-high-dpi-guide/
- DOI (أحدث نسخة)
- 10.5281/zenodo.21621605
- DOI (هذه النسخة)
- 10.5281/zenodo.22240990
«بعد استبدال الحاسوب المحمول الجديد، صار نص تطبيق الأعمال ضبابياً وصعب القراءة»، «بعد التوصيل بشاشة 4K تداخلت الأزرار والتسميات»، «تنهار معاينة التقرير فقط في بيئة العميل عند 125%». في السنوات الأخيرة تزايدت هذه الاستشارات بشدّة مع مواسم استبدال الحواسيب. أصبحت الشاشات عالية الدقة التي تتجاوز Full HD والتحجيم بين 125% و200% معياراً حتى في حواسيب العمل، فلم تعد تطبيقات WinForms التي صُمّمت في عصر 96 DPI وتحجيم 100% تُعرض بشكل مريح كما هي. وأصبح هذا، من واقع استشارات صيانة تطبيقات WinForms القديمة، أعلى المواضيع تردّداً حالياً.
المزعج أن الأعراض تبدو متفرّقة: «ضبابي»، «منهار»، «جزء صغير فقط». في الواقع يمكن ترتيب الأسباب في عدد قليل من الفئات، وحين تعرف أي عرض يقابل أي سبب يمكنك تحديد طريقة الإصلاح ومدى العمق المطلوب في المعالجة. في هذا المقال، وانطلاقاً من آلية تحجيم DPI في Windows وأوضاع إدراك DPI، نرتّب دعم DPI العالي في تطبيقات WinForms (.NET و.NET Framework كليهما): طريقة الضبط، والفخاخ النمطية، واستراتيجية المعالجة المرحلية، من منظور عملي.
المصطلحات المستخدمة في هذا المقال
قبل الخلاصة، نثبت المصطلحات التي تتكرّر في النص. نذكر أيضاً في أي فصل يُعالَج كل مصطلح، فعد إليه إن التبس المعنى.
| المصطلح | المعنى | التفصيل |
|---|---|---|
| DPI / تحجيم العرض | عدد النقاط في الإنش. 96 DPI تساوي 100%، و125% = 120 DPI، و150% = 144 DPI | الفصل 2 |
| DPI virtualization | إجراء إنقاذ: لنظام التشغيل يوهم التطبيق غير المعلن عن دعم DPI بأن «الشاشة 96 DPI» ثم يعرض النتيجة كصورة نقطية مكبّرة. لا ينهار التخطيط، لكن الشاشة كلّها تتلطّخ1 | الفصل 2 |
| وضع إدراك DPI | التصنيف الذي يعلن به التطبيق لنظام التشغيل «إلى أي حد يستطيع التعامل مع DPI». أربعة أوضاع: Unaware / System Aware / Per-Monitor / Per-Monitor V22 | الفصل 3 |
| System Aware | وضع «التكيّف مع DPI الشاشة الرئيسية عند تسجيل الدخول». واضح على الشاشة الرئيسية، وعند النقل إلى شاشة أخرى يكبّر نظام التشغيل فتتلطّخ | الفصل 3 |
| PMv2 | اختصار Per-Monitor V2. وضع يتابع DPI لكل شاشة. شريط العنوان والمناطق غير العميليّة يحجّمها نظام التشغيل تلقائياً2 | الفصل 3 |
| GDI scaling | نسخة محسّنة من تكبير الصورة النقطية: يبقى التطبيق Unaware، لكن النص والأشكال المرسومة عبر GDI يكبّرها نظام التشغيل على مستوى المتّجهات. يمكن تخفيف تلطّخ النص دون تغيير الشيفرة2 | الفصل 3 والقسم 4.3 |
| البيان (manifest) | XML يُضمَّن في الملف التنفيذي. أحد مواضع إعلان وضع إدراك DPI | الفصل 4 |
| AutoScaleMode | آلية تحجيم تلقائي يملكها نموذج WinForms نفسه، منفصلة عن وضع إدراك DPI | الفصل 5 |
1. الخلاصة أولاً
- ضبابية التطبيق القديم في بيئة DPI عالية ليست خللاً، بل إجراء إنقاذ من نظام التشغيل (DPI virtualization). Windows يرسم التطبيق غير الداعم لـ DPI بدقة 96 DPI ثم يكبّر النتيجة كصورة نقطية، فيبقى التخطيط سليماً مقابل التلطّخ.1
- والعكس، «واضح لكن التخطيط ينهار» يعني أن دعم DPI أُعلن لكن التخطيط لم يستطع المتابعة. أسباب الضبابية والانهيار معاكسة تماماً، فميّز أيّهما قبل المعالجة.
- الخطوة الأولى في المعالجة هي معرفة أي وضع إدراك DPI (Unaware / System Aware / Per-Monitor V2) يعمل به تطبيقك حالياً. تحقّق مما إذا كنت تعلنه عبر البيان أو app.config أو استدعاء API (أو لا شيء منها).3
- تختلف طريقة الضبط باختلاف الجيل. .NET (من Core 3.1 حتى .NET 8) عبر ملف المشروع أو
Application.SetHighDpiMode، و.NET Framework 4.7 فما بعده عبر app.config، و4.6 فما دون يقف الخط الواقعي عند System Aware عبر البيان.45 - يجب فتح المصمّم دائماً على شاشة 100% (96 DPI). فتح نموذج على بيئة 150% وحفظه يعيد كتابة
AutoScaleDimensions، وهو حادث كلاسيكي ينهار فيه تخطيط الفريق كلّه.6 - الدعم الكامل (Per-Monitor V2) يتطلّب حجم عمل كبير. الأنسب مرحلتان: «واضح على الشاشة الرئيسية فقط عبر System Aware» كمرحلة أولى، ودعم PMv2 كامل كمرحلة ثانية، بحيث يتناسب حجم الاستثمار مع عمر التطبيق وبيئة الاستخدام.
- كإجراء مؤقّت إن تعذّر التعديل الذاتي أو ضاق الوقت، من المفيد أيضاً معرفة «إعداد DPI العالي» الذي يمكن للمستخدم نفسه تجاوزه من خصائص الملف التنفيذي ← علامة تبويب التوافق، فهو يسهّل التعامل مع الاستفسارات.2
في المخطّط، يشير الخطّ المتّصل إلى علاقة قائمة دائماً، ويشير الخطّ المتقطّع إلى علاقة مشروطة (شروط قيامها مذكورة في شرح كلّ علاقة في الصفحة التفصيليّة). القائمة الكاملة للعلاقات (المجموع 21، مع الأدلّة ودرجة اليقين) وتعريفات المفاهيم الرئيسة مجمّعة في صفحة تفاصيل خريطة المعرفة (باليابانية). البيانات: JSON-LD / Turtle
2. لماذا يظهر ضبابياً ── آلية DPI virtualization
يُعبَّر عن تحجيم العرض في Windows بمعامل يجعل 96 DPI تساوي 100%. أي 125% = 120 DPI، و150% = 144 DPI، و200% = 192 DPI. عند استخدام شاشة 4K (3840×2160) بحجم 27 إنشاً بتحجيم 100%، يصبح النص صغيراً جداً، لذا يوصي Windows افتراضياً بنحو 150%. هذا يعني أن انتشار الشاشات عالية الدقة يعني مباشرة «انتشار بيئات تعمل بدقة غير 96 DPI».
المشكلة أن معظم تطبيقات سطح المكتب القديمة كُتبت على افتراض «الشاشة دائماً 96 DPI». الإحداثيات والخطوط والأيقونات جميعها مكتوبة بالبكسل مباشرة، فإذا رُسمت كما هي في بيئة 150% ستظهر كل العناصر فعلياً بحجم يعادل ثلثي الحجم. لذلك يوهم Windows التطبيقات التي لم تُعلن دعم DPI بأن «الشاشة 96 DPI»، ثم يعرض ما رسمه التطبيق ظاناً أنه بدقة 96 DPI كصورة نقطية مكبّرة. هذا هو DPI virtualization (تمديد الصورة النقطية).1
مع أخذ هذه الآلية بالحسبان، يتطابق العرض والسبب بشكل مرتّب. استخدم هذا الجدول في التشخيص الأول.
| العرض | السبب | الحالة |
|---|---|---|
| تلطّخ وضبابية موحّدة على الشاشة كلّها. لا ينهار التخطيط | DPI virtualization (نظام التشغيل يكبّر الصورة النقطية) | غير داعم لـ DPI (Unaware). آمن لكن قبيح |
| النص واضح، لكن عناصر التحكّم تتداخل أو تُقصّ | أُعلن دعم DPI لكن التخطيط لم يتابع | دعم DPI ناقص. من هنا يبدأ التعديل |
| واضح على الشاشة الرئيسية، ضبابي عند الانتقال إلى شاشة فرعية | System Aware (DPI الشاشة الرئيسية عند بدء التشغيل ثابت) | كما هو المتوقَّع. موضوع قرار حول التحوّل إلى PMv2 |
| حجم النص جيّد، لكن الأيقونات والصور فقط صغيرة أو خشنة | أصول الصور النقطية لا تزال لـ 96 DPI | عدم دعم أصول الصور (الفصل 6) |
| شاشة أو عنصر تحكّم معيّن فقط ينهار | تخطيط بإحداثيات ثابتة، رسم ذاتي، عنصر تحكّم من طرف ثالث | موضوع تعديل فردي (الفصل 6) |
المهم أن التطبيق «الضبابي» ليس منهاراً في الحقيقة. إجراء إنقاذ نظام التشغيل يعمل بشكل صحيح. التعديل يعني قطع إجراء الإنقاذ هذا وإعلان «سأحجّم بنفسي» (أي رفع وضع إدراك DPI)، وبمجرّد الإعلان تصبح مشكلة التخطيط كلّها مسؤوليتك. الاستشارات من نوع «حاولت التحوّل إلى PMv2 فازداد الأمر سوءاً» تحدث في هذا الإطار بالضبط.
2.1 خطوات إعادة إنتاج الأعراض والتحقّق منها على جهازك
هذا المقال لا يتضمّن لقطات شاشة. الفرق بين «ضبابي» و«منهار» أوضح حين تبدّل الإعداد على جهازك وتقارن بعينك من أن تراه في صورة ثابتة. بالخطوات التالية ميّز بنفسك الصف الأول والثاني من الجدول أعلاه. يمكن التحقّق إلى هذا الحد حتى بشاشة واحدة.
- بدّل معامل التكبير بين 100% و150%. ابدأ > الإعدادات > النظام > العرض > «تغيير الحجم والتخطيط» > «تغيير حجم النص والتطبيقات والعناصر الأخرى».7 أكبر فرق يظهر عند مقارنة 100% و150%.
- أعد تشغيل التطبيق دائماً. لا Unaware ولا System Aware يتابع معامل التكبير الجديد وهو قيد التشغيل. بعد كل تغيير أعد التشغيل. في حالة System Aware، عند تبديل الشاشة الرئيسية يلزم أيضاً تسجيل الخروج ثم الدخول (لأن System DPI يُثبَّت عند تسجيل الدخول).
- قارن التفاصيل بعدسة المكبّر. مفتاح شعار Windows +
+(زائد) يشغّل المكبّر.8 ارفع إلى نحو 400% واحكم أي الحالتين تنطبق.- حدود النص ضبابية بشكل موحّد، والخطوط تتلطّخ بلون وسيط ── DPI virtualization (الصف الأول في الجدول). النص والخطوط والأيقونات تتدهور بالقدر نفسه هو الفيصل، وليست مشكلة في جانب التطبيق.
- النص واضح، لكن الأزرار والتسميات تتداخل أو تُقص أطرافها ── دعم DPI معلن والتخطيط لا يتابع (الصف الثاني). من هنا يبدأ تعديل الفصل 6.
- انظر إلى الأيقونات وحدها. إن كان النص واضحاً وأيقونات ToolStrip وحدها كحبّة أرز أو خشنة، فهذا الصف الرابع (لصق صورة نقطية لـ 96 DPI مباشرة).
- انقل النافذة بين الشاشات (إن وُجدت شاشتان أو أكثر). اسحب النافذة إلى شاشة بمعامل تكبير مختلف. إن تلّطخت في الوجهة فقط فذلك System Aware (الصف الثالث)، وهو السلوك المتوقَّع.
ويمكن تقريباً استنتاج الوضع الحالي لتطبيقك من هذا المظهر. واضح عند 100% و150% ويبقى واضحاً عند الانتقال بين الشاشات = ما يعادل PMv2، واضح على الشاشة الرئيسية فقط = System Aware، تلطّخ موحّد في كل البيئات = Unaware. موضع الإعلان (البيان / app.config / استدعاء API) نتحقّق منه في الفصل 4.
3. ترتيب أوضاع إدراك DPI
تعلن التطبيقات وحدةً بوحدة (وبالدقة، النافذة العلوية منذ Windows 10 فما بعده) إلى أي حد تستطيع التعامل مع DPI. الأوضاع أربعة فعلياً.12
| الوضع | نظام التشغيل الذي أُدخل فيه | DPI الذي يراه التطبيق | عند الانتقال بين الشاشات / تغيّر DPI | الموقع الواقعي في WinForms |
|---|---|---|---|---|
| Unaware | ── | دائماً 96 | نظام التشغيل يكبّر الصورة النقطية (ضبابية) | الافتراضي إن لم يُعلن شيء. ضبابي لكن لا ينهار |
| System Aware | Vista | DPI الشاشة الرئيسية عند تسجيل الدخول ثابت | خارج الشاشة الرئيسية أو بعد التغيير، يكبّر نظام التشغيل (ضبابية) | يعمل في جميع الأجيال. المرشّح الأول للتسوية |
| Per-Monitor (V1) | 8.1 | DPI الشاشة التي تحوي النافذة | إشعار فقط للنافذة العلوية. التحجيم كلّه يدوي | لا دعم من الإطار، جدوى عملية ضئيلة. لا يُختار |
| Per-Monitor V2 | 10 (1703) | DPI الشاشة التي تحوي النافذة | إشعار حتى النوافذ الفرعية. المنطقة غير العميليّة يتابعها نظام التشغيل | المرشّح الأول للدعم الكامل. متاح في .NET Framework 4.7+ و.NET |
الفرق بين Per-Monitor V1 وV2 حاسم في العمل الفعلي. V1 آلية موجّهة لـ Win32 الخام حيث «يصلك الإشعار لكن الباقي كلّه بنفسك»، ولا يوجد سبب لاستخدامها من WinForms. أما V2 فيحجّم نظام التشغيل تلقائياً شريط العنوان وشريط التمرير والقوائم وغيرها من المناطق غير العميليّة، ودعم إطار WinForms نفسه (لاحقاً) مبني على افتراض V2. إن اخترت Per-Monitor، فـ V2 هو الاختيار الوحيد.2
هناك أيضاً وضع آخر يُدعى GDI scaling (DPI_AWARENESS_CONTEXT_UNAWARE_GDISCALED، من Windows 10 1809 فما بعده). يبقى التطبيق كما هو Unaware، لكن النص والأشكال المرسومة عبر GDI فقط يكبّرها نظام التشغيل على مستوى المتّجهات، وهي نسخة محسّنة من تمديد الصورة النقطية.2 بما أنها قد تخفّف تلطّخ النص دون تغيير أي شيفرة على الإطلاق، فمن المفيد تذكّرها كإجراء مؤقّت للتطبيقات التي يتعذّر تعديلها (القسم 4.3).
كذلك، منذ Windows 10 1607 فما بعده يوجد أيضاً وضع مختلط (Mixed-Mode) يسمح بمزج أوضاع مختلفة وحدةً بوحدة على مستوى النافذة العلوية، بحيث يُدعم انتقال مرحلي من نوع «الشاشة الرئيسية PMv2 فقط، والحوارات التي يتعذّر إصلاحها تبقى Unaware ليكبّرها نظام التشغيل» على مستوى Win32.9 ليس أمراً يُستخدم بسهولة من WinForms، لكن فكرة تصميم «لا حاجة لإصلاح الشاشة كلّها دفعة واحدة» تتّصل باستراتيجية المراحل في الفصل 7.
4. طريقة الضبط ── الإجابة الصحيحة حسب الجيل
تختلف طريقة إعلان وضع إدراك DPI حسب جيل تطبيقك. الخطأ هنا يضيّع الوقت في حالة «ضبطته لكنه لا يعمل»، لذا نكتبه مفصّلاً حسب كل جيل.
4.1 WinForms في .NET (من Core 3.1 حتى .NET 8)
في .NET يتوفّر Application.SetHighDpiMode، ويستدعيه ApplicationConfiguration.Initialize() (المولَّد بواسطة القالب، من .NET 6 فما بعده). الافتراضي هو SystemAware.4 يُنصح بكتابة الإعداد في ملف المشروع، وهو ما يستخدمه أيضاً مصمّم Visual Studio.
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>WinExe</OutputType>
<TargetFramework>net8.0-windows</TargetFramework>
<UseWindowsForms>true</UseWindowsForms>
<!-- SystemAware(既定)/ PerMonitorV2 / DpiUnaware / DpiUnawareGdiScaled -->
<ApplicationHighDpiMode>PerMonitorV2</ApplicationHighDpiMode>
</PropertyGroup>
</Project>
نقطة يجب الانتباه إليها هي أن ApplicationHighDpiMode في ملف المشروع وApplicationConfiguration.Initialize() هما آلية أُدخلت في .NET 6.4 في مشاريع .NET Core 3.1 / .NET 5، كتابة هذه الخاصية لا تعمل، لذا استدعِ Application.SetHighDpiMode مباشرة من الشيفرة كما يلي (وينطبق الأمر نفسه على النمط القديم لـ Main الذي لا يستخدم ApplicationConfiguration.Initialize()). في كلتا الحالتين، يجب استدعاؤه قبل إنشاء نافذة واحدة.
[STAThread]
static void Main()
{
Application.SetHighDpiMode(HighDpiMode.PerMonitorV2);
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new MainForm());
}
تحسّن في .NET 6 فما بعده تحجيم عناصر تحكّم الحاوية ونوافذ MDI الفرعية عند استخدام PMv2، وحُلّت إلى حد كبير مشاكل مثل «انزياح عناصر التحكّم عند الانتقال من شاشة 200% إلى شاشة 100%» التي كانت موجودة حتى .NET 5.4 عند خوض دعم PMv2 بجدّية، فإن الانطباع الفعلي هو أن .NET الأحدث أسهل في التعامل معه بوضوح مقارنة بـ .NET Framework. عوامل النظر في الانتقال من .NET Framework مجموعة في «قائمة فحص ما قبل الترحيل من .NET Framework إلى .NET».
4.2 .NET Framework 4.7 فما بعده
تعزّز دعم DPI العالي بقوة في .NET Framework 4.7. أُدخل تحسين تحجيم عناصر التحكّم، وأحداث تغيّر DPI (سلسلة DpiChanged)، وخاصية DeviceDpi. لكنه اختياري التفعيل (opt-in)، ولا يُفعَّل إلا بضبط النقطتين التاليتين معاً.5
أولاً، أعلن توافق Windows 10 عبر البيان (بدونه لا تُفعَّل ميزة DPI العالي في 4.7 من الأساس).
<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
<application>
<!-- Windows 10 互換宣言 -->
<supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}" />
</application>
</compatibility>
ثانياً، أعلن وضع إدراك DPI عبر System.Windows.Forms.ApplicationConfigurationSection في app.config.
<configuration>
<System.Windows.Forms.ApplicationConfigurationSection>
<add key="DpiAwareness" value="PerMonitorV2" />
<!-- 自前でスケーリング済みの画面がある場合は個別機能をオフにできる -->
<!-- <add key="EnableWindowsFormsHighDpiAutoResizing" value="false" /> -->
</System.Windows.Forms.ApplicationConfigurationSection>
</configuration>
تأكّد أيضاً من استدعاء Application.EnableVisualStyles() في بداية Main. هنا نقطة تنبيه واحدة: الطريقة القديمة المتمثّلة في وصف <dpiAware> / <dpiAwareness> في البيان تُبطل إعداد app.config، فالموصى به رسمياً في WinForms 4.7 عدم استخدامهما معاً.5 عند ترقية تطبيق كتب سابقاً <dpiAware>true</dpiAware> في البيان للتحوّل إلى System Aware إلى 4.7+PMv2، ابدأ بتنظيف الإعلان في جانب البيان. سبب حالة «ضبطته في app.config لكنه لا يعمل» غالباً ما يكون هذا بالضبط.
4.3 .NET Framework 4.6 فما دون · خليط VB6/MFC
في WinForms لجيل 4.6 فما دون لا توجد شيفرة إطار داعمة لـ PMv2، وحتى لو أُعلن قسراً، ستُضطر إلى معالجة كامل انهيار التخطيط بنفسك. الحل الواقعي لهذا الجيل هو الوقوف عند إعلان System Aware عبر البيان. الوسيلة الموصى بها للإعلان على مستوى نظام التشغيل هي البيان، وكتابة <dpiAware> (من Vista) و<dpiAwareness> (من Windows 10 1607) معاً تجعل التفسير صحيحاً في الأنظمة القديمة والحديثة كليهما.3
<asmv3:application xmlns:asmv3="urn:schemas-microsoft-com:asm.v3">
<asmv3:windowsSettings>
<dpiAware xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">true</dpiAware>
<dpiAwareness xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">system</dpiAwareness>
</asmv3:windowsSettings>
</asmv3:application>
عند التحوّل إلى System Aware، يعمل التحجيم التلقائي لـ WinForms (الفصل 5) مرّة واحدة عند بدء التشغيل وفق DPI الشاشة الرئيسية، فيظهر واضحاً على الشاشة الرئيسية. النموذج الذي ضُبط فيه AutoScaleMode.Font بشكل صحيح غالباً ما يصل إلى حالة مقبولة إلى حد كبير بهذا الإعلان وحده. توجد أيضاً طريقة للإعلان وقت التشغيل عبر API مثل SetProcessDpiAwareness، لكن لا يمكن تغييره بعد إنشاء النافذة، والإعلان عبر البيان هو الموصى به رسمياً.10 فكرة التعامل واحدة أيضاً لتطبيقات تختلط فيها شيفرات VB6 أو MFC، إذ يُحدَّد الوضع على مستوى العملية كلّها عبر بيان الملف التنفيذي (لا يملك MFC نفسه دعماً للتحجيم التلقائي، لذا يبقى فحص الشاشات بعد إعلان System Aware ضرورياً. راجع أيضاً «ما هو MFC في Windows» بخصوص التعامل مع أصول هذا الجيل).
نذكر أيضاً الحل المؤقّت من جهة المستخدم في حال تعذّر التعديل نفسه. يمكن للمستخدم تجاوز تحجيم DPI لذلك التطبيق من خصائص الملف التنفيذي.2 نرتّب أسماء عناصر الشاشة بالترتيب حتى يمكن قراءتها في مكالمة هاتفية.
- انقر بالزر الأيمن على ملف exe المستهدف واختر «خصائص». إن لم يكن لديك إلا اختصار، استخدم «فتح موقع الملف» للانتقال إلى المجلد الذي يحوي الملف الفعلي.
- افتح علامة تبويب «التوافق».
- اضغط زر «تغيير إعدادات DPI العالي».
- في الحوار الذي يفتح، فعّل خانة «تجاوز سلوك تحجيم DPI العالي».
- من القائمة المنسدلة «تنفيذ التحجيم من» أسفلها اختر السلوك. «النظام» يفرض DPI virtualization (لا ينهار لكن يتلطّخ)، و«النظام (محسّن)» يطبّق GDI scaling المذكور في الفصل 3، فيصبح النص المرسوم عبر GDI فقط واضحاً.2
- أغلق الحوارين بـ «موافق»، ثم أعد تشغيل التطبيق وتفقّد المظهر.
أيّهما أفضل، «النظام» أم «النظام (محسّن)»، يعتمد على التطبيق، فالأضمن أن يقارنهما المستخدم بخطوات القسم 2.1. ليس حلاً شاملاً، لكنه يستحق إدراجه في دليل الدعم كوسيلة يمكن إرشادها عبر الهاتف عند الحاجة إلى حل فوري لدى العميل. خصائص الاختصار لا تحتوي هذا العنصر، فالنقطة الوحيدة التي لا تُسقَط عند الإرشاد هي فتح ملف exe الفعلي.
5. AutoScaleMode وفخ المصمّم (Designer)
يملك WinForms آلية تحجيم تلقائي خاصة بالنموذج نفسه، منفصلة عن وضع إدراك DPI. من دون فهم هذه الآلية، لن يُحجَّم بشكل صحيح حتى بعد التحوّل إلى System Aware.
الآلية كالتالي. عند التصميم، يسجّل كل نموذج (ContainerControl) مرجع التحجيم في AutoScaleMode، والقيمة المرجعية في بيئة التصميم في AutoScaleDimensions. عند التشغيل، تُقارَن قيمة البيئة الحالية (CurrentAutoScaleDimensions) بها، وإن وُجد فرق، تُكبَّر أو تُصغَّر عناصر التحكّم الفرعية معاً.11 بعبارة أخرى، هذه آلية تمتص «الفرق بين بيئة التصميم وبيئة التشغيل»، وتُحفظ القيمة المرجعية داخل الشيفرة (Designer.cs).
خيارات AutoScaleMode اثنان فعلياً.
| AutoScaleMode | المرجع | الخصائص |
|---|---|---|
| Font (موصى به · الافتراضي) | أبعاد خط النموذج | يتغيّر الحجم الفعلي لخط النظام مع ارتفاع DPI، فيتابع DPI أيضاً. يتابع أيضاً تغيير إعداد خط المستخدم |
| Dpi | دقة الشاشة | يتناسب مع DPI فقط. مناسب للشاشات القائمة على الرسوميات |
| None | ── | التحجيم التلقائي معطّل. غالباً ما تكون هذه حالة التطبيقات المكتوبة بالبكسل مباشرة لـ 96 DPI |
إن تردّدت، اختر Font. نقطة تنبيه: مزج أوضاع مختلفة بين النموذج الأساسي والنماذج المشتقّة يؤدّي إلى نتيجة غير متوقَّعة، وهذا موثَّق رسمياً أيضاً.11 في التطبيقات التي تستخدم وراثة النماذج، يجب أولاً جرد وتوحيد وضع جميع النماذج.
والآن الفخ الرئيسي: بما أن AutoScaleDimensions آلية تسجّل «قيمة بيئة التصميم»، فإن فتح مصمّم Visual Studio على شاشة 150% وحفظ النموذج يعيد كتابة AutoScaleDimensions في Designer.cs بقيمة 150% (في وضع Font تصبح 6F, 12F مثلاً 9F, 18F). وتُحفظ الإحداثيات والأحجام أيضاً بقيمة مضروبة في 1.5. عندما يبني عضو من الفريق يعمل ببيئة 100% هذا النموذج ويشغّله، يظهر كل شيء منكمشاً، وتظهر في مراجعة الفروق فروقات ضخمة تشمل إحداثيات جميع عناصر التحكّم. هذا حادث كلاسيكي في استشارات DPI العالي: «عضو جديد بحاسوب محمول عالي الدقة لمس نموذجاً واحداً فانكسر تخطيط المستودع».
هذا الحادث يظهر حتماً في git diff قبل الالتزام. إن فتحت نموذجاً واحداً وحفظته فقط، وظهر في Designer.cs فرق كهذا، فذلك دليل على الفتح في بيئة 150%.
- this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F);
+ this.AutoScaleDimensions = new System.Drawing.SizeF(9F, 18F);
بعد هذا السطر تتوالى فروق أعادت كتابة ClientSize وLocation / Size لجميع عناصر التحكّم بقيم مضروبة في 1.5. ما ينبغي النظر إليه في المراجعة هو سطر AutoScaleDimensions هذا وحده؛ إن تغيّر، يجوز إرجاع الباقي دون قراءة فروق الإحداثيات اللاحقة.
الحل الأساسي واحد فقط: يجب فتح المصمّم بدقة 100% (96 DPI). Visual Studio نفسه تطبيق داعم لـ DPI، لكن مصمّم WinForms (لتطبيقات .NET Framework) غير داعم لـ DPI، لذا عند فتحه على شاشة عالية الدقة يظهر شريط معلوماتي أصفر يطلب «إعادة تشغيل Visual Studio بتحجيم 100%».6 لا نضع لقطة شاشة، لكن التسلسل كالتالي.
- على شاشة عالية DPI، افتح في Visual Studio نموذجاً من مشروع
.NET Frameworkفي المصمّم. - يظهر شريط معلوماتي أصفر أعلى المصمّم يطلب إعادة التشغيل بتحجيم 100%. لا تحفظ النموذج في هذه الحالة. يظهر الفرق أعلاه.
- من رابط الشريط أعد تشغيل Visual Studio. يقوم VS كلّه بوضع غير داعم لـ DPI، فيبدو عرض VS نفسه ضبابياً قليلاً، وهذه هي الحالة الصحيحة.
- في تلك الحالة عدّل النموذج واحفظه، وتحقّق بـ
git diffمن أنAutoScaleDimensionsلم يتغيّر. - بعد انتهاء العمل شغّل Visual Studio كالعادة لإلغاء وضع عدم دعم DPI.
للتشغيل مباشرة من سطر الأوامر في هذه الحالة استخدم devenv /noScale. في مشاريع .NET 6 فما بعده، يتيح ضبط <ForceDesignerDPIUnaware>true</ForceDesignerDPIUnaware> في ملف المشروع (من Visual Studio 2022 17.8 فما بعده) تشغيل تبويب المصمّم فقط بوضع عدم دعم DPI دون إعادة تشغيل Visual Studio كاملاً (لا يُستخدم في مشاريع .NET Framework).6 إن كان الهدف .NET 6 فما بعده، تصبح خطوات 3 إلى 5 نفسها غير لازمة، فانظر في هذا أولاً.
بالنسبة لآلية الفحص التلقائي، فإن «رصد أي فرق في AutoScaleDimensions في Designer.cs عن القيمة المحدَّدة عبر CI أو pre-commit» طريقة سهلة وفعّالة. من الأرخص إيقاف الحادث عند مدخل الالتزام بدل إصلاحه بعد وقوعه.
6. الأنماط النمطية للانهيار وطريقة إصلاحها
عند رفع وضع إدراك DPI (أو محاولة رفعه)، تقع المواضع المنهارة غالباً ضمن الأنماط التالية.
| ما ينهار | السبب | طريقة الإصلاح |
|---|---|---|
| تداخل عناصر التحكّم / قصّها | تخطيط بإحداثيات وأحجام ثابتة | الاستبدال بـ Anchor/Dock، وTableLayoutPanel / FlowLayoutPanel. الاستفادة من AutoSize |
| الأيقونات والصور صغيرة/خشنة | إلصاق صورة نقطية مباشرة لـ 96 DPI | تجهيز صور بدقّات متعدّدة والتبديل حسب DPI. تصغير من صورة كبيرة واحدة إن أمكن |
| الرسم الذاتي (الرسوم البيانية، الرسومات، معاينة التقارير) | كتابة مباشرة بالبكسل إلى Graphics | تحجيم الإحداثيات وعرض الخط والخط استناداً إلى DeviceDpi |
| ضيق صفوف DataGridView | تحديد بكسلي لـ RowHeight وما شابه | استخدام AutoSizeRowsMode، أو ضبط قيمة محجّمة وفق DPI |
| أيقونات ToolStrip صغيرة كحبّة الأرز | ثابتة 16×16 | ضبط ImageScalingSize وفق DPI |
| عنصر تحكّم معيّن من طرف ثالث أو ActiveX فقط ينهار | العنصر نفسه غير داعم لـ DPI | التحديث إلى نسخة داعمة من المورّد. إن لم تتوفّر، فهذا هو سقف مستوى الدعم |
استبدال التخطيط هو محور حجم العمل. بعبارة أخرى، الشاشة المبنية أصلاً بـ TableLayoutPanel وDock لا تحتاج جهداً يُذكر حتى بعد رفع وضع إدراك DPI. مجرّد اعتماد قاعدة «تُبنى الشاشات الجديدة من الآن فصاعداً بألواح تخطيط من البداية» يقلّل من الدين المستقبلي.
تحجيم الرسم الذاتي أساسه تحويل القيمة المحسوبة على أساس 96 DPI استناداً إلى Control.DeviceDpi (.NET Framework 4.7+ / .NET).
public partial class ChartPanel : Panel
{
// 96 DPI 基準の設計値を現在の DPI へ変換
private int Scale(int value96) => value96 * DeviceDpi / 96;
protected override void OnPaint(PaintEventArgs e)
{
using var pen = new Pen(Color.Navy, Scale(2));
e.Graphics.DrawRectangle(pen,
Scale(16), Scale(16), Scale(320), Scale(120));
}
// PMv2 ではモニター間移動で DPI が変わるので再描画を促す
protected override void OnDpiChangedAfterParent(EventArgs e)
{
base.OnDpiChangedAfterParent(e);
Invalidate();
}
}
حتى System Aware، تبقى دقة DPI ثابتة عند بدء التشغيل، لذا يكفي إدخال Scale فقط، لكن في PMv2 يتغيّر DeviceDpi مع كل انتقال بين الشاشات، لذا يلزم تصميم يعيد بناء الخطوط والصور وقيم التخطيط المخزَّنة مؤقّتاً عبر أحداث سلسلة DpiChanged.5 «كم عدد شاشات الرسم الذاتي» يؤثّر مباشرة على تقدير حجم العمل لدعم PMv2.
عناصر التحكّم من طرف ثالث وActiveX/OCX هي العامل الذي يحدّد سقف هذا التعديل. إن كان العنصر نفسه غير داعم لـ DPI، فمهما بذلت من جهد على جانب المضيف، لن تكتمل تلك الشاشة كاملة. تحقّق من حالة دعم المورّد، وبالنسبة لـ ActiveX التي لا يُرجى تحديثها، حدّد كيفية التعامل معها من جدول القرار في «هل تُبقي على ActiveX/OCX أم تغلّفه أم تستبدله» قبل ضبط هدف دعم DPI العالي.
7. استراتيجية المعالجة المرحلية ── جدول القرار حول مدى العمق المطلوب
استناداً إلى ما سبق، يمكن ترتيب مستوى المعالجة في 3 مراحل. المثالي التقني هو جعل كل التطبيقات PMv2، لكن مع أخذ ميزانية التعديل وعمر التطبيق بالحسبان، غالباً ما تكون التسوية هي الإجابة الصحيحة.
| (1) لا شيء (Unaware) | (2) التحوّل إلى System Aware | (3) دعم PMv2 كامل | |
|---|---|---|---|
| المظهر | ضبابي في جميع البيئات (لا ينهار) | واضح على الشاشة الرئيسية. ضبابي عند الشاشة الفرعية أو تغيير DPI | واضح في جميع الشاشات |
| العمل الرئيسي | لا شيء | إعلان البيان/الإعدادات + فحص AutoScaleMode + التحقّق من عرض جميع الشاشات | (2) + فحص شامل للتخطيط + دعم DPI للرسم الذاتي وأصول الصور + دعم DpiChanged |
| حجم العمل | صفر | صغير إلى متوسّط (التحقّق يتناسب مع عدد الشاشات) | كبير (محوره إصلاح الانهيار. عناصر التحكّم من طرف ثالث تحدّد السقف) |
| الحالة المناسبة | مقرَّر إلغاؤه خلال سنوات قليلة. يقبله المستخدمون | تطبيقات العمل الداخلية المتمحورة حول سطح مكتب ثابت / شاشة واحدة. كمرحلة أولى | استخدام مختلط للحاسوب المحمول + شاشة خارجية. تطبيق رئيسي طويل العمر. منتج يُوزَّع على العملاء |
محاور القرار ثلاثة: عمر التطبيق (كم سنة سيُستخدم بعد)، بيئة الاستخدام (إن كان الجميع على نفس سطح المكتب الثابت، فإن System Aware يكتمل عملياً؛ أما إذا كثر استخدام الحاسوب المحمول مع شاشة خارجية، فسيبقى استياء من System Aware الذي يظهر ضبابياً عند كل انتقال بين الشاشات)، وميزانية التعديل. الخطوة الموصى بها هي تنفيذ (2) أولاً كمعيار لجميع التطبيقات، ثم الاستناد إلى حجم الانهيار الذي وُجد خلال هذه العملية وقيود عناصر التحكّم من طرف ثالث لتقرير الانتقال إلى (3) أم لا، وأي الشاشات فقط. (2) محوره «الإعلان + الفحص»، ومخاطر الفشل فيه صغيرة، ومع ذلك يتحسّن إحساس المستخدم كثيراً.
نتطرّق أيضاً للاختبار. غالباً لا تظهر مشاكل DPI العالي على جهاز التطوير، لذا يجب تعمّد إنشاء البيئات التالية للتحقّق.1
- توصيل شاشتين بتحجيم مختلف (مثال: 150% للشاشة المدمجة في الحاسوب المحمول + 100% للشاشة الخارجية)، والانتقال بالنافذة بينهما
- تبديل الشاشة الرئيسية ثم التشغيل بعد إعادة تسجيل الدخول (تُحدَّد دقة DPI للنظام عند تسجيل الدخول، فلن تتغيّر دون إعادة تسجيل الدخول)
- تغيير إعداد التحجيم أثناء تشغيل التطبيق
- الاتّصال عبر سطح المكتب البعيد (RDP) من عميل عالي DPI (بما أن RDP ينقل دقة DPI الخاصة بالعميل، فإن «الطبيعي على وحدة تحكّم الخادم لكن منهار عبر RDP» تقرير شائع)
يظهر التكوين في الشكل التالي. جهاز فعلي واحد + شاشتان هما الأساس، ثم تُضاف النسب الناقصة بآلة افتراضية، ويُركَّب أخيراً التحقّق عبر RDP.
flowchart TB
APP["تطبيق WinForms المستهدف للتحقق"]
subgraph PHYS["جهاز فعلي واحد ── شاشتان كأساس"]
NB["الشاشة المدمجة 150%<br/>الجانب الذي نجعله الشاشة الرئيسية"]
EXT["شاشة خارجية 100%"]
NB <-->|"اسحب النافذة ذهاباً وإياباً"| EXT
end
subgraph VMS["آلة افتراضية ── إضافة النسب الناقصة"]
VM1["125%"]
VM2["200%"]
end
RDPC["سطح المكتب البعيد<br/>الاتصال من عميل عالي DPI"]
APP --> NB
APP --> EXT
APP --> VM1
APP --> VM2
APP --> RDPC
سهم الذهاب والإياب في الشكل هو العملية التي يظهر فيها فرق System Aware وPMv2 بأوضح صورة. تبديل الشاشة الرئيسية يتم داخل PHYS بتبادل دورَي NB وEXT، مع إعادة تسجيل الدخول في كل مرّة للتحقّق.
عندما يصل تقرير بأن «الانهيار يحدث فقط عند 125%»، فإن إنشاء ذلك التحجيم فعلياً ومشاهدته هو الأسرع في النهاية، وفق الخبرة. يمكن أيضاً تغيير إعداد التحجيم في الآلة الافتراضية، لذا فإن تجهيز بيئات تحقّق بنسب 100 / 125 / 150 / 200% يسرّع التمييز.
8. الخلاصة
«الضبابية» في بيئة DPI العالية إجراء إنقاذ من نظام التشغيل (DPI virtualization)، و«الانهيار» دعم DPI ناقص ── إن أمسكت هذه العلاقة وحدها، يمكنك عكس المسار من العرض إلى السبب والحل. طريقة الضبط تختلف حسب الجيل: في .NET يُستخدم ApplicationHighDpiMode في ملف المشروع، وفي .NET Framework 4.7 فما بعده app.config (بدون استخدام dpiAware في البيان معه)، و4.6 فما دون يقف الخط الواقعي عند System Aware عبر البيان. بالإضافة إلى ذلك، فإن توحيد AutoScaleMode.Font وقاعدة تشغيلية تقضي بفتح المصمّم بدقة 100% أمران بسيطان لكنهما الأكثر فاعلية في تقليل الحوادث.
بعد ذلك، حدّد مدى العمق المطلوب من المراحل الثلاث في الفصل 7. البدء بالتحوّل إلى System Aware لجعل الشاشة الرئيسية واضحة، ثم الانتقال إلى PMv2 إذا تناسب بيئة الاستخدام وعمر التطبيق ── هذا هو النهج ذو المرحلتين الذي نوصي به فعلياً في مشاريع التعديل التي نتولاها. إن كان الوقت قد حان لإعادة النظر في إطار الواجهة نفسه (WPF مصمَّم منذ البداية بقدرة قوية على التعامل مع DPI)، فإن «كيف نختار بين WinForms / WPF / WinUI» أيضاً مادّة جيّدة للنظر فيها. إن تردّدت في تحديد إلى أي مرحلة يمكن إصلاح تطبيقك الحالي، يمكننا المساعدة ابتداءً من جرد بنية الشاشات وعناصر التحكّم.
مقالات ذات صلة
- كيف نختار بين WinForms / WPF / WinUI - جدول قرار
- هل تُبقي على ActiveX / OCX أم تغلّفه أم تستبدله - جدول قرار
- قائمة فحص ما قبل الترحيل من .NET Framework إلى .NET
- ما هو MFC في Windows ── معرفة أساسية لصيانة الأصول القائمة
مجالات الاستشارة ذات الصلة
تتعامل شركة كومورا سوفت ذ.م.م. مع دعم DPI العالي لتطبيقات WinForms / MFC القديمة (المسح الحالي، تحديد مستوى المعالجة، تعديل التخطيط)، وتحقيق أسباب أعطال العرض المصاحبة لاستبدال الحواسيب، واستشارات تجديد الواجهة.
- الاستشارة التقنية ومراجعة التصميم
- الاستفادة من الأصول القائمة ودعم الترحيل
- تطوير تطبيقات Windows
- التواصل معنا
روابط مرجعية
-
Microsoft Learn, High DPI Desktop Application Development on Windows. حول خلفية تحجيم DPI، وسلوك كل وضع من أوضاع إدراك DPI، وآلية تكبير التطبيقات غير الداعمة لـ DPI كصورة نقطية، ونقاط الاختبار في بيئة DPI مختلطة. ↩ ↩2 ↩3 ↩4 ↩5
-
Microsoft Learn, DPI_AWARENESS_CONTEXT handle. حول تعريف وسلوك كل سياق من Unaware / System Aware / Per-Monitor / Per-Monitor V2 / UNAWARE_GDISCALED (GDI scaling، من Windows 10 1809 فما بعده). ↩ ↩2 ↩3 ↩4 ↩5 ↩6 ↩7 ↩8 ↩9
-
Microsoft Learn, Setting the default DPI awareness for a process. حول طريقة الإعلان عبر عنصري dpiAware / dpiAwareness في البيان، وعلاقة الأولوية بينهما، وعدم استحسان الإعلان عبر API. ↩ ↩2
-
Microsoft Learn, What’s new in Windows Forms .NET 6. حول التمهيد عبر ApplicationConfiguration.Initialize، وإعداد ApplicationHighDpiMode في ملف المشروع (الافتراضي SystemAware)، وتحسين تحجيم PerMonitorV2 في .NET 6. ↩ ↩2 ↩3 ↩4
-
Microsoft Learn, High DPI support - Windows Forms. حول محتوى تعزيز DPI العالي في .NET Framework 4.7، وSystem.Windows.Forms.ApplicationConfigurationSection في app.config (DpiAwareness=PerMonitorV2)، وعدم استحسان الإعلان عبر البيان لأنه يُبطل app.config، وأحداث سلسلة DpiChanged وDeviceDpi. ↩ ↩2 ↩3 ↩4
-
Microsoft Learn, Fix DPI display issues in Windows Form Designer. حول عدم دعم مصمّم WinForms لـ DPI، والشريط المعلوماتي الذي يظهر على الشاشات عالية الدقة لإعادة التشغيل بتحجيم 100%، وdevenv /noScale، وForceDesignerDPIUnaware لمشاريع .NET 6+. ↩ ↩2 ↩3
-
Microsoft Support, Change your screen resolution and layout in Windows. حول اختيار معامل التكبير من «تغيير الحجم والتخطيط» في «ابدأ > الإعدادات > النظام > العرض» عبر «تغيير حجم النص والتطبيقات والعناصر الأخرى». ↩
-
Microsoft Support, Use Magnifier to make things on the screen easier to see. حول تشغيل المكبّر بمفتاح شعار Windows + علامة الزائد، وإمكان تكبير جزء من الشاشة. ↩
-
Microsoft Learn, Mixed-Mode DPI Scaling and DPI-aware APIs. حول مزج أوضاع إدراك DPI على مستوى النافذة العلوية عبر SetThreadDpiAwarenessContext، وواجهات API الداعمة لـ DPI مثل GetDpiForWindow. ↩
-
Microsoft Learn, SetProcessDpiAwareness function. حول ضبط إدراك DPI الافتراضي للعملية عبر API، واستحسان الإعلان عبر البيان، وعدم إمكانية التغيير بعد الضبط مرّة واحدة. ↩
-
Microsoft Learn, Automatic form scaling - Windows Forms. حول سلوك التحجيم التلقائي عبر AutoScaleMode / AutoScaleDimensions / CurrentAutoScaleDimensions، وعدم دعم مزج وضعَي Font وDpi. ↩ ↩2
مقالات ذات صلة
أحدث المقالات التي تشترك في نفس الوسوم. عمّق فهمك بمواضيع مرتبطة.
دعم DPI العالي في WPF ── أسباب الضبابية والتلطّخ رغم أنه «يفترض أن يكون محصّناً ضد DPI» وطرق العلاج
WPF واعٍ بـ System DPI، لكن نقل النافذة إلى شاشة مختلفة DPI يجعل الشاشة كلّها تتلطّخ، وتصبح الصور النقطية ضبابية. نرتّب تشخيص السبب، ودعم...
دمج مصادقة Entra ID في تطبيقات WinForms/WPF ── التشكيل العملي لـ MSAL.NET ووسيط WAM
نرتّب خطوات دمج مصادقة Entra ID في تطبيقات WinForms/WPF لسطح المكتب. نشرح مفهوم العميل العامّ، وتسجيل التطبيق، وAcquireTokenSilent في MSA...
التاريخ والوقت والمناطق الزمنية في تطبيقات الأعمال ── من فخاخ DateTime إلى مبدأ التخزين بـ UTC وتصميم الاختبارات
ينزاح الوقت 9 ساعات بعد نقل الخادم. نرتّب أسباب أعطال التاريخ والوقت انطلاقاً من Kind في DateTime والتحويل الضمني. نشرح التمييز مع DateTi...
إقامة تطبيقات Windows في علبة النظام والإشعارات المنبثقة ── مطبات NotifyIcon وكيفية اختيار AppNotification
نرتّب إقامة تطبيقات Windows للأعمال في علبة النظام والإشعارات المنبثقة. نشرح الاستخدام الصحيح لـ NotifyIcon، وإعادة التسجيل عند إعادة تشغ...
كيف نفهم عزل الجلسات في Windows ── Session 0 وRDP وتشغيل عدة مستخدمين معاً
نوضح مفهوم «الجلسة» الذي يربك كثيراً من مطوّري تطبيقات Windows. نشرح عملياً سبب عزل Session 0 الذي يمنع الخدمة من عرض واجهة، وسلوك الجلسا...
أين يتصل هذا الموضوع
ترتبط هذه المقالة بشكل طبيعي بصفحات الخدمات التالية.
تطوير تطبيقات ويندوز
ندعم تطوير برامج ويندوز للأعمال، وتكامل الأجهزة، وأدوات التواصل.
الأسئلة الشائعة
أسئلة شائعة حول موضوع هذه المقالة.
- لماذا يظهر تطبيق WinForms ضبابياً على شاشة 4K؟
- ليس خللاً برمجياً، بل إجراء إنقاذ من نظام التشغيل (DPI virtualization). للتطبيقات التي لم تُعلن دعم DPI، يوهم Windows التطبيق بأن «الشاشة 96 DPI»، ثم يعرض ما رسمه التطبيق ظاناً أنه بدقة 96 DPI كصورة نقطية مكبّرة. لذلك لا ينهار التخطيط لكنه يتلطّخ. والعكس، «واضح لكن التخطيط ينهار» يعني أن دعم DPI أُعلن لكن التخطيط لم يستطع المتابعة، والسبب هنا معاكس تماماً. الخطوة الأولى قبل المعالجة هي تمييز أيّ العرضين يظهر.
- كيف يُضبط دعم DPI العالي في WinForms؟
- تختلف الطريقة باختلاف الجيل. في .NET 6 فما بعده تُستخدم خاصية ApplicationHighDpiMode في ملف المشروع (الافتراضي SystemAware)، وفي .NET Core 3.1 / .NET 5 يُستدعى Application.SetHighDpiMode قبل إنشاء أي نافذة. أما .NET Framework 4.7 فما بعده فيُعلن فيه توافق Windows 10 عبر البيان (manifest) ثم يُستخدم إعداد DpiAwareness في app.config، لكن وصف dpiAware في البيان يُبطل إعداد app.config، فالموصى به رسمياً عدم استخدامهما معاً. أما 4.6 فما دون، فالخط الواقعي يقف عند إعلان System Aware عبر البيان.
- أيّهما يجب اختياره، System Aware أم Per-Monitor V2؟
- نوصي بمرحلتين. المرحلة الأولى هي التحوّل إلى System Aware، حيث يُطبَّق التحجيم وفق DPI الشاشة الرئيسية عند بدء التشغيل، فيظهر واضحاً على الشاشة الرئيسية. تتمحور حول الإعلان والفحص، ومخاطر الفشل فيها صغيرة، وبالنسبة لتطبيقات العمل الداخلية القائمة على سطح مكتب ثابت تكتمل عملياً بهذا وحده. أما Per-Monitor V2 فيجعل الشاشة كلّها واضحة حتى عند الانتقال بين الشاشات، لكنه يتطلّب فحصاً شاملاً للتخطيط، ودعم DPI للرسم الذاتي وأصول الصور، ودعم حدث DpiChanged، ما يعني حجم عمل كبير، وإن كانت عناصر تحكّم من طرف ثالث غير داعمة فذلك يصبح السقف. يُتَّخذ القرار حسب عمر التطبيق وبيئة الاستخدام وميزانية التعديل.
- لماذا ينهار التخطيط عند حفظ نموذج من المصمّم (Designer)؟
- عند فتح مصمّم WinForms في Visual Studio على شاشة عالية DPI (مثل 150%) وحفظ النموذج، تُعاد كتابة AutoScaleDimensions في Designer.cs بقيمة 150%، وتُحفظ الإحداثيات والأحجام أيضاً بقيمة مضروبة في 1.5. عندما يبني عضو من الفريق يعمل ببيئة 100% هذا النموذج، يظهر كل شيء منكمشاً. الحل هو فتح المصمّم بدقة 100% (96 DPI)، وعلى الشاشات عالية DPI يمكن إعادة التشغيل بتحجيم 100% من الشريط الأصفر المعلوماتي. في مشاريع .NET 6 فما بعده يمكن أيضاً استخدام إعداد ForceDesignerDPIUnaware. من المفيد أيضاً بناء آلية ترصد عبر CI أو pre-commit أي فرق غير متوقَّع في AutoScaleDimensions.
الملف الشخصي للمؤلف
صفحة الملف الشخصي لمؤلف المقالة.
غو كومورا
مؤسّس شركة كومورا سوفت ذ.م.م.
يركّز على تطوير برامج ويندوز، والاستشارات التقنية، والتحقيق في الأخطاء، ويتميّز في المشاريع التي تبقى فيها الأصول القديمة ناشطة، وفي تشخيص الأعطال التي يصعب تحديد سببها.