RibbonWindow.Top returns wrong value -> my workaround

Ribbon for WPF Forum

Posted 8 years ago by Danilo
Avatar
I wanted to serialize my RibbonWindow coordinates
and maximize state today.
RibbonWindow.Top always returned a smaller value
than the real window size. So i always had to
add 26 to mainWindow.Top.
I searched the forums here and found out that it is
a problem for quite some time now.

I wrote a workaround to get the normal windows position
(not maximized nor minimized) and a fixed getter Top2.
It was not allowed to override the original Top, so i
had to use Top2. :)

You can use it easily like:
x = mainWindow.NormalPosition.left;
y = mainWindow.NormalPosition.top;
w = mainWindow.NormalPosition.right;
h = mainWindow.NormalPosition.bottom;

realtop = mainWindow.Top2;
Here my solution:
#pragma warning disable 0649

    internal struct POINT
    {
        public System.Int32 x, y;
    }

    internal struct RECT
    {
        public System.Int32 left, top, right, bottom;
    }

    internal struct WINDOWPLACEMENT
    {
        public System.UInt32 length, flags, showCmd;
        public POINT ptMinPosition;
        public POINT ptMaxPosition;
        public RECT rcNormalPosition;
    }

#pragma warning restore 0649

    internal static class NativeMethods
    {
        [System.Runtime.InteropServices.DllImport("user32.dll", SetLastError = false)]
        internal static extern bool GetWindowPlacement(System.IntPtr hWnd, System.IntPtr windowplacement);
    }

    internal static class WindowHelper
    {
        public static void GetWindowCoords(System.Windows.Window w, ref RECT rect)
        {
            System.IntPtr hWnd = GetWindowHandle(w);
            if (hWnd != System.IntPtr.Zero)
            {
                int size = System.Runtime.InteropServices.Marshal.SizeOf(typeof(WINDOWPLACEMENT));
                System.IntPtr hglobal = System.Runtime.InteropServices.Marshal.AllocHGlobal(size);
                if (hglobal != System.IntPtr.Zero)
                {
                    System.Runtime.InteropServices.Marshal.WriteInt32(hglobal, size);
                    NativeMethods.GetWindowPlacement(hWnd, hglobal);
                    rect.left   = System.Runtime.InteropServices.Marshal.ReadInt32(hglobal, 28);
                    rect.top    = System.Runtime.InteropServices.Marshal.ReadInt32(hglobal, 32);
                    rect.right  = System.Runtime.InteropServices.Marshal.ReadInt32(hglobal, 36) - rect.left;
                    rect.bottom = System.Runtime.InteropServices.Marshal.ReadInt32(hglobal, 40) - rect.top;
                    System.Runtime.InteropServices.Marshal.FreeHGlobal(hglobal);
                }
            }
        }
        public static System.IntPtr GetWindowHandle(System.Windows.Window window)
        {
            if (window != null) return new System.Windows.Interop.WindowInteropHelper(window).Handle;
            return System.IntPtr.Zero;
        }
    }

    internal class RibbonWindow : ActiproSoftware.Windows.Controls.Ribbon.RibbonWindow
    {
        public RECT NormalPosition
        {
            get
            {
                RECT rect = new RECT();
                WindowHelper.GetWindowCoords(this, ref rect);
                return rect;
            }
        }
        public double Top2
        {
            get
            {
                if (this.WindowState == System.Windows.WindowState.Normal)
                {
                    RECT rect = new RECT();
                    WindowHelper.GetWindowCoords(this, ref rect);
                    return rect.top;
                }
                return base.Top;
            }
        }
    }
Now i can serialize my RibbonWindow position and the window
opens always at the saved location.


EDIT:
Umm... now i found out that RestoreBounds works too for serializing. :)
editorX      = mainWindow.RestoreBounds.Left;
editorY      = mainWindow.RestoreBounds.Top;
editorWidth  = mainWindow.RestoreBounds.Width;
editorHeight = mainWindow.RestoreBounds.Height;
Now, that's much easier, isn't it?

[Modified at 12/26/2011 11:13 PM]
The latest build of this product (v2019.1 build 0683) was released 1 month ago, which was after this thread was created.

Add Comment

Please log in to a validated account to post comments.