windows - मैं विंडोज 8.1 को कैसे जागरूक कर सकता हूं कि मेरा डेल्फी एप्लिकेशन प्रति मॉनिटर डीपीआई का समर्थन करना चाहता है?




delphi windows-8.1 (2)

मैंने विंडोज 8.1 को डेल्फी एक्सई 6 एप्लिकेशन (एक डेमो प्रोग्राम) को पहचानने की कोशिश की है जिसे मैं बनाने की कोशिश कर रहा हूं, और यह मेरे आवेदन को पहचानने के लिए है, जो कि मैनिफेस्ट तकनीक द्वारा पूरी तरह से प्रति-मॉनिटर डीपीआई को अवगत कराता है। डेल्फी XE6 (और डेल्फी के सभी अन्य समान संस्करण) परियोजना विकल्पों के अंदर, एक मैनिफेस्ट को आसान बनाने के लिए जोड़ते हैं, और मैंने ऐसा किया है।

यह एमएसडीएन संसाधनों का उपयोग करके निर्धारित किया गया है। मुझे संदेह है कि यह थोड़ा गलत हो सकता है।

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

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0" xmlns:asmv3="urn:schemas-microsoft-com:asm.v3" >
  <!-- Per Monitor DPI Awareness in Windows 8.1 uses asmv3:application + asmv3:windowsSettings -->
  <asmv3:application>
    <asmv3:windowsSettings xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">
      <dpiAware>True</dpiAware>
    </asmv3:windowsSettings>
  </asmv3:application>

  <!-- Dear Microsoft, Don't Lie to Me About What Version of Windows I am On -->
  <compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
    <application>
      <!-- Windows Vista and Windows Server 2008 -->
      <supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}"/>
      <!-- Windows 7 and Windows Server 2008 R2 -->
      <supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}"/>
      <!-- Windows 8 and Windows Server 2012 -->
      <supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}"/>
      <!-- Windows 8.1 and Windows Server 2012 R2 -->
      <supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}"/>
    </application>
  </compatibility>
  <dependency>
    <dependentAssembly>
      <assemblyIdentity
        type="win32"
        name="Microsoft.Windows.Common-Controls"
        version="6.0.0.0"
        processorArchitecture="*"
        publicKeyToken="6595b64144ccf1df"
        language="*"
        />
    </dependentAssembly>
  </dependency>
</assembly>

किसी को भी काम करने के लिए यह मिल गया है? मुझे क्या लगता है कि उपरोक्त पहचान नहीं है। अगर मैं पहले SetProcessDPIAwareness(Process_Per_Monitor_DPI_Aware) कॉल करता हूं, तो GetProcessDPIAwareness(hProc,Awareness) कॉल करें, मुझे आवश्यक Awareness = Process_Per_Monitor_DPI_Aware वापस Awareness = Process_Per_Monitor_DPI_Aware , लेकिन मैंने पढ़ा है कि उस दृष्टिकोण में संभावित Awareness = Process_Per_Monitor_DPI_Aware हैं, और इसलिए मैं केवल एक कार्यशील प्रकट करना पसंद करूंगा दृष्टिकोण।

अगर मैं GetProcessDPIAwareness(hProc,Awareness) कॉल करता हूं, तो मुझे 'जागरूकता = Process_DPI_Unaware' वापस मिल जाता है।

मेरी दूसरी चिंता यह है कि एमएसडीएन स्रोतों में वे एक अतिरिक्त अभिव्यक्ति जोड़ना निर्दिष्ट करते हैं। जबकि, मैं डेल्फी XE6 की आईडीई की क्षमता को एक और केवल एक मैनिफेस्ट को मेरे एप्लिकेशन में जोड़ने की क्षमता का उपयोग कर रहा हूं। मैंने कभी नहीं देखा है कि किसी भी अतिरिक्त मेनिफेस्ट बनाम केवल एक ही समस्या थी, इसके अलावा शायद विजुअल स्टूडियो 2010 में .manifest प्रबंधन प्रणाली लंगड़ा था, और यही वजह है कि टिप मौजूद थी, और इसलिए अन्य आईडीई के लिए कोई प्रासंगिकता नहीं है / बोली।

विजुअल स्टूडियो 2013 में, प्रोजेक्ट विकल्पों के अंदर एक चेकबॉक्स है, लेकिन मेरे पास विजुअल स्टूडियो 2013 नहीं है इसलिए मैं एक कामकाजी .manifest की जांच नहीं कर सकता।

अद्यतन करें:

