Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Moving toolstrip just a little too far left will create a new row if another toolstrip is on the same toolstrip panel

When I drag a toolstrip to the left (perhaps just to get it in the corner) with another toolstrip in that same toolstrip panel, the one I'm dragging jumps down to a 'new' row, as if I had moved it down. It's quite tricky to explain, so here's a couple of diagrams.

Diagram A: I move the toolstrip to the left, and 'accidentally' go too far left (well only by a couple of dozen pixels, which users can easily do).

Diagram B: This happens, the dragged toolstrip drops down a row.

enter image description here

How can I prevent this new row from being 'created'? As a last resort, I would be happy to prevent new rows being created under any circumstances (e.g: If the user intended to drag it down to create a new row).

I've experimented with LayoutStyle to no avail.

like image 376
Dan W Avatar asked Oct 21 '22 16:10

Dan W


1 Answers

There's probably a couple ways to do this. I've experimented with a few, but none are perfect. I would say the least complicated way I found is to set the maximum size of the ToolStripPanel like Hans mentioned, and also to subclass the ToolStrip and override OnLocationChanged (or assign an event handler to LocationChanged rather than subclassing, but you'd have to assign a handler to each ToolStrip).

public class ToolStripEx : ToolStrip
{
    protected override void OnLocationChanged(EventArgs e)
    {
        if (this.Location.Y >= this.Parent.MaximumSize.Height)
        {
            this.Location = new Point(this.Location.X, 0);
        }
        else
        {
            base.OnLocationChanged(e);
        }           
    }
}


Note: This causes the mouse to jump back and forth when trying to drag the ToolStrip down, due to the fact that the Location is reset after it already changed, so it is essentially moving down, then immediately jumping back up.

It's also worth mentioning that this may be an annoyance to the user, especially if they are purposely trying to put the ToolStrip in a new row, so I wouldn't really recommend doing this. But since you asked, there it is.

Update with complete steps and code:

I created a new blank Windows Forms project. I added a new file ToolStripEx.cs to the solution, and this is what is inside:

Updated for the other panels and their Orientation

using System;
using System.Drawing;
using System.Windows.Forms;

namespace WindowsFormsApplication2
{
    public class ToolStripEx : ToolStrip
    {
        protected override void OnLocationChanged(EventArgs e)
        {
            if (this.Parent is ToolStripPanel)
            {
                ToolStripPanel parent = this.Parent as ToolStripPanel;

                if (parent.Orientation == Orientation.Horizontal)
                {
                    if (this.Location.Y != 0)
                    {
                        this.Location = new Point(this.Location.X, 0);
                        return;
                    }
                }
                else if (parent.Orientation == Orientation.Vertical)
                {
                    if (this.Location.X != 0)
                    {
                        this.Location = new Point(0, this.Location.Y);
                        return;
                    }
                }
            }
            base.OnLocationChanged(e);
        }
    }
}


Then I built the solution so the ToolStripEx class will show up in the Toolbox.

Then I put a regular ToolStripContainer onto the form from the Toolbox, set Dock to Fill, set the colors, etc.

Then I dragged two ToolStripExs (with the cog icon you mentioned) from the Toolbox to the TopToolStripPanel. I set their colors and renderers and whatnot.

This is what Form1.cs looks like:

Updated to set the other maximum sizes

using System.Drawing;
using System.Windows.Forms;

namespace WindowsFormsApplication2
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
            this.toolStripContainer1.TopToolStripPanel.MaximumSize = new Size(0, toolStripEx1.Height);
            this.toolStripContainer1.LeftToolStripPanel.MaximumSize = new Size(toolStripEx1.Height, 0);
            this.toolStripContainer1.BottomToolStripPanel.MaximumSize = new Size(0, toolStripEx1.Height);
            this.toolStripContainer1.RightToolStripPanel.MaximumSize = new Size(toolStripEx1.Height, 0);
        }
    }
}


Note: This code prevents any of the panels from expanding their rows (or columns if they have an Orientation of Orientation.Vertical) If you want the side panels to be able to expand, don't set their maximum size and get rid of the else if parent.Orientation == Orientation.Vertical section.

That should be all there is to it. I ran this, and both of the ToolStripExs did not disappear when moving them around.

Like Hans said, the ToolStrip class is pretty quirky and pretty much any solution to your problem is not going to be perfect unless you develop your own controls from the ground up with your needs in mind.

If for some reason you need to extend the ToolStripContainer class, keep it separate from the new ToolStripEx class. I suspect that having the nested classes was causing you to still be using the regular ToolStrip rather than the ToolStripEx class.

Another Update - fixing the mouse jumping: I found this by accident when experimenting to get rid of the mouse cursor problem. Add this to the ToolStripEx class:

protected override void OnBeginDrag(EventArgs e)
{
    //base.OnBeginDrag(e);
}

Strangely enough, that seems to cut down significantly on the toolstrip's resistance to being dragged outside of a panel. I haven"t dug into why this works, but it seems like ToolStrip implements its own dragging behavior without using basic drag/drop functionality and by overriding OnBeginDragDrop the ToolStrip is then using its custom behavior exclusively which makes the mouse act a lot nicer when dragging it.

like image 129
sparky68967 Avatar answered Oct 24 '22 12:10

sparky68967