Home Dashboard Directory Help

WPF Ribbon Window: The border is too thin by omjbe



Sign in
to vote
Type: Bug
ID: 775972
Opened: 1/7/2013 7:30:41 AM
Access Restriction: Public
User(s) can reproduce this bug


The WPF 4.5 Ribbon implementation comes with some visual issues. These issues were not seen with the “Microsoft Ribbon for WPF October 2010” (http://www.microsoft.com/en-us/download/details.aspx?id=11877) implementation.

* The window content (client area) is cropped when the window is in Maximized mode.
* The window border is too thin.
* QuickAccessToolbar does not have enough “margin” to the top.
* The window title is blurry and does not have enough “margin” to the top.
Sign in to post a comment.
Posted by omjbe on 10/25/2013 at 4:18 AM
Fluent ribbon or any other 3rd party library is not an option for us. Our applications have a lifetime of more than 10 years. Such libraries are seldom maintained that long and we do not have the time to do it ourselves. Therefore, we stick to the official .NET Framework API which is supported for a long time.
Posted by Staeff on 10/25/2013 at 3:21 AM
Just use Fluent ribbon library, it's much more convenient to use and also has Office 2013 styles. fluent.codeplex.com
Posted by omjbe on 10/24/2013 at 7:33 AM
Please review this issue again because none of the workarounds seems to work. This is a very serious issue for us.
Posted by Microsoft on 3/29/2013 at 11:22 AM
The WPF team has recently reviewed this issue and will not be addressing this issue as at this time the team is focusing on the bugs impacting the highest number of WPF developers. If you believe that this was resolved in error, please reactivate this bug with any necessary supporting details.

We appreciate the feedback. However, this issue will not be addressed in the next version of WPF. Thank you.
–WPF Team.
Posted by Microsoft on 1/7/2013 at 6:29 PM
Thank you for submitting feedback on Visual Studio and .NET Framework. Your issue has been routed to the appropriate VS development team for investigation. We will contact you if we require any additional information.
Posted by Microsoft on 1/7/2013 at 7:50 AM
Thank you for your feedback, we are currently reviewing the issue you have submitted. If this issue is urgent, please contact support directly(http://support.microsoft.com)
Sign in to post a workaround.
Posted by Tom Zschaage on 1/9/2014 at 12:21 AM
The Workaround described by trytryrtyrtyrtytyty (with the SetWindowPos) works under Windows 7 with Aero active. If Aero is not active top left border is fine but height and width are missing two pixels. Therefore you can see the backround on the right and bottom edges.
Another altough not good solution would be to stick with the wrong window size and adjust the margins of the visible contents, like this.

        private static void UpdateMargins(RibbonWindow window)
            if (window.WindowState == WindowState.Minimized) return;

            var grid = window.GetVisualChilds<Grid>(X.SearchStrategy.BreadthFirstSearch).FirstOrDefault();
            if (grid == null) return;

            Border outerBorder = null;
            Border mainBorder = null;
            foreach (var border in grid.GetVisualChilds<Border>(X.SearchStrategy.BreadthFirstSearch)) {
                if (border.Name.Equals("NonClientAreaBorder") || border.Name.Equals("PART_ClientAreaBorder")) {
                } else if (border.Name.Equals("OuterBorder")) {
                    outerBorder = border;
                } else {
                    mainBorder = border;
            if (mainBorder == null) return;

            if (outerBorder != null) {
                // Aero-Style ist aus
                var image = outerBorder.GetVisualChilds<Image>(X.SearchStrategy.BreadthFirstSearch).FirstOrDefault();
                if (image == null) return;

                if (window.WindowState == WindowState.Maximized) {
                    image.Margin = new Thickness(4, 0, 0, 0);
                    mainBorder.Margin = new Thickness(4, 0, 4, 4);
                } else {
                    image.Margin = new Thickness(0);
                    mainBorder.Margin = new Thickness(0);
            } else {
                // Aero-Style ist aktiv
                var image = mainBorder.GetVisualChilds<Image>(X.SearchStrategy.BreadthFirstSearch).FirstOrDefault();
                if (image == null) return;

                var titleHost = grid.GetVisualChilds<ContentPresenter>(X.SearchStrategy.BreadthFirstSearch)
                    .FirstOrDefault(v => v.Name.Equals("PART_TitleHost"));
                if (titleHost == null) return;

                if (window.WindowState == WindowState.Maximized) {
                    image.Margin = new Thickness(1, 4, 0, 0);
                    titleHost.Margin = new Thickness(0, 6, 3, 0);
                    mainBorder.Margin = new Thickness(4, 0, 4, 4);
                } else {
                    image.Margin = new Thickness(0, 2, 0, 0);
                    titleHost.Margin = new Thickness(3, 3, 3, 0); // default ist eigentlich 3, 0, 3, 0
                    mainBorder.Margin = new Thickness(0);
Posted by trytryrtyrtyrtytyty on 12/17/2013 at 12:22 AM
Hoera, as a side efffect this seems to fix the problem with autohide taskbar also!!!!


So the RibbonWindow is now finally usable.
Posted by trytryrtyrtyrtytyty on 12/16/2013 at 8:55 AM
The subsystemversion hack is no longer supported in Visual Studio 2012 SP2 and higher, the closed the hack and didn't fix the bug, and was fishy at least.
The code below takes care of the Maximize problem , there might be a bug in GetWindowRect on Vista with multiple monitors.
But I leave that for somebody who actually uses Vista to complete the code if neccessary
Posted by trytryrtyrtyrtytyty on 12/16/2013 at 8:47 AM
This takes care of it in all cases under Windows 7 with no side effects, cost two full days of searching, maybe I can bill MS?

#region FixMaximize

        public static readonly DependencyProperty FixMaximizeProperty =
                new FrameworkPropertyMetadata(false, FixMaximizeChanged));

        public static void SetFixMaximize(RibbonWindow ribbonWindow, bool value)
            ribbonWindow.SetValue(FixMaximizeProperty, value);

        public static bool GetFixMaximize(RibbonWindow ribbonWindow)
            return (bool)ribbonWindow.GetValue(FixMaximizeProperty);

        private static void FixMaximizeChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
            RibbonWindow ribbonWindow = (RibbonWindow)d;
            if ((bool)e.NewValue == true)
                ribbonWindow.SourceInitialized += FixMaximize_RibbonWindow_SourceInitialized;

        static void FixMaximize_RibbonWindow_SourceInitialized(object sender, System.EventArgs e)
            RibbonWindow ribbonWindow = (RibbonWindow)sender;
            HwndSource source = HwndSource.FromHwnd(new WindowInteropHelper(ribbonWindow).Handle);
            source.AddHook(new HwndSourceHook(FixMaximize_RibbonWindow_WndProc));

        private static IntPtr FixMaximize_RibbonWindow_WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
            const int WM_GETMINMAXINFO = 0x0024;
            const uint SWP_NOOWNERZORDER = 0x0200;
            const uint SWP_NOSIZE = 0x0001;
            const int SIZE_MAXIMIZED = 0x2;
            const int WM_SIZE = 0x0005;
            if (msg == WM_SIZE && wParam.ToInt32() == SIZE_MAXIMIZED)
                RECT rect = new RECT();
                GetWindowRect(hwnd, out rect); // to compensate for multiple monitor offset
                SetWindowPos(hwnd, IntPtr.Zero, rect.left - 1 - 4, rect.top - 1 - 4, 0, 0, SWP_NOSIZE | SWP_NOOWNERZORDER); // we need to go from (de)fault (-8,-8) to (-4,-4) we are currently at (1,1)
            else if (msg == WM_GETMINMAXINFO)
                MINMAXINFO mmi = (MINMAXINFO)Marshal.PtrToStructure(lParam, typeof(MINMAXINFO));
                mmi.ptMaxSize.x -= 8; // we are missing 4 pixels left and right
                mmi.ptMaxSize.y -= 8; // we are missing 4 pixels top and bottom
                mmi.ptMaxPosition.x = 1; // need to set this to positive value for MaxSize to have any effect, we will reposition later anyway
                mmi.ptMaxPosition.y = 1; // need to set this to positive value for MaxSize to have any effect, we will reposition later anyway
                Marshal.StructureToPtr(mmi, lParam, false);
            return IntPtr.Zero;

        static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int X, int Y, int cx, int cy, uint uFlags);

        public static extern bool GetWindowRect(IntPtr hwnd, out RECT lpRect);

        public struct MINMAXINFO
            public POINT ptReserved;
            public POINT ptMaxSize;
            public POINT ptMaxPosition;
            public POINT ptMinTrackSize;
            public POINT ptMaxTrackSize;

        public struct POINT
            public int x;
            public int y;

        [StructLayout(LayoutKind.Sequential, Pack = 0)]
        public struct RECT
            public int left;
            public int top;
            public int right;
            public int bottom;


Posted by Olly A on 3/27/2013 at 6:22 AM
The issue is described here: http://stackoverflow.com/questions/12567455/wpf-ribbonwindow-ribbon-title-outside-screen.

There is a workaround. Specify the /subsystemversion compiler switch, and set the value to be 5.01. This falsely indicates to the compiler that the code might run on XP. You can set the property by inserting <subsystemversion>5.0</subsystemversion> into a <PropertyGroup> in the project file. (In VS, right click on the project and choose Unload. Right click again and a new option is available to edit the project file. After making the change, use the Reload option on the right click menu.)
File Name Submitted By Submitted On File Size  
WpfRibbonIssue.png 1/7/2013 66 KB
WpfRibbonIssue.zip 1/7/2013 10 KB