Zune Window in WPF

I have become a huge fan of Metro UI design and i really like the Zune interface and the starting point would be the custom chrome so i searched a bit and found this neat little thing , thought I would share

 /// <summary>
    /// Borderless Window Behavior
    /// </summary>
    public class BorderlessWindowBehavior : Behavior<window>
    {
        #region Native Methods
 
        [StructLayout(LayoutKind.Sequential)]
        public struct MARGINS
        {
            public int leftWidth;
            public int rightWidth;
            public int topHeight;
            public int bottomHeight;
        }
 
        [DllImport("dwmapi.dll")]
        private static extern int DwmExtendFrameIntoClientArea(IntPtr hWnd, ref MARGINS pMarInset);
 
        /// <summary>
        /// POINT aka POINTAPI
        /// </summary>
        [StructLayout(LayoutKind.Sequential)]
        public struct POINT
        {
            /// <summary>
            /// x coordinate of point.
            /// </summary>
            public int x;
 
            /// <summary>
            /// y coordinate of point.
            /// </summary>
            public int y;
 
            /// <summary>
            /// Construct a point of coordinates (x,y).
            /// </summary>
            public POINT(int x, int y)
            {
                this.x = x;
                this.y = y;
            }
        }
 
        [StructLayout(LayoutKind.Sequential)]
        public struct MINMAXINFO
        {
            public POINT ptReserved;
            public POINT ptMaxSize;
            public POINT ptMaxPosition;
            public POINT ptMinTrackSize;
            public POINT ptMaxTrackSize;
        };
 
        /// <summary>
        /// </summary>
        [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
        public class MONITORINFO
        {
            public int cbSize = Marshal.SizeOf(typeof(MONITORINFO));
 
            public RECT rcMonitor = new RECT();
 
            public RECT rcWork = new RECT();
 
            public int dwFlags = 0;
        }
 
 
        /// <summary> Win32 </summary>
        [StructLayout(LayoutKind.Sequential, Pack = 0)]
        public struct RECT
        {
            /// <summary>
            /// Win32
            /// </summary>
            public int left;
 
            /// <summary>
            /// Win32
            /// </summary>
            public int top;
 
            /// <summary>
            /// Win32
            /// </summary>
            public int right;
 
            /// <summary>
            /// Win32
            /// </summary>
            public int bottom;
 
            /// <summary>
            /// Win32
            /// </summary>
            public static readonly RECT Empty = new RECT();
 
            /// <summary>
            /// Win32
            /// </summary>
            public int Width
            {
                // Abs needed for BIDI OS
                get { return Math.Abs(right - left); }  
            }
 
            /// <summary>
            /// Win32
            /// </summary>
            public int Height
            {
                get { return bottom - top; }
            }
 
            /// <summary>
            /// Win32
            /// </summary>
            /// <param name="left">The left.</param>
            /// <param name="top">The top.</param>
            /// <param name="right">The right.</param>
            /// <param name="bottom">The bottom.</param>
            public RECT(int left, int top, int right, int bottom)
            {
                this.left = left;
                this.top = top;
                this.right = right;
                this.bottom = bottom;
            }
 
            /// <summary>
            /// Win32
            /// </summary>
            /// <param name="rcSrc">The rc SRC.</param>
            public RECT(RECT rcSrc)
            {
                this.left = rcSrc.left;
                this.top = rcSrc.top;
                this.right = rcSrc.right;
                this.bottom = rcSrc.bottom;
            }
 
            /// <summary>
            /// Win32
            /// </summary>
            /// <value>
            ///   <c>true</c> if this instance is empty; otherwise, <c>false</c>.
            /// </value>
            public bool IsEmpty
            {
                get
                {
                    // BUGBUG : On Bidi OS (hebrew arabic) left > right
                    return left >= right || top >= bottom;
                }
            }
 
            /// <summary>
            /// Return a user friendly representation of this struct
            /// </summary>
            /// <returns>
            /// A <see cref="System.String"/> that represents this instance.
            /// </returns>
            public override string ToString()
            {
                if (this == RECT.Empty) 
                    return "RECT {Empty}";
 
                return String.Format("RECT {{ left : {0} / top : {1} / right : {2} / bottom : {3} }}", left, top, right, bottom);
            }
 
            /// <summary>
            /// Determine if 2 RECT are equal (deep compare)
            /// </summary>
            /// <param name="obj">The <see cref="System.Object"/> to compare with this instance.</param>
            /// <returns>
            ///   <c>true</c> if the specified <see cref="System.Object"/> is equal to this instance; otherwise, <c>false</c>.
            /// </returns>
            public override bool Equals(object obj)
            {
                if (!(obj is Rect))
                    return false;
 
                return (this == (RECT)obj);
            }
 
            /// <summary>
            /// Return the HashCode for this struct (not guaranteed to be unique)
            /// </summary>
            /// <returns>
            /// A hash code for this instance, suitable for use in hashing algorithms and data structures like a hash table. 
            /// </returns>
            public override int GetHashCode()
            {
                return left.GetHashCode() + top.GetHashCode() + right.GetHashCode() + bottom.GetHashCode();
            }
 
            /// <summary>
            /// Determine if 2 RECT are equal (deep compare)
            /// </summary>
            /// <param name="rect1">The rect1.</param>
            /// <param name="rect2">The rect2.</param>
            /// <returns>
            /// The result of the operator.
            /// </returns>
            public static bool operator ==(RECT rect1, RECT rect2)
            {
                return (rect1.left == rect2.left && rect1.top == rect2.top && rect1.right == rect2.right && rect1.bottom == rect2.bottom);
            }
 
            /// <summary>
            /// Determine if 2 RECT are different (deep compare)
            /// </summary>
            /// <param name="rect1">The rect1.</param>
            /// <param name="rect2">The rect2.</param>
            /// <returns>
            /// The result of the operator.
            /// </returns>
            public static bool operator !=(RECT rect1, RECT rect2)
            {
                return !(rect1 == rect2);
            }
        }
 
        /// <summary>
        /// Gets the monitor info.
        /// </summary>
        /// <param name="hMonitor">The h monitor.</param>
        /// <param name="lpmi">The lpmi.</param>
        /// <returns></returns>
        [DllImport("user32")]
        internal static extern bool GetMonitorInfo(IntPtr hMonitor, MONITORINFO lpmi);
 
        /// <summary>
        /// Monitors from window.
        /// </summary>
        /// <param name="handle">The handle.</param>
        /// <param name="flags">The flags.</param>
        /// <returns></returns>
        [DllImport("User32")]
        internal static extern IntPtr MonitorFromWindow(IntPtr handle, int flags);
 
        /// <summary>
        /// Wms the get min max info.
        /// </summary>
        /// <param name="hwnd">The HWND.</param>
        /// <param name="lParam">The l param.</param>
        private static void WmGetMinMaxInfo(System.IntPtr hwnd, System.IntPtr lParam)
        {
            MINMAXINFO mmi = (MINMAXINFO)Marshal.PtrToStructure(lParam, typeof(MINMAXINFO));
 
            // Adjust the maximized size and position to fit the work area of the correct monitor
            int MONITOR_DEFAULTTONEAREST = 0x00000002;
            System.IntPtr monitor = MonitorFromWindow(hwnd, MONITOR_DEFAULTTONEAREST);
 
            if (monitor != System.IntPtr.Zero)
            {
                MONITORINFO monitorInfo = new MONITORINFO();
                GetMonitorInfo(monitor, monitorInfo);
                RECT rcWorkArea = monitorInfo.rcWork;
                RECT rcMonitorArea = monitorInfo.rcMonitor;
                mmi.ptMaxPosition.x = Math.Abs(rcWorkArea.left - rcMonitorArea.left);
                mmi.ptMaxPosition.y = Math.Abs(rcWorkArea.top - rcMonitorArea.top);
                mmi.ptMaxSize.x = Math.Abs(rcWorkArea.right - rcWorkArea.left);
                mmi.ptMaxSize.y = Math.Abs(rcWorkArea.bottom - rcWorkArea.top);
            }
 
            Marshal.StructureToPtr(mmi, lParam, true);
        }
 
        /// <summary>
        /// Defs the window proc.
        /// </summary>
        /// <param name="hwnd">The HWND.</param>
        /// <param name="msg">The MSG.</param>
        /// <param name="wParam">The w param.</param>
        /// <param name="lParam">The l param.</param>
        /// <returns></returns>
        [DllImport("user32.dll")]
        public static extern IntPtr DefWindowProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam);
 
        #endregion
 
        private const int WM_NCCALCSIZE = 0x83;
        private const int WM_NCPAINT = 0x85;
        private const int WM_NCACTIVATE = 0x86;
        private const int WM_GETMINMAXINFO = 0x24;
 
        private HwndSource m_hwndSource;
        private IntPtr m_hwnd;
 
        public static DependencyProperty ResizeWithGripProperty = DependencyProperty.Register("ResizeWithGrip", typeof(bool), typeof(BorderlessWindowBehavior), new PropertyMetadata(true));
 
        /// <summary>
        /// Gets or sets a value indicating whether [resize with grip].
        /// </summary>
        /// <value>
        ///   <c>true</c> if [resize with grip]; otherwise, <c>false</c>.
        /// </value>
        public bool ResizeWithGrip
        {
            get { return (bool)GetValue(ResizeWithGripProperty); }
            set { SetValue(ResizeWithGripProperty, value); }
        }
 
        /// <summary>
        /// Called after the behavior is attached to an AssociatedObject.
        /// </summary>
        protected override void OnAttached()
        {
            if (AssociatedObject.IsInitialized)
                AddHwndHook();
            else
                AssociatedObject.SourceInitialized += AssociatedObject_SourceInitialized;
 
            AssociatedObject.WindowStyle = WindowStyle.None;
            AssociatedObject.ResizeMode = ResizeWithGrip ? ResizeMode.CanResizeWithGrip : ResizeMode.CanResize;
 
            base.OnAttached();
        }
 
        /// <summary>
        /// Called when the behavior is being detached from its AssociatedObject, but before it has actually occurred.
        /// </summary>
        protected override void OnDetaching()
        {
            RemoveHwndHook();
            base.OnDetaching();
        }
 
        /// <summary>
        /// Adds the HWND hook.
        /// </summary>
        private void AddHwndHook()
        {
            m_hwndSource = HwndSource.FromVisual(AssociatedObject) as HwndSource;
            m_hwndSource.AddHook(HwndHook);
            m_hwnd = new WindowInteropHelper(AssociatedObject).Handle;
        }
 
        /// <summary>
        /// Removes the HWND hook.
        /// </summary>
        private void RemoveHwndHook()
        {
            AssociatedObject.SourceInitialized -= AssociatedObject_SourceInitialized;
            m_hwndSource.RemoveHook(HwndHook);
        }
 
        /// <summary>
        /// Handles the SourceInitialized event of the AssociatedObject control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        private void AssociatedObject_SourceInitialized(object sender, EventArgs e)
        {
            AddHwndHook();
        }
 
        /// <summary>
        /// HWNDs the hook.
        /// </summary>
        /// <param name="hWnd">The h WND.</param>
        /// <param name="message">The message.</param>
        /// <param name="wParam">The w param.</param>
        /// <param name="lParam">The l param.</param>
        /// <param name="handled">if set to <c>true</c> [handled].</param>
        /// <returns></returns>
        private IntPtr HwndHook(IntPtr hWnd, int message, IntPtr wParam, IntPtr lParam, ref bool handled)
        {
            IntPtr returnval = IntPtr.Zero;
 
            switch (message)
            {
                case WM_NCCALCSIZE:
                    /* Hides the border */
                    handled = true;
                    break;
                case WM_NCPAINT:
                    {
                        if (Environment.OSVersion.Version.Major >= 6)
                        {
                            var m = new MARGINS { bottomHeight = 1, leftWidth = 1, rightWidth = 1, topHeight = 1 };
                            DwmExtendFrameIntoClientArea(m_hwnd, ref m);
                        }
                        handled = true;
                    }
                    break;
                case WM_NCACTIVATE:
                    {
                        /* As per http://msdn.microsoft.com/en-us/library/ms632633(VS.85).aspx , "-1" lParam
                         * "does not repaint the nonclient area to reflect the state change." */
                        returnval = DefWindowProc(hWnd, message, wParam, new IntPtr(-1));
                        handled = true;
                    }
                    break;
                case WM_GETMINMAXINFO:
                    /* From Lester's Blog (thanks @aeoth):  
                     * http://blogs.msdn.com/b/llobo/archive/2006/08/01/maximizing-window-_2800_with-windowstyle_3d00_none_2900_-considering-taskbar.aspx */
                    WmGetMinMaxInfo(hWnd, lParam);
                    handled = true;
                    break;
            }
 
            return returnval;
        }
    }
}
</window>
04
Jul 2011
Author naresh
Category

.net Programming

Comments 2 Comments
TAGS

, ,

2 Responses to “Zune Window in WPF”

  1. How and where to use this code bro? Can you please guide me?

  2. naresh says:

    To use this behavior to your window init code add

    var collection = System.Windows.Interactivity.Interaction.GetBehaviors(this);
    collection.Add(new BorderlessWindowBehavior());

    Hope this helps

Leave a Reply