private void OnRibbonMdiChildActivate(object sender, EventArgs e)
        {
            // Cast to correct type
            Form topForm = sender as Form;

            // Unhook from watching any previous mdi child
            if (_activeMdiChild != null)
            {
                _activeMdiChild.SizeChanged -= new EventHandler(OnRibbonMdiChildSizeChanged);
            }

            _activeMdiChild = topForm.ActiveMdiChild;

            // Start watching any new mdi child
            if (_activeMdiChild != null)
            {
                _activeMdiChild.SizeChanged += new EventHandler(OnRibbonMdiChildSizeChanged);
            }

            // Update the pendant buttons with reference to new child
            _buttonSpecClose.MdiChild   = _activeMdiChild;
            _buttonSpecRestore.MdiChild = _activeMdiChild;
            _buttonSpecMin.MdiChild     = _activeMdiChild;
            _buttonManager.RecreateButtons();
            PerformNeedPaint(true);

            // We never want the mdi child window to have a system menu, we provide the
            // pendant buttons as part of the ribbon and so replace the need for it.
            PI.SetMenu(new HandleRef(_ribbon, topForm.Handle), NullHandleRef);

            if (_activeMdiChild != null)
            {
                uint windowStyle = PI.GetWindowLong(_activeMdiChild.Handle, -16);
                windowStyle |= PI.WS_SYSMENU;
                PI.SetWindowLong(_activeMdiChild.Handle, -16, windowStyle);
            }
        }
        private void RenderOnComposition(RenderContext context)
        {
            // Convert the clipping rectangle from floating to int version
            RectangleF rectClipF = context.Graphics.ClipBounds;
            Rectangle  rectClip  = new Rectangle((int)rectClipF.X, (int)rectClipF.Y,
                                                 (int)rectClipF.Width, (int)rectClipF.Height);

            // No point drawing unless some of the client fits into the clipping area
            if (rectClip.IntersectsWith(ClientRectangle))
            {
                // Get the hDC for the graphics instance and create a memory DC
                IntPtr gDC = context.Graphics.GetHdc();
                IntPtr mDC = PI.CreateCompatibleDC(gDC);

                PI.BITMAPINFO bmi = new PI.BITMAPINFO();
                bmi.biSize        = Marshal.SizeOf(bmi);
                bmi.biWidth       = ClientWidth;
                bmi.biHeight      = -ClientHeight;
                bmi.biCompression = 0;
                bmi.biBitCount    = 32;
                bmi.biPlanes      = 1;

                // Create a device independant bitmp and select into the memory DC
                IntPtr hDIB = PI.CreateDIBSection(gDC, bmi, 0, 0, IntPtr.Zero, 0);
                PI.SelectObject(mDC, hDIB);

                // To call the renderer we need to convert from Win32 HDC to Graphics object
                using (Graphics bitmapG = Graphics.FromHdc(mDC))
                {
                    Rectangle renderClientRect = new Rectangle(0, 0, ClientWidth, ClientHeight);

                    // Create new render context that uses the bitmap graphics instance
                    using (RenderContext bitmapContext = new RenderContext(context.Control,
                                                                           bitmapG,
                                                                           renderClientRect,
                                                                           context.Renderer))
                    {
                        // Finally we get the renderer to draw the background for the bitmap
                        _mementoBack = context.Renderer.RenderRibbon.DrawRibbonTabContextTitle(_ribbon.RibbonShape, bitmapContext, renderClientRect, _ribbon.StateCommon.RibbonGeneral, this, _mementoBack);
                    }
                }

                // Select the font for use when drawing
                IntPtr hFont = _contentProvider.GetContentShortTextFont(State).ToHfont();
                PI.SelectObject(mDC, hFont);

                // Get renderer for the correct state
                VisualStyleRenderer renderer = new VisualStyleRenderer(VisualStyleElement.Window.Caption.Active);

                // Create structures needed for theme drawing call
                PI.RECT textBounds = new PI.RECT();
                textBounds.left   = TEXT_SIDE_GAP_COMPOSITION;
                textBounds.top    = 0;
                textBounds.right  = ClientWidth - (TEXT_SIDE_GAP_COMPOSITION * 2);
                textBounds.bottom = ClientHeight;
                PI.DTTOPTS dttOpts = new PI.DTTOPTS();
                dttOpts.dwSize    = Marshal.SizeOf(typeof(PI.DTTOPTS));
                dttOpts.dwFlags   = PI.DTT_COMPOSITED | PI.DTT_GLOWSIZE | PI.DTT_TEXTCOLOR;
                dttOpts.crText    = ColorTranslator.ToWin32(SystemColors.ActiveCaptionText);
                dttOpts.iGlowSize = (_ribbon.Enabled ? 12 : 2);

                // Always draw text centered
                TextFormatFlags textFormat = TextFormatFlags.SingleLine |
                                             TextFormatFlags.HorizontalCenter |
                                             TextFormatFlags.VerticalCenter |
                                             TextFormatFlags.EndEllipsis;

                // Perform actual drawing
                PI.DrawThemeTextEx(renderer.Handle,
                                   mDC, 0, 0,
                                   GetShortText(), -1, (int)textFormat,
                                   ref textBounds, ref dttOpts);

                // Copy to foreground
                PI.BitBlt(gDC,
                          ClientLocation.X, ClientLocation.Y,
                          ClientWidth, ClientHeight,
                          mDC, 0, 0, 0x00CC0020);

                // Dispose of allocated objects
                PI.DeleteObject(hFont);
                PI.DeleteObject(hDIB);
                PI.DeleteDC(mDC);

                // Must remember to release the hDC
                context.Graphics.ReleaseHdc(gDC);
            }
        }
        /// <summary>
        /// Discover the preferred size of the element.
        /// </summary>
        /// <param name="context">Layout context.</param>
        public override Size GetPreferredSize(ViewLayoutContext context)
        {
            Size preferredSize = Size.Empty;

            // We need an owning form to perform calculations
            if (_ownerForm != null)
            {
                // We only have size if custom chrome is being used with composition
                if (_ownerForm.ApplyCustomChrome && _ownerForm.ApplyComposition)
                {
                    try
                    {
                        // Create structure that will be populated by call to WM_GETTITLEBARINFOEX
                        PI.TITLEBARINFOEX tbi = new PI.TITLEBARINFOEX();
                        tbi.cbSize = (uint)Marshal.SizeOf(tbi);

                        // Ask the window for the title bar information
                        PI.SendMessage(_ownerForm.Handle, PI.WM_GETTITLEBARINFOEX, IntPtr.Zero, ref tbi);

                        // Find width of the button rectangle
                        int closeWidth = tbi.rcCloseButton.right - tbi.rcCloseButton.left;
                        int helpWidth  = tbi.rcHelpButton.right - tbi.rcHelpButton.left;
                        int minWidth   = tbi.rcMinButton.right - tbi.rcMinButton.left;
                        int maxWidth   = tbi.rcMaxButton.right - tbi.rcMaxButton.left;

                        int clientWidth       = _ownerForm.ClientSize.Width;
                        int clientScreenRight = _ownerForm.RectangleToScreen(_ownerForm.ClientRectangle).Right;
                        int leftMost          = clientScreenRight;

                        // Find the left most button edge (start with right side of client area)
                        if ((closeWidth > 0) && (closeWidth < clientWidth))
                        {
                            leftMost = Math.Min(leftMost, tbi.rcCloseButton.left);
                        }

                        if ((helpWidth > 0) && (helpWidth < clientWidth))
                        {
                            leftMost = Math.Min(leftMost, tbi.rcHelpButton.left);
                        }

                        if ((minWidth > 0) && (minWidth < clientWidth))
                        {
                            leftMost = Math.Min(leftMost, tbi.rcMinButton.left);
                        }

                        if ((maxWidth > 0) && (maxWidth < clientWidth))
                        {
                            leftMost = Math.Min(leftMost, tbi.rcMaxButton.left);
                        }

                        // Our width is the distance between the left most button edge and the right
                        // side of the client area (this space the buttons are taking up). Plus a small
                        // extra gap between the first button and the caption elements to its left.
                        _width = (clientScreenRight - leftMost) + SPACING_GAP;

                        preferredSize.Width = _width;
                    }
                    catch (ObjectDisposedException)
                    {
                        // Asking for the WM_GETTITLEBARINFOEX can cause exception if the form level
                        // Icon has already been disposed. This happens in rare circumstances.
                    }
                }
            }

            return(preferredSize);
        }