Get real screen size

Is it possible to get the real screen size in cm not in pixels? those. I need to know the screen size, not its resolution.

I need this if possible in a windows application.

+3


source to share


2 answers


All information about the screen (from the manufacturer) is in the registry HKLM\SYSTEM\CurrentControlSet\Enum\DISPLAY

. The screen size is encoded and difficult to find, but it is possible.

For more information, search the Internet for: EDID ("Extended Display Identity") ( http://en.wikipedia.org/wiki/Extended_display_identification_data , bytes for size # 21 and # 22)

Here's the code I use to be sized (and more info, but I cleaned up the code to only be sized):

// 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]);
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}

      

The size is in cm (integer only).

You can have this physical ratio and diagonal:



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);
}

      

Edit: How to have the monitor name (all connected monitors):

[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;
}

      

and finish:

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);
}

      

+4


source


I found this

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;
   }
  }
}

      

which uses PInvoke to get DPI in another question on the subject, and I'm posting it here because I've only seen links.



I will mention that this is not a common thing and I don't know why you need it. this sounds like an AB problem, so I will say that you need to be absolutely sure you need DPI before using this

look at Lasse W. Carlsen, please comment. it may not be accurate, so be careful

+3


source







All Articles