2014-11-05 80 views
3

是否有可能得到以釐米爲單位的實際屏幕大小不是以像素爲單位?即我需要知道屏幕的大小而不是其分辨率。獲取屏幕的實際大小

我需要這個,如果它可能在Windows應用程序。

+1

是的,這是可能的;) – Xaruth 2014-11-05 13:38:33

+0

@Xaruth我想你的'wro ng:http://stackoverflow.com/questions/6363752/acquire-monitor-physical-dimension – 2014-11-05 13:39:10

+0

請參閱http://ofekshilon.com/2011/11/13/reading-monitor-physical-dimensions-or-getting-the -edid-the-right-way /不確定這是否準確或不正確,因爲@NoIdeaForName發佈了一個問題的鏈接,如果你按照鏈接重複它指的是回答說不,無法完成。 – 2014-11-05 13:44:22

回答

4

有關屏幕(製造商)的所有信息都在註冊表HKLM\SYSTEM\CurrentControlSet\Enum\DISPLAY。屏幕的大小被編碼,很難找到,但這是可能的。

有關詳細信息,在網絡上的搜索:EDID(「擴展顯示標識數據」)(http://en.wikipedia.org/wiki/Extended_display_identification_data,對於大小的字節是#21,#22)

在這裏,我使用的代碼有大小(和更多的信息,但我清理的代碼只有大小):

// Open the Display Reg-Key 
RegistryKey displayRegistry = Registry.LocalMachine; 
Boolean isFailed = false; 
try 
{ 
    displayRegistry = Registry.LocalMachine.OpenSubKey(@"SYSTEM\CurrentControlSet\Enum\DISPLAY"); 
} 
catch 
{ 
    isFailed = true; 
} 

if (!isFailed & (displayRegistry != null)) 
{ 
    // Get all MonitorIDss 
    foreach (String monitorID in displayRegistry.GetSubKeyNames()) 
    { 
     if (monitorID == name) 
     { 
      RegistryKey monitorIDRegistry = displayRegistry.OpenSubKey(monitorID); 

      if (monitorIDRegistry != null) 
      { 
       // Get all Plug&Play ID's 
       foreach (String subname in monitorIDRegistry.GetSubKeyNames()) 
       { 
        RegistryKey pnpID = monitorIDRegistry.OpenSubKey(subname); 
        if (pnpID != null) 
        { 
         String[] subkeys = pnpID.GetSubKeyNames(); 

         // Check if Monitor is active 
         if (subkeys.Contains("Control")) 
         { 
          if (subkeys.Contains("Device Parameters")) 
          { 
           RegistryKey devParam = pnpID.OpenSubKey("Device Parameters"); 

           Int16 sizeH = 0; 
           Int16 sizeV = 0; 

           // Get the EDID code 
           byte[] edidObj = devParam.GetValue("EDID", null) as byte[]; 
           if (edidObj != null) 
           { 
            sizeH = Convert.ToInt16(Encoding.Default.GetString(edidObj, 0x15, 1)[0]); 
            sizeV = Convert.ToInt16(Encoding.Default.GetString(edidObj, 0x16, 1)[0]); 
           } 
          } 
         } 
        } 
       } 
      } 
     } 
    } 
} 

大小是釐米(只有它的整數)。

你可以有這個身體比例和對角線:

private static String GetRatio(Double MaxSizeH, Double MaxSizeV) 
{ 
    if (MaxSizeV == 0) 
    { 
     return "undefined"; 
    } 

    Double ratio = MaxSizeH/MaxSizeV; 

    String strRatio = "4/3"; 
    Double ecartRatio = Math.Abs(ratio - (4/(Double)3)); 

    if (Math.Abs(ratio - (16/(Double)10)) < ecartRatio) 
    { 
     ecartRatio = Math.Abs(ratio - (16/(Double)10)); 
     strRatio = "16/10"; 
    } 

    if (Math.Abs(ratio - (16/(Double)9)) < ecartRatio) 
    { 
     ecartRatio = Math.Abs(ratio - (16/(Double)9)); 
     strRatio = "16/9"; 
    } 

    return strRatio; 
} 

// diagonal in inch 
private static Double GetDiagonale(Double MaxSizeH, Double MaxSizeV) 
{ 
    return 0.3937 * Math.Sqrt(MaxSizeH * MaxSizeH + MaxSizeV * MaxSizeV); 
} 

編輯:如何擁有監視器名稱(所有連接的顯示器):

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)] 
public struct DISPLAY_DEVICE 
{ 
    [MarshalAs(UnmanagedType.U4)] 
    public int cb; 

    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)] 
    public string DeviceName; 

    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)] 
    public string DeviceString; 

    [MarshalAs(UnmanagedType.U4)] 
    public DisplayDeviceStateFlags StateFlags; 

    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)] 
    public string DeviceID; 

    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)] 
    public string DeviceKey; 
} 

[Flags] 
public enum DisplayDeviceStateFlags : int 
{ 
    /// <summary>The device is part of the desktop.</summary> 
    AttachedToDesktop = 0x1, 

    MultiDriver = 0x2, 

    /// <summary>The device is part of the desktop.</summary> 
    PrimaryDevice = 0x4, 

    /// <summary>Represents a pseudo device used to mirror application drawing for remoting or other purposes.</summary> 
    MirroringDriver = 0x8, 

    /// <summary>The device is VGA compatible.</summary> 
    VGACompatible = 0x10, 

    /// <summary>The device is removable; it cannot be the primary display.</summary> 
    Removable = 0x20, 

    /// <summary>The device has more display modes than its output devices support.</summary> 
    ModesPruned = 0x8000000, 

    Remote = 0x4000000, 
    Disconnect = 0x2000000 
} 

[DllImport("User32.dll")] 
public static extern int EnumDisplayDevices(string lpDevice, int iDevNum, ref DISPLAY_DEVICE lpDisplayDevice, int dwFlags); 


private static List<NativeMethods.DISPLAY_DEVICE> GetAllDevice() 
{ 
    List<NativeMethods.DISPLAY_DEVICE> devices = new List<NativeMethods.DISPLAY_DEVICE>(); 
    bool error = false; 
    for (int devId = 0; !error; devId++) 
    { 
     try 
     { 
      NativeMethods.DISPLAY_DEVICE device = new NativeMethods.DISPLAY_DEVICE(); 
      device.cb = Marshal.SizeOf(typeof(NativeMethods.DISPLAY_DEVICE)); 
      error = NativeMethods.EnumDisplayDevices(null, devId, ref device, 0) == 0; 
      if (String.IsNullOrWhiteSpace(device.DeviceID) == false) 
      { 
       devices.Add(device); 
      } 
     } 
     catch (Exception) 
     { 
      error = true; 
     } 
    } 

    return devices; 
} 

,並完成:

List<NativeMethods.DISPLAY_DEVICE> devices = GetAllDevice(); 

foreach (NativeMethods.DISPLAY_DEVICE device in devices) 
{ 
    NativeMethods.DISPLAY_DEVICE monitor = new NativeMethods.DISPLAY_DEVICE(); 
    monitor.cb = Marshal.SizeOf(typeof(NativeMethods.DISPLAY_DEVICE)); 
    NativeMethods.EnumDisplayDevices(device.DeviceName, 0, ref monitor, 0); 
    String monitorname = monitor.DeviceID.Split(new char[] { '\\' }, StringSplitOptions.RemoveEmptyEntries).Skip(1).FirstOrDefault(); 

    GetMonitorDetail(monitorname); 
} 
3

,我發現這個

public class NativeMethods 
{ 
    [DllImport("gdi32.dll", EntryPoint = "CreateDC", CharSet = CharSet.Auto, SetLastError = true)] 
    private static extern IntPtr CreateDC(string lpszDriver, string lpszDeviceName, string lpszOutput, IntPtr devMode); 

    [DllImport("gdi32.dll", ExactSpelling = true, SetLastError = true)] 
    static extern bool DeleteDC(IntPtr hdc); 

    [DllImport("gdi32.dll", SetLastError = true)] 
    private static extern Int32 GetDeviceCaps(IntPtr hdc, Int32 capindex); 
    private const int LOGPIXELSX = 88; 

    private static int _dpi = -1; 
    public static int DPI 
    { 
    get 
    { 
    if (_dpi != -1) 
    return _dpi; 

    _dpi = 96; 
    try 
    { 
    IntPtr hdc = CreateDC("DISPLAY", null, null, IntPtr.Zero); 
    if (hdc != IntPtr.Zero) 
    { 
     _dpi = GetDeviceCaps(hdc, LOGPIXELSX); 
     if (_dpi == 0) 
     _dpi = 96; 
     DeleteDC(hdc); 
    } 
    } 
    catch (Exception) 
    { 
    } 

    return _dpi; 
    } 
    } 
} 

使用的PInvoke得到DPI在有關這個問題的其他問題,我張貼在這裏,因爲我只看到了鏈接。

我會提及這不是一個普遍的事情,我不知道你爲什麼需要這個。這聽起來像A-B問題,所以我會說你需要絕對確定你需要使用前的DPI

請看看Lasse V. Karlsen的評論。這可能不準確,所以請小心謹慎

+0

看起來很有前途,但不確定這是多麼正確/準確。我的BENQ BL2400屏幕報道了96的DPI,並且是全高清,但這相當於22.94英寸,而不是24英寸,因爲它應該是。 – 2014-11-05 13:47:36

+0

@ LasseV.Karlsen我使用這段代碼尋找ppl,有人說它運行良好,有些人說它根本不起作用。沒有看到「不準確」的評論,但我會在答案中發佈 – 2014-11-05 13:49:19