Contextual Content in WinForms version

Docking/MDI for Windows Forms Forum

Posted 1 year ago by Tom Johnson
Version: 18.1.0340
Avatar

Any way to implement an indicator in the title bar of a ToolWindow like the Docking WPF version does?  Can't easily switch to WPF.

Comments (7)

Answer - Posted 1 year ago by Actipro Software Support - Cleveland, OH, USA
Avatar

Hi Tom,

All the WinForms Docking/MDI controls render themselves with renderers.  For instance, the VisualStudio2005DockRenderer that is used as a base renderer for some other renderers has a virtual DrawDockContainerTitleBarForeground that draws the title bar text in the bounds specified.  You could create a DockRenderer class that inherits one of ours and overrides that method.  Then render your indicator in that method and call the base method with slightly reduced bounds so the text won't overlap your indicator.  That would probably work.  Your resulting renderer can be set to the DockManager.DockRenderer property.


Actipro Software Support

Posted 9 months ago by Amyn Virani
Avatar

I had a followup question on the approach you noted above.

I created a new class MyDockRenderer which inherits from VisualStudio2005DockRenderer as suggested above and overrided the DrawDockContainerTitleBarForeground to draw the image. Till this point, it seem to work.

Now, the limitation to this approach is that all tool windows have the same image. Is there a way I could control which image to be drawn for each window? It seems to me that an override on the ToolWindow would give that control but I couldn't find anything in it that I could use.

Any thoughts?

Posted 9 months ago by Actipro Software Support - Cleveland, OH, USA
Avatar

Hello,

Each ToolWindow has separate image-related properties.  You can use the ToolWindow.GetImage() method to get the image, which resolves between the Image and ImageIndex properties on the ToolWindow.  Is that what you mean?


Actipro Software Support

Posted 9 months ago by Amyn Virani
Avatar

Not exactly.

So here is the class I wrote for MyDockRenderer

 

class MyDockRenderer : ActiproSoftware.UIStudio.Dock.VisualStudio2005DockRenderer
    {
        private System.Drawing.Image loadingImg = Properties.Resources.loading;

        public override void DrawDockContainerTitleBarForeground(System.Windows.Forms.PaintEventArgs e, System.Drawing.Rectangle bounds, ActiproSoftware.UIStudio.Dock.DockContainer dockContainer)
        {
                base.DrawDockContainerTitleBarForeground(e, bounds, dockContainer);
                e.Graphics.DrawImage(loadingImg, bounds.Width - 20, 0, 20, 20);
        }
    }

 And in my MainForm constructor, I do the following:

dockManager.DockRenderer = new MyDockRenderer();

 Now since all the ToolWindows are added to the dockManager, they all have the same DockRenderer and hence show the same image in the title bar.

What I am trying to achieve is the ability to display different images for every ToolWindow that is inside the DockManager.

Makes sense?

Posted 9 months ago by Actipro Software Support - Cleveland, OH, USA
Avatar

You should be able to look at this method to get the image to render: 

dockContainer.SelectedToolWindow.GetImage()


Actipro Software Support

Posted 9 months ago by Amyn Virani
Avatar

Thanks, that helped.

Now instead of using a static image, I would like to display an animated gif. Here is my code below:

class MyDockRenderer : ActiproSoftware.UIStudio.Dock.VisualStudio2005DockRenderer
    {
        private System.Drawing.Image loadingImg = Properties.Resources.loading;
        private ActiproSoftware.UIStudio.Dock.DockContainer dockContainer = null;
        bool currentlyAnimating = false;

        //This method begins the animation.
        public void AnimateImage()
        {
            if (!currentlyAnimating)
            {
                //Begin the animation only once.
                ImageAnimator.Animate(loadingImg, new EventHandler(this.OnFrameChanged));
                currentlyAnimating = true;
            }
        }

        public override void DrawDockContainerTitleBarForeground(System.Windows.Forms.PaintEventArgs e, System.Drawing.Rectangle bounds, ActiproSoftware.UIStudio.Dock.DockContainer dockContainer)
        {
            try
            {
                base.DrawDockContainerTitleBarForeground(e, bounds, dockContainer);
                this.dockContainer = dockContainer;

                //Begin the animation.
                AnimateImage();

                //Get the next frame ready for rendering.
                ImageAnimator.UpdateFrames(loadingImg);

                //Draw the next frame in the animation.
                e.Graphics.DrawImage(loadingImg, bounds.Width - 20, 0, 20, 20);
            }
            catch (Exception)
            {
                
            }
        }

        private void OnFrameChanged(object sender, EventArgs eventArgs)
        {
            if (dockContainer != null)
            {
                dockContainer.Invalidate();
            }
        }
    }

 It does show the icon on all the windows and there seems to be some animation going on but it is no where smooth. Is there any better way of doing this? Note that I have almost 20 ToolWindows opened at the same time.

Posted 9 months ago by Actipro Software Support - Cleveland, OH, USA
Avatar

I'm not sure if this would help but the first child element of a ToolWindowContainer should be the title bar element.  You could try just invalidating that instead of the whole container, which covers all the content too.  That might speed things up since it's not invalidating quite as much.

var titleBar = ((IUIElement)toolWindowContainer).Children[0] as IUIElement;
if (titleBar != null)
    titleBar.Invalidate(InvalidationLevels.Element, InvalidationTypes.Paint);

Other than that I'm not sure what to suggest.


Actipro Software Support

The latest build of this product (v2018.1 build 0341) was released 7 months ago, which was after the last post in this thread.

Add Comment

Please log in to a validated account to post comments.