एक मैनिफेस्ट में एक और शॉट यहाँ दिया गया है:

<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0" xmlns:asmv3="urn:schemas-microsoft-com:asm.v3" >
  <asmv3:application>
    <asmv3:windowsSettings xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">
      <dpiAware>true</dpiAware>
    </asmv3:windowsSettings>
  </asmv3:application>
</assembly>

उपर्युक्त मिनी मेनिफेस्ट एप्लिकेशन के व्यवहार को बदलता है, लेकिन जिस तरह से मैं इसे चाहता था बिल्कुल नहीं। उपर्युक्त छोटे मैनिफेस्ट के साथ, ओल्ड विंडोज 8.0 / विंडोज 7 / विस्टा डीपीआई जागरूकता स्तर का पता चला है।

अद्यतन 2:

विचारों के लिए धन्यवाद रेमी। दिलचस्प बात यह है कि एप्लिकेशन लॉन्च की अनुमति देने के लिए पर्याप्त मान्य है। हालांकि उपर्युक्त के साथ एसएमआई / 2005 वाक्यविन्यास को मिलाकर साइड-बाय-साइड लॉन्च त्रुटि हुई। आप देख सकते हैं कि माइक्रोसॉफ्ट अपने मैनिफ़ेस्ट पर बहुत मंथन कर रहा है। ध्यान दें कि निम्नलिखित वास्तव में मेरी समस्या का समाधान नहीं करता है, लेकिन यह अभी तक एक और "संभावित आधार फ़ॉर्म" प्रदान करता है जो वास्तविक समाधान के लिए बंद हो सकता है:

 <assembly xmlns="urn:schemas-microsoft-com:asm.v3" manifestVersion="1.0" >
  <application>
    <windowsSettings xmlns="http://schemas.microsoft.com/SMI/2011/WindowsSettings">
      <dpiAware>true</dpiAware>
    </windowsSettings>
  </application>
</assembly>

अद्यतन 3:

कोड लाल अलर्ट! किसी भी डेल्फी वीसीएल अनुप्रयोग में निम्न ओएस संगतता ध्वज का उपयोग न करें: <supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}"/> OS <supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}"/> । माइक्रोसॉफ्ट में ब्रोकन माउस कैप्चर बहेवियर, ब्रोकन विन्डो पेंटिंग भयानक तरीकों से है कि मैं अनुमान लगाने में भी सक्षम नहीं हूं। इस ध्वज को मेरे आवेदन में बहुत सूक्ष्म बग के कारण चालू करना, जिसमें पेंटिंग समस्याओं, नियंत्रण पर क्लिक करने में असमर्थता (नियंत्रण में पहुंचने वाले माउस डाउन संदेश, माउस कैप्चर होने के कारण माउस), और कई अन्य समस्याएं शामिल हैं।


यह एमएसडीएन विषय पर डीपीआई-एवेयर डेस्कटॉप और Win32 अनुप्रयोगों को लिखने पर दस्तावेज है:

आवेदन मैनिफेस्ट को संशोधित करके या SetProcessDpiAwarenessAPI को कॉल करके मॉनिटर-डीपीआई के अनुसार एप्लिकेशन को चिह्नित करें। हम अनुशंसा करते हैं कि आप एप्लिकेशन मैनिफेस्ट का उपयोग करें क्योंकि एप्लिकेशन लॉन्च होने पर डीपीआई जागरूकता स्तर सेट करता है। केवल निम्नलिखित मामलों में एपीआई का प्रयोग करें:

  • आपका कोड एक डीएलएल में है जो rundll32.exe के माध्यम से चलता है। यह एक लॉन्च तंत्र है जो एप्लिकेशन मैनिफेस्ट का समर्थन नहीं करता है।
  • आपको ओएस संस्करण या अन्य विचारों के आधार पर जटिल रन-टाइम निर्णय लेने की आवश्यकता है। उदाहरण के लिए, यदि आपको विंडोज 7 पर सिस्टम-डीपीआई के बारे में पता होना चाहिए और विंडोज 8.1 पर गतिशील रूप से अवगत होना है, तो सही / पीएम मेनिफेस्ट सेटिंग का उपयोग करें।

यदि आप डीपीआई जागरूकता स्तर को सेट करने के लिए SetProcessDpiAwareness विधि का उपयोग करते हैं, तो आपको किसी भी Win32API कॉल से पहले SetProcessDpiAwareness को कॉल करना होगा जो सिस्टम को वर्चुअलाइजेशन शुरू करने के लिए मजबूर करता है।

डीपीआई जागरूकता प्रकट मूल्य, विवरण

गलत आवेदन डीपीआई-जागरूक नहीं है।

सही सिस्टम डीपीआई-जागरूक सिस्टम को सेट करता है।

विंडोज 8.1 पर प्रति-मॉनीटर , प्रति मॉनिटर-डीपीआई प्रति जागरूकता के लिए एप्लिकेशन सेट करता है। विंडोज 8 के माध्यम से विंडोज विस्टा पर, एप्लिकेशन को डीपीआई-जागरूक नहीं है।

विंडोज 8.1 पर सही / पीएम , आवेदन प्रति मॉनीटर-डीपीआई को जागरूक करता है। विंडोज 8 के माध्यम से विंडोज विस्टा पर, एप्लिकेशन को सिस्टम-डीपीआई को जागरूक करता है।

आप बस मानक डीपीआई जागरूक मैनिफेस्ट का उपयोग करते हैं लेकिन सही के बजाय सही / पीएम या प्रति-मॉनिटर निर्दिष्ट करते हैं।

वही विषय डीपीआई को जागरूक रूप से प्रकट करता है:

<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0" xmlns:asmv3="urn:schemas-microsoft-com:asm.v3" >
  <asmv3:application>
    <asmv3:windowsSettings xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">
      <dpiAware>true</dpiAware>
    </asmv3:windowsSettings>
  </asmv3:application>
</assembly>

तो, अपने चुने हुए मूल्य के साथ ट्रू को प्रतिस्थापित करें।


यह मैनिफेस्ट काम करता है लेकिन कुछ चेतावनियों के साथ:

  • Asmv1, और asm.v2 और asmv3 के बारे में विभिन्न "मेटाडेटा" मतभेदों पर ध्यान दें। शायद महत्वपूर्ण नहीं है।

  • जैसा कि दाऊद ने संभवतः True/PM मूल्य को इंगित किया, True/PM बजाए जो सभी अंतर बनाता है। माइक्रोसॉफ्ट ने स्पष्ट रूप से इसे दस्तावेज किया था। (बिताए)

  • कुछ एसएमआई / 2011 वेरिएंट एसएक्सएस लॉन्च त्रुटियों के बिना लॉन्च किए जाएंगे, लेकिन मुझे काम करने वाले एसएमआई / 2011 संस्करण नहीं मिला है।

  • एक एप्लिकेशन का उपयोग करने के बाद जो प्रति मॉनिटर एपीआई सक्षम है, और विंडोज 8.1 के रूप में परिभाषित ओएस संगतता, मुझे अपने आवेदन में कुछ हॉरबिल रिग्रेशन मिले। माइक्रोसॉफ्ट ने विंडोज 8.1 स्तर के अनुप्रयोगों में माउस फोकस व्यवहार बदल दिया है। मैं इस अनुमोदन की सिफारिश नहीं करता हूं। मैनिफ़ेस्ट के बजाय CODE के माध्यम से ऑप्ट इन करें, और <supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}"/> नीचे उदाहरण का उपयोग न करें!

एक्सएमएल यहाँ है। मुझे इस एक्सएमएल को मैकलिंग स्टैक ओवरव्लो के साथ कुछ परेशानी हो रही है, इसलिए यदि यह खराब दिखता है, तो आप स्टैक ओवरफ्लो बग देख रहे हैं।

<?xml version="1.0" encoding="utf-8" ?>
<asmv1:assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1" xmlns:asmv1="urn:schemas-microsoft-com:asm.v1" xmlns:asmv2="urn:schemas-microsoft-com:asm.v2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" >
  <assemblyIdentity version="1.0.0.0" name="MyApplication.app"/>
  <trustInfo xmlns="urn:schemas-microsoft-com:asm.v2">
    <security>
      <requestedPrivileges xmlns="urn:schemas-microsoft-com:asm.v3">
        <requestedExecutionLevel level="asInvoker" uiAccess="false" />
      </requestedPrivileges>
    </security>
  </trustInfo>

  <compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
    <application>
      <supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}"/>
    </application>
  </compatibility>

  <asmv3:application xmlns:asmv3="urn:schemas-microsoft-com:asm.v3">
    <asmv3:windowsSettings
         xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">
      <dpiAware>True/PM</dpiAware>
    </asmv3:windowsSettings>
  </asmv3:application>
</asmv1:assembly>

और आप भी teh codez कर सकते हैं:

कोड नमूना:

unit PerMonitorApi;

interface

const
   Process_DPI_Unaware = 0;
   Process_System_DPI_Aware = 1;    // Old windows 8.0
   Process_Per_Monitor_DPI_Aware = 2; // Windows 8.1

function SystemCanSupportPerMonitorDpi(AutoEnable: Boolean): Boolean; // New Windows 8.1 dpi awareness available?

function SystemCanSupportOldDpiAwareness(AutoEnable: Boolean): Boolean; // Windows Vista/ Windows 7 Global System DPI functional level.

var
   _RequestedLevelOfAwareness:LongInt;
   _ProcessDpiAwarenessValue:LongInt;

implementation

uses
   System.SysUtils,
   WinApi.Windows;

type
   TGetProcessDPIAwarenessProc = function(const hprocess: THandle; var ProcessDpiAwareness: LongInt): HRESULT; stdcall;
   TSetProcessDPIAwarenessProc = function(const ProcessDpiAwareness: LongInt): HRESULT; stdcall;

const
   E_ACCESSDENIED = $80070005;



function _GetProcessDpiAwareness(AutoEnable: Boolean): LongInt;
var
   hprocess: THandle;
   HRESULT: DWORD;
   BAwareness: Integer;
   GetProcessDPIAwareness: TGetProcessDPIAwarenessProc;
   LibHandle: THandle;
   PID: DWORD;

   function ManifestOverride: Boolean;
   var
      HRESULT: DWORD;
      SetProcessDPIAwareness: TSetProcessDPIAwarenessProc;
   begin
      Result := False;
      SetProcessDPIAwareness := TSetProcessDPIAwarenessProc(GetProcAddress(LibHandle, 'SetProcessDpiAwareness'));
      if Assigned(SetProcessDPIAwareness) and (_RequestedLevelOfAwareness>=0) then
      begin
         HRESULT := SetProcessDPIAwareness(_RequestedLevelOfAwareness ); // If we do this we don't need the manifest change.
         Result := (HRESULT = 0) or (HRESULT = E_ACCESSDENIED)
         // if Result = 80070005 then ACESS IS DENIED, means already set.
      end
   end;

begin
   Result := _ProcessDpiAwarenessValue;
   if (Result = -1) then
   begin
      BAwareness := 3;
      LibHandle := LoadLibrary('shcore.dll');
      if LibHandle <> 0 then
      begin
         if (not AutoEnable) or ManifestOverride then
         begin
            // This supercedes the Vista era IsProcessDPIAware api, and is available in Windows 8.0 and 8.1,although only
            // windows 8.1 and later will return a per-monitor-dpi-aware result.
            GetProcessDPIAwareness := TGetProcessDPIAwarenessProc(GetProcAddress(LibHandle, 'GetProcessDpiAwareness'));
            if Assigned(GetProcessDPIAwareness) then
            begin
               PID := WinApi.Windows.GetCurrentProcessId;
               hprocess := OpenProcess(PROCESS_ALL_ACCESS, False, PID);
               if hprocess > 0 then
               begin
                  HRESULT := GetProcessDPIAwareness(hprocess, BAwareness);
                  if HRESULT = 0 then
                     Result := BAwareness;
               end;
            end;
         end;
      end;
   end;
end;

// If this returns true, this is a windows 8.1 system that has Per Monitor DPI Awareness enabled
// at a system level.
function SystemCanSupportPerMonitorDpi(AutoEnable: Boolean): Boolean;
begin
   if AutoEnable then
   begin
    _RequestedLevelOfAwareness := Process_Per_Monitor_DPI_Aware;
    _ProcessDpiAwarenessValue := -1;
   end;
   Result := _GetProcessDpiAwareness(AutoEnable) = Process_Per_Monitor_DPI_Aware;
end;


// If this returns true, This is either a Windows 7 machine, or a Windows 8 machine, or a
// Windows 8.1 machine where the Per-DPI Monitor Awareness feature has been disabled.
function SystemCanSupportOldDpiAwareness(AutoEnable: Boolean): Boolean;
begin
   if AutoEnable then
   begin
     _RequestedLevelOfAwareness := Process_Per_Monitor_DPI_Aware;
     _ProcessDpiAwarenessValue := -1;
   end;

   Result := _GetProcessDpiAwareness(AutoEnable) = Process_System_DPI_Aware;
end;


initialization
   _ProcessDpiAwarenessValue := -1;// not yet determined.
   _RequestedLevelOfAwareness := -1;

end.






delphi-xe6