c# डीपीआई जागरूकता-एक रिलीज में अनजान, दूसरे में सिस्टम अवेयर



.net winforms (1)

इस प्रश्न में बताई गई समस्या के बारे में :
एक अनुप्रयोग, जो डीपीआई-डिज़ाइन से अनजान है, अपने यूआई सामग्री को स्केल करने के लिए विंडोज वर्चुअलाइजेशन पर भरोसा करता है, अचानक (हालांकि कुछ संशोधनों के बाद, एक मामूली रिलीज अपडेट के लिए अग्रणी) - और जाहिरा तौर पर एक अवलोकनीय कारण के बिना - डीपीआई-अवेयर (सिस्टमवेयर) )।

  • एप्लिकेशन भी app.manifest <windowsSettings> की व्याख्या पर निर्भर करता है, जहां DPI- app.manifest के लिए app.manifest जागरूकता परिभाषा, चूक (पिछड़े संगतता के लिए) की अनुपस्थिति।

  • WPF असेंबली और कोई DPI- संबंधित API कॉल का कोई सीधा संदर्भ नहीं है।

  • आवेदन में तृतीय-पक्ष घटक (और, संभवतः, बाहरी निर्भरता) शामिल हैं।

चूंकि डीपीआई-अवेयरनेस यूआई प्रेजेंटेशन का एक प्रासंगिक पहलू बन गया है, जो उपलब्ध स्क्रीन रिज़ॉल्यूशन की विविधता (और संबंधित डीपीआई स्केलिंग सेटिंग्स) को देखते हुए, अधिकांश घटक उत्पादकों ने उच्च-डीपीआई के लिए अनुकूलित किया है और उनके उत्पाद डीपीआई-अवेयर (स्केल जब डीपीआई बदलते हैं) पता लगाया गया है) और डीपीआई-अवेयर असेंबलियों का उपयोग करें (अक्सर डब्ल्यूपीएफ असेंबलियों को संदर्भित करते हुए, डीपीआई-अवेयर परिभाषा द्वारा)।

जब इन DPI-Aware घटकों में से किसी एक प्रोजेक्ट (प्रत्यक्ष या अप्रत्यक्ष रूप से) में दर्शाया गया है, तो DPI- अनभिज्ञ अनुप्रयोग DPI-Aware बन जाएगा, जब DPI- अवेयरनेस को स्पष्ट रूप से अक्षम नहीं किया गया है।

असेंबली DPI- अवेयरनेस की घोषणा करने के लिए अधिक प्रत्यक्ष (अनुशंसित) तरीका है, इसे स्पष्ट रूप से एप्लिकेशन घोषणा में घोषित करना है।

Visual Studio 2017 से पहले अनुप्रयोग मैनिफ़ेस्ट सेटिंग के लिए हंस पैसेंट उत्तर का संदर्भ लें:
उच्च डीपीआई सेटिंग के साथ मशीन पर चलने के लिए ऐप को कैसे कॉन्फ़िगर करें

Visual Studio 2015-Update.1 और Visual Studio 2017 app.manifest , यह सेटिंग पहले से मौजूद है, इसे बस app.manifest करने की आवश्यकता है। अनुभाग सेट करें: <dpiAware>false</dpiAware>

<?xml version="1.0" encoding="utf-8"?>
<assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1">
  <assemblyIdentity version="1.0.0.0" name="MyApplication.app"/>

  //(...)

  <!-- Indicates that the application is DPI-aware and will not be automatically scaled by Windows at higher
       DPIs. Windows Presentation Foundation (WPF) applications are automatically DPI-aware and do not need 
       to opt in. Windows Forms applications targeting .NET Framework 4.6 that opt into this setting, should 
       also set the 'EnableWindowsFormsHighDpiAutoResizing' setting to 'true' in their app.config. -->

  <application xmlns="urn:schemas-microsoft-com:asm.v3">
    <windowsSettings>
      <dpiAware xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">false</dpiAware>
    </windowsSettings>
  </application>

//(...)

</assembly>

अधिक जानकारी के लिए इन MSDN लेखों का संदर्भ लें:
विंडोज पर उच्च डीपीआई डेस्कटॉप अनुप्रयोग विकास
किसी प्रक्रिया के लिए डिफ़ॉल्ट DPI जागरूकता सेट करना

एक अन्य विधि इन विंडोज एपीआई कार्यों का उपयोग करते हुए प्रक्रिया संदर्भ डीपीआई-जागरूकता सेट करना है:

विंडोज 7
SetProcessDPIAware

[DllImport("user32.dll", SetLastError=true)]
static extern bool SetProcessDPIAware();

विंडोज 8.1
SetProcessDpiAwareness

[DllImport("shcore.dll")]
static extern int SetProcessDpiAwareness(ProcessDPIAwareness value);

enum ProcessDPIAwareness
{
    DPI_Unaware = 0,
    System_DPI_Aware = 1,
    Per_Monitor_DPI_Aware = 2
}

विंडोज 10, संस्करण 1703
SetProcessDpiAwarenessContext()
(जब प्रति-मॉनिटर डीपीआई-जागरूकता के लिए चयन किया जाता है, तो Context_PerMonitorAwareV2 उपयोग Context_PerMonitorAwareV2 )

इसे भी देखें: मिश्रित-मोड डीपीआई स्केलिंग और डीपीआई-अवगत एपीआई - MSDN

विंडोज 10, संस्करण 1809 (अक्टूबर 2018)
एक नया DPI_AWARENESS_CONTEXT जोड़ा गया है: DPI_AWARENESS_CONTEXT_UNAWARE_GDISCALED

डीपीआई जीडीआई-आधारित सामग्री की बेहतर गुणवत्ता से अनजान है। यह मोड DPI_AWARENESS_CONTEXT_UNAWARE के समान व्यवहार करता है, लेकिन यह सिस्टम को उच्च-DPI मॉनिटर पर विंडो प्रदर्शित होने पर पाठ और अन्य GDI- आधारित प्राइमेटिव की रेंडरिंग गुणवत्ता को स्वचालित रूप से सुधारने में सक्षम बनाता है।

GetWindowDpiAwarenessContext() DPI_AWARENESS_CONTEXT GetWindowDpiAwarenessContext() फ़ंक्शन का उपयोग करें DPI_AWARENESS_CONTEXT विंडो का एक हैंडल और GetThreadDpiAwarenessContext() DPI_AWARENESS_CONTEXT हैंडल वर्तमान धागे के लिए। उसके बाद GetAwarenessFromDpiAwarenessContext() संरचना से DPI_AWARENESS मान प्राप्त करने के लिए DPI_AWARENESS_CONTEXT DPI_AWARENESS GetAwarenessFromDpiAwarenessContext()

[DllImport("user32.dll", SetLastError=true)]
static extern IntPtr GetWindowDpiAwarenessContext(IntPtr hWnd);

[DllImport("user32.dll", SetLastError=true)]
static extern IntPtr GetThreadDpiAwarenessContext();

[DllImport("user32.dll", SetLastError=true)]
static extern int GetAwarenessFromDpiAwarenessContext(InPtr DPI_AWARENESS_CONTEXT);


[DllImport("user32.dll", SetLastError=true)]
static extern int SetProcessDpiAwarenessContext(ContextDPIAwareness value);

// Virtual enumeration: DPI_AWARENESS_CONTEXT is *contextual*. 
// This value is returned by GetWindowDpiAwarenessContext() or GetThreadDpiAwarenessContext()
// and finalized by GetAwarenessFromDpiAwarenessContext(). See the Docs.
enum ContextDPIAwareness
{
    Context_Unaware = ((DPI_AWARENESS_CONTEXT)(-1)),
    Context_SystemAware = ((DPI_AWARENESS_CONTEXT)(-2)),
    Context_PerMonitorAware = ((DPI_AWARENESS_CONTEXT)(-3)),
    Context_PerMonitorAwareV2 = ((DPI_AWARENESS_CONTEXT)(-4)),
    Context_UnawareGdiScaled = ((DPI_AWARENESS_CONTEXT)(-5))
}

चूंकि डीपीआई-जागरूकता थ्रेड-आधारित है, इसलिए इन सेटिंग्स को एक विशिष्ट थ्रेड पर लागू किया जा सकता है। डीपीआई-जागरूकता को लागू करने के लिए उपयोगकर्ता इंटरफ़ेस को फिर से डिजाइन करते समय यह उपयोगी हो सकता है, सिस्टम को अधिक महत्वपूर्ण कार्यात्मकताओं पर ध्यान केंद्रित करते हुए कम महत्वपूर्ण घटक को लागू करने के लिए।

SetThreadDpiAwarenessContext
( SetProcessDpiAwarenessContext() रूप में एक ही पैरामीटर)

Assemblyinfo.cs
यदि कोई तृतीय-पक्ष / बाहरी घटक, जो एक WPF असेंबली का संदर्भ देता है, किसी अनुप्रयोग की DPI- जागरूकता स्थिति को फिर से परिभाषित करता है, तो यह Assemblyinfo.cs व्यवहार अक्षम किया जा सकता है, प्रोजेक्ट Assemblyinfo.cs में एक पैरामर्ट सम्मिलित करते Assemblyinfo.cs :

[assembly: System.Windows.Media.DisableDpiAwareness]

इस सवाल का पहले से ही यहाँ एक जवाब है:

इसलिए हमारे पास यह वास्तव में अजीब मुद्दा है। हमारे आवेदन एक सी # / WinForms app है। 6.0 रिलीज में, हमारा आवेदन DPI से अवगत नहीं है। हमारी 6.1 रिलीज में यह अचानक DPI से अवगत हो गया है।
6.0 रिलीज में, यदि आप इसे उच्च डीपीआई में चलाते हैं, तो यह विंडोज बिटमैप स्केलिंग का उपयोग करता है, जो ठीक है, क्योंकि यह स्क्रीन लेआउट को प्रभावित नहीं करता है। 6.1 रिलीज में, क्योंकि यह किसी कारण से डीपीआई के बारे में जागरूक हो गया है, उपयोगकर्ता इंटरफेस में गड़बड़ हो जाती है।
हम अभी इसे ठीक करने की स्थिति में नहीं हैं। हमारे पास सैकड़ों स्क्रीन हैं, इसलिए उन सभी को डीपीआई जागरूक मोड में ठीक से काम करने में बहुत समय लगेगा।

हमने SysInternals Process Explorer का उपयोग करके इसकी पुष्टि की है। हमारे 6.0 रिलीज में, यह अनजान को दिखाता है, लेकिन हमारी 6.1 रिलीज में, यह शुरू में अनजान को दिखाता है, लेकिन फिर सिस्टम अवेयर में बदल जाता है।
बाद वाला तब होता है जब कोड EXE से हमारे असेंबली DLL में प्रवेश करता है, जिसमें हमारे सभी यूजर इंटरफेस कोड होते हैं (हमारा EXE मूल रूप से एक बहुत ही पतला शेल है; यह वास्तव में हमारे प्रेजेंटेशन लेयर असेंबली पर कंट्रोलर क्लास कहता है।)

हमने निम्नलिखित की पुष्टि की है:

  • दोनों संस्करण VSS 2017 का उपयोग करके रिलीज़ मोड में बनाए गए हैं।
  • दोनों संस्करण एक ही .NET फ्रेमवर्क को लक्षित करते हैं (4.5)
  • दोनों संस्करण एक ही DevExpress संस्करण का उपयोग करते हैं।
  • दोनों संस्करणों में एक ही एप्लिकेशन प्रकट होता है, जिसमें DPI जागरूकता सेटिंग सक्षम नहीं होती है।
  • किसी भी संस्करण में किसी भी डीपीआई से संबंधित विंडोज एपीआई के लिए कोई कॉल नहीं है।
  • Sys इंटर्नल्स और कुछ संदेश बॉक्स का उपयोग करके हमने निर्धारित किया है कि 6.1 रिलीज़ क्या पता चलता है (प्रेजेंटेशन असेंबली में प्रवेश बिंदु) और क्या DLL उस बिंदु पर लोड किए गए हैं (हमारा, DevExpress, अन्य निर्भरताएँ), और फिर हमने एक छोटा सा डमी ऐप बनाया उसी DLL का संदर्भ देता है, और पुष्टि करता है कि ये लोड किए गए हैं। वह डमी ऐप DPI से वाकिफ नहीं है।
  • हमने दोनों रिलीज के बीच मुख्य csproj फाइलों की तुलना की है और कोई सार्थक अंतर नहीं हैं।
    • न ही WPF से कुछ भी संदर्भ जारी करें।

हमें समझ में नहीं आता है कि हमारी 6.1 रिलीज अचानक डीपीआई से अवगत क्यों हो गई है। हम इस बात पर अडिग हैं कि हमें और क्या देखना है और हमें एक सुधार की आवश्यकता है जो इस रिलीज को डीपीआई से अनजान मोड में वापस लाए। यह हमारी रिलीज को रोक रहा है। वास्तव में किसी भी संकेत की सराहना करेंगे। हम इस बिंदु पर कुछ भी करने को तैयार हैं।





dpi-aware