/* * Util.ExtendedDisplayIdentificationData.cs * Authors: Adam Nabinger * Copyright (c) 2007-2008 Cornell University This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ using System; using System.Collections.Generic; using Microsoft.Win32; using Microsoft.Xna.Framework.Graphics; namespace Util { /// /// Attempt to pull the device information from the windows registry. This is /very/ hardware dependent and not guaranteed to work. /// It does, however, work on the development dell laptops. /// See the DeviceInfo class for more options. /// public static class ExtendedDisplayIdentificationData { #region Fields // Array for storing all the arrays of information of the various graphics devices private static readonly byte[][] data; // Array for storing all the information for the current graphics device private static byte[] bytes; #endregion #region Properties /// /// Check if there is a profile available to read information from. /// public static bool HasProfile { get { return bytes != null; } } /// /// The reported Physical Horizontal Width of the Monitor, in Millimeters. /// public static int HorizontalSize { get { #if DEBUG if (!HasProfile) { throw new InvalidOperationException("This is not guaranteed to work. Check if the EDID Has Profile first!"); } #endif return getHorizontalSize(bytes); } } /// /// The reported Physical Vertical Height of the Monitor, in Millimeters. /// public static int VerticalSize { get { #if DEBUG if (!HasProfile) { throw new InvalidOperationException("This is not guaranteed to work. Check if the EDID Has Profile first!"); } #endif return getVerticalSize(bytes); } } /// /// The reported Horizontal Resolution of the Monitor, in Pixels. /// public static int HorizontalResolution { get { #if DEBUG if (!HasProfile) { throw new InvalidOperationException("This is not guaranteed to work. Check if the EDID Has Profile first!"); } #endif return getHorizontalResolution(bytes); } } /// /// The reported Vertical Resolution of the Monitor, in Pixels. /// public static int VerticalResolution { get { #if DEBUG if (!HasProfile) { throw new InvalidOperationException("This is not guaranteed to work. Check if the EDID Has Profile first!"); } #endif return getVerticalResolution(bytes); } } #endregion #region Creation /// /// Constructor /// static ExtendedDisplayIdentificationData() { List list = new List(); try { RegistryKey DisplayKey = Registry.LocalMachine.OpenSubKey("SYSTEM").OpenSubKey("CurrentControlSet").OpenSubKey("Enum").OpenSubKey("DISPLAY"); foreach (string s in DisplayKey.GetSubKeyNames()) { RegistryKey MonitorKey = DisplayKey.OpenSubKey(s); foreach (string x in MonitorKey.GetSubKeyNames()) { list.Add((byte[])MonitorKey.OpenSubKey(x).OpenSubKey("Device Parameters").GetValue("EDID")); } } } catch(NullReferenceException) { // Error reading from registry, stop and use what we've got so far. } data = list.ToArray(); } #endregion #region Getters /// /// Gets the horizontal resolution of the current graphics device /// /// The array of information for the current graphics device /// The horizontal resolution of the current graphics device private static int getHorizontalResolution(byte[] p_bytes) { return ((((240 & (p_bytes[58])) >> 4) << 8) | p_bytes[56]); } /// /// Gets the verticle resolution of the current graphics device /// /// The array of information for the current graphics device /// The verticle resolution of the current graphics device private static int getVerticalResolution(byte[] p_bytes) { return ((((240 & (p_bytes[61])) >> 4) << 8) | p_bytes[59]); } /// /// Gets the horizontal size of the current graphics device /// /// The array of information for the current graphics device /// The horizontal size of the current graphics device private static int getHorizontalSize(byte[] p_bytes) { return ((((240 & (p_bytes[68])) >> 4) << 8) | p_bytes[66]); } /// /// Gets the verticle size of the current graphics device /// /// The array of information for the current graphics device /// The verticle size of the current graphics device private static int getVerticalSize(byte[] p_bytes) { return (((15 & (p_bytes[68])) << 4) | p_bytes[67]); } #endregion #region Setters /// /// The EDID data may contain multiple devices, such as for example, on a dual-monitor machine. /// We pick a dataset that matches the known information about the graphics device we're being displayed on. /// /// The graphics device to set as active public static void SetActiveDevice(GraphicsDevice device) { bytes = null; foreach (byte[] b in data) { if (b == null) { continue; } if (getHorizontalResolution(b) != device.DisplayMode.Width || getVerticalResolution(b) != device.DisplayMode.Height) { continue; } #if DEBUG if (bytes != null) { Console.WriteLine("Debug: More than one possible matching display device EDID"); } #endif bytes = b; #if !DEBUG return; #endif } } #endregion } }