I'm using .net 2.0 with Visual Studio 2005 and I am trying to add two different toolstrips to the top of the form such that they show up side-by-side. I want it to be like Word 2003, where you can add multiple toolstrips to the same row and have them show up in line with each other, rather than dedicating a row to each toolstrip.
So I added a ToolStripPanel and docked it to the top of the form (I didn't use a ToolStripContainer because I don't need all the extra panels; I just need the one at the top). I added both toolstrips and set their Stretch properties to False. I can get them to show up in the designer window side-by-side, but at runtime the ToolStripPanel separates the toolstrips and gives each toolstrip its own dedicated row. As if to add insult to injury, when i stop debugging and return back to the designer, I am finding that the designer is moving the toolstrips to their own row as well! Am I doing something wrong here?
I have been Googling all day and found some information about a ToolStripPanelRow object, but I don't see an easy way to add toolstrips to it (i.e. it doesn't have a ToolStripPanelRow.Controls.Add method or anything like that), all it has is a Controls() property that returns an Array of control objects, and I haven't had much luck trying to add items to that array. I also found some documentation on the ToolStripPanel.Join method, which sounds like it should do the job, so I tried all 3 overloads but they don't work as advertised. No matter what I do or which options I try, it always adds the new toolstrip to the top of the panel on its own row and pushes everything else down.
In the interests of full disclosure I should warn you that I have the ToolStripPanel and one of the toolstrips added to a baseclass form, and I am trying to add the other toolstrip to a subclass form that inherits from the baseclass form. The ToolStripPanel and ToolStrip in the baseclass form are both declared "Protected Friend", so this should be working. As I mentioned, the subclass form's designer window will allow me to do it (at least, for a time).
If anyone can help me get this working or at least shed some light on why it isn't, I would be extremely grateful.
I created a custom ToolStripPanel so that I could overload the LayoutEngine;
using System.Drawing;
using System.Windows.Forms;
using System.Windows.Forms.Layout;
namespace CustomGUI
{
class CustomToolStripPanel : ToolStripPanel
{
private LayoutEngine _layoutEngine;
public override LayoutEngine LayoutEngine
{
get
{
if (_layoutEngine == null) _layoutEngine = new CustomLayoutEngine();
return _layoutEngine;
}
}
public override Size GetPreferredSize(Size proposedSize)
{
Size size = base.GetPreferredSize(proposedSize);
foreach(Control control in Controls)
{
int newHeight = control.Height + control.Margin.Vertical + Padding.Vertical;
if (newHeight > size.Height) size.Height = newHeight;
}
return size;
}
}
}
Then the custom LayoutEngine lays out the ToolStrips;
using System.Drawing;
using System.Windows.Forms;
using System.Windows.Forms.Layout;
namespace CustomGUI
{
class CustomLayoutEngine : LayoutEngine
{
public override bool Layout(object container, LayoutEventArgs layoutEventArgs)
{
Control parent = container as Control;
Rectangle parentDisplayRectangle = parent.DisplayRectangle;
Control [] source = new Control[parent.Controls.Count];
parent.Controls.CopyTo(source, 0);
Point nextControlLocation = parentDisplayRectangle.Location;
foreach (Control c in source)
{
if (!c.Visible) continue;
nextControlLocation.Offset(c.Margin.Left, c.Margin.Top);
c.Location = nextControlLocation;
if (c.AutoSize)
{
c.Size = c.GetPreferredSize(parentDisplayRectangle.Size);
}
nextControlLocation.Y = parentDisplayRectangle.Y;
nextControlLocation.X += c.Width + c.Margin.Right + parent.Padding.Horizontal;
}
return false;
}
}
}
One thing that took a while is that changing the location / size of one ToolStrip item will cause the layout to re-fire, with the controls reordered. So I take a copy of the controls before the layout loop.
And you cant use AddRange(...) to add items to the Custom Panel for some reason - need to Add(...) them one at a time.
hope that helps (it's based on MSDN LayoutEngine Example, fixed for ToolStripPanels)
Wyzfen
I think in your case you can get away with just setting the LayoutStyle on your ToolStrip to ToolStripLayoutStyle.HorizontalStackWithOverflow rather than need your own custom LayoutEngine.
I asked a different question on a similar topic on how to handle layout with dynamic items to have better control of the overflow.
System.Windows.Forms.FlowLayoutPanel can do the job.
Just put the ToolStrip controls in it with correct order.