2014-09-29 91 views
2

所以,Delphi程序不是DPI的意識。直到最近,當我需要具有高DPI的計算機中的真實屏幕分辨率(Wrong resolution reported by Screen.Width when "Make it easier to read what's on screen" is 150%)時,這並沒有讓我感到困擾。一些建議是讓應用程序高DPI知道(XML清單),但其他人警告我們,這涉及到很多工作!所以,懶惰(或缺乏時間),我想知道是否有一個技巧來計算真實的分辨率。如何在高DPI系統中獲得真實的屏幕分辨率?

一個非常骯髒的技巧,我想到的將是創建一個DPI知道的伴侶工具(小控制檯應用程序)。我所要做的就是調用這個工具並從中獲得真正的分辨率。 漂亮斯巴達,但它應該工作。無論如何,必須有更好的方式來做到這一點!

回答

4

Win32_DesktopMonitor WMI類將產生信息。

例如,使用從這裏取代碼:Delphi7: Get attached monitor properties

{$APPTYPE CONSOLE} 

uses 
    SysUtils, 
    ActiveX, 
    ComObj, 
    Variants; 

function VarStrNull(VarStr: OleVariant): string; 
// dummy function to handle null variants 
begin 
    Result := ''; 
    if not VarIsNull(VarStr) then 
    Result := VarToStr(VarStr); 
end; 

procedure GetMonitorInfo; 
var 
    objWMIService: OleVariant; 
    colItems: OleVariant; 
    colItem: OleVariant; 
    oEnum: IEnumvariant; 
    iValue: LongWord; 

    function GetWMIObject(const objectName: String): IDispatch; 
    var 
    chEaten: Integer; 
    BindCtx: IBindCtx; 
    Moniker: IMoniker; 
    begin 
    OleCheck(CreateBindCtx(0, BindCtx)); 
    OleCheck(MkParseDisplayName(BindCtx, StringToOleStr(objectName), chEaten, 
     Moniker)); 
    OleCheck(Moniker.BindToObject(BindCtx, nil, IDispatch, Result)); 
    end; 

begin 
    objWMIService := GetWMIObject('winmgmts:\\localhost\root\CIMV2'); 
    colItems := objWMIService.ExecQuery 
    ('SELECT * FROM Win32_DesktopMonitor', 'WQL', 0); 
    oEnum := IUnknown(colItems._NewEnum) as IEnumvariant; 
    while oEnum.Next(1, colItem, iValue) = 0 do 
    begin 
    Writeln('Caption  ' + VarStrNull(colItem.Caption)); 
    Writeln('Device ID ' + VarStrNull(colItem.DeviceID)); 
    Writeln('Width  ' + VarStrNull(colItem.ScreenWidth)); 
    Writeln('Height  ' + VarStrNull(colItem.ScreenHeight)); 
    Writeln; 
    end; 
end; 

begin 
    try 
    CoInitialize(nil); 
    try 
     GetMonitorInfo; 
     Readln; 
    finally 
     CoUninitialize; 
    end; 
    except 
    on E: Exception do 
    begin 
     Writeln(E.Classname, ': ', E.Message); 
     Readln; 
    end; 
    end; 
end. 

如果出於任何原因WMI不可用,那麼你需要一個獨立的DPI感知過程中做的工作。這也將需要一些IPC。

另一個問題是最近的Windows版本已經改變了這些WMI類的行爲。您可能需要使用不同的WMI查詢。看到這裏:https://social.msdn.microsoft.com/Forums/windowsdesktop/en-US/138d387c-b222-4c9f-b3bb-c69ee890491c/problem-with-win32desktopmonitor-in-windows-8-platform?forum=windowsgeneraldevelopmentissues

+0

這聽起來像一個美妙的解決方案。不幸的是,我對WMI的一些不好的經驗在某些電腦上不可用。我的程序在一些WMI函數之前使用。最後我不得不刪除它們。如果您在Google中搜索「WMI不可用」,則會看到很多報告。 – Ampere 2015-10-28 17:33:53

+0

@ davidhefferman-我知道爲什麼我有這麼多與WMI相關的錯誤:WMI是一種服務,在某些系統上默認情況下不會啓用! https://www.youtube.com/watch?v=JgsHfc-4TUE – Ampere 2015-10-28 18:03:29

+0

這不符合我的WMI體驗 – 2015-10-28 18:10:06