Bookmark and Share Share...    Subscribe to this feed Feed   About Christian Moser  


WPF replacemenet for Screen.AllScreens()

Many WPF applications want to check the available screen resolution to adjust window placements of sizes. In WinForms was a nice helper called Screen.AllScreens that returned a list of screens with their corresponding resolution. To use it from WPF you have to reference System.Windows.Forms and System.Windows.Drawing which is not always what you want (because of application load time, dependencies, ambigue class names, etc.).

To get around this limitation I created a helper called Monitor which is a simple port of the Screen functionality from WinForms.

 
public class Monitor
{
    #region Dll imports
 
    [DllImport("user32.dll", CharSet = CharSet.Auto)]
    [ResourceExposure(ResourceScope.None)]
    private static extern bool GetMonitorInfo
                  (HandleRef hmonitor, [In, Out]MonitorInfoEx info);
 
    [DllImport("user32.dll", ExactSpelling = true)]
    [ResourceExposure(ResourceScope.None)]
    private static extern bool EnumDisplayMonitors
         (HandleRef hdc, IntPtr rcClip, MonitorEnumProc lpfnEnum, IntPtr dwData);
 
    private delegate bool MonitorEnumProc
                 (IntPtr monitor, IntPtr hdc, IntPtr lprcMonitor, IntPtr lParam);
 
    [StructLayout(LayoutKind.Sequential)]
    private struct Rect
    {
        public int left;
        public int top;
        public int right;
        public int bottom;
    }
 
    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto, Pack = 4)]
    private class MonitorInfoEx
    {
        internal int cbSize = Marshal.SizeOf(typeof(MonitorInfoEx));
        internal Rect rcMonitor = new Rect();
        internal Rect rcWork = new Rect();
        internal int dwFlags = 0;
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 32)]
        internal char[] szDevice = new char[32];
    }
 
    private const int MonitorinfofPrimary = 0x00000001;
 
    #endregion
 
    public static HandleRef NullHandleRef = new HandleRef(null, IntPtr.Zero);
 
    public System.Windows.Rect Bounds { get; private set; }
    public System.Windows.Rect WorkingArea { get; private set; }
    public string Name { get; private set; }
 
    public bool IsPrimary { get; private set; }
 
    private Monitor(IntPtr monitor, IntPtr hdc)
    {
        var info = new MonitorInfoEx();
        GetMonitorInfo(new HandleRef(null, monitor), info);
        Bounds = new System.Windows.Rect(
                    info.rcMonitor.left, info.rcMonitor.top, 
                    info.rcMonitor.right - info.rcMonitor.left, 
                    info.rcMonitor.bottom - info.rcMonitor.top);
        WorkingArea = new System.Windows.Rect(
                    info.rcWork.left, info.rcWork.top, 
                    info.rcWork.right - info.rcWork.left, 
                    info.rcWork.bottom - info.rcWork.top);
        IsPrimary = ((info.dwFlags & MonitorinfofPrimary) != 0);
        Name = new string(info.szDevice).TrimEnd((char)0);
    }
 
    public static IEnumerable<Monitor> AllMonitors
    {
        get
        {
            var closure = new MonitorEnumCallback();
            var proc = new MonitorEnumProc(closure.Callback);
            EnumDisplayMonitors(NullHandleRef, IntPtr.Zero, proc, IntPtr.Zero);
            return closure.Monitors.Cast<Monitor>();
        }
    }
 
    private class MonitorEnumCallback
    {
        public ArrayList Monitors { get; private set; }
 
        public MonitorEnumCallback()
        {
            Monitors = new ArrayList();
        }
 
        public bool Callback(IntPtr monitor, IntPtr hdc, 
                       IntPtr lprcMonitor, IntPtr lparam)
        {
            Monitors.Add(new Monitor(monitor, hdc));
            return true;
        }
    }
}
 
 




Last modified: 2012-12-06 16:52:36
Copyright (c) by Christian Moser, 2011.

 Comments on this article

Show all comments
No comments for this article

Name
E-Mail (optional)
Comment