Introduction
This article is about a ToolBox
control which has the look and feel of VS.NET IDE's toolbox. About two weeks back, I was searching for a toolbox like control for an UI design application. I came across Iulian Serban's VS.NET-like Toolbox and its upgrade by Giorgio Santini. I was using that control initially, but later on, I had problems with it, because it lacked the feature of renaming items (a requirement in our project) and also a little problem with drawing items when there were too many tabs and the item area was small. Its design is pretty good except that it uses button controls and panels to draw tabs and tab items. For these reasons, I thought of writing a toolbox control myself.
This ToolBox
control is a completely owner drawn control which includes animated tab movements, swapping/renaming tab/tab items, and of course, drag-drop support ;).
About ToolBox Control
Classes:
+-------------+
| ToolObject |
+------o------+
|\________
| \
+------o------+ \
| ToolBoxItem | \
+------o------+ \
| \
| +----------------+
+------o------+ |ToolScrollButton|
| ToolBoxTab | +----------------+
+-------------+
+-------------+
| UserControl | // System.Windows.Forms.UserControl
+-------------+
|
|
+------o------+
| ToolBox |
+-------------+
The ToolBox
object keeps an array of ToolBoxTab
s. When a ToolBoxTab
is added to the ToolBox
, it registers five events with the parent (ToolBox
). They are:
MouseDown
MouseUp
MouseMove
MouseLeave
Paint
These events are un-registered when the tab is removed. When the tab is disabled, the events except Paint
is un-registered; and when it is enabled, events except Paint
are registered again.
ToolBox
keeps two ToolScrollButton
objects to render up and down scroll buttons respectively. It also initializes a hidden edit control and adds it to its control collection (the one and only one child control).
Each ToolBoxTab
object keeps an array of ToolBoxItem
s which can be added/deleted through member methods. A ToolBoxTab
keeps a rectangle called itemArea
into which the toolbox items are rendered. When the tab becomes unselected, this area reduces to an empty rect
; and the newly selected tab's itemRect
is prepared and rendered.
Items are scrolled when a click occurs in a scroll button or at a mouse wheel event.
If you want to set the ImageList
from a bitmap strip (just like in MFC CToolBar
), use the method SetImageList(Image image, Size size, Color transparentColor)
of ToolBox
which will slice the image by the specified size and make the ImageList
using the given transparent color.
Properties of interest.
BackColor
: The background color of the control.
TabHeight
: Height of each tab.
ItemHeight
: Height of each tab item.
TabSpacing
: Spacing between tabs.
ItemSpacing
: Spacing between items.
ItemHoverColor
: Color of item when mouse is over it.
ItemNormalColor
: Normal color of item.
ItemSelectedColor
: Selected item color.
SmallImageList
: The imagelist whose image indices are used to render images in list view and small icon view.
LargeImageList
: The imagelist whose image indices are used to render images in large icon view.
SmallItemSize
: Size of the tool box item in small icon view.
LargeItemSize
: Size of the tool box item in large icon view.
Using the code
Creating the ToolBox:
using Silver.UI;
ToolBox _toolBox = new ToolBox();
_toolBox.BackColor = System.Drawing.SystemColors.Control;
_toolBox.Dock = System.Windows.Forms.DockStyle.Fill;
_toolBox.TabHeight = 18;
_toolBox.ItemHeight = 20;
_toolBox.ItemSpacing = 1;
_toolBox.ItemHoverColor = System.Drawing.Color.BurlyWood;
_toolBox.ItemNormalColor = System.Drawing.SystemColors.Control;
_toolBox.ItemSelectedColor = System.Drawing.Color.Linen;
_toolBox.Name = "_toolBox";
_toolBox.Size = new System.Drawing.Size(208, 405);
_toolBox.Location = new System.Drawing.Point(0, 0);
Controls.Add(_toolBox);
Adding a Tab
ToolBoxTab tab = new ToolBoxTab("Tab Name",1);
_toolBox.AddTab(tab);
_toolBox.AddTab("Another Tab ",-1);
Adding a Tab item
int tabIndex = 2;
_toolBox[tabIndex].AddItem("Item Caption", 10,
true, new Rectangle(10,10,100,100));
ToolBoxItem item = new ToolBoxItem();
item.Caption = "New Item";
item.Enabled = true;
item.ImageIndex = 12;
item.Object = new Rectangle(10,10,100,100);
_toolBox[tabIndex].AddItem(item);
Accessing Tabs
ToolBoxTab tab;
tab = _toolBox.SelectedTab;
tab = _toolBox[tabIndex];
Accessing TabItems
TooBoxItem item;
item = _toolBox.SelectedTab.SelectedItem;
item = _toolBox[tabIndex][itemIndex];
Events
_toolBox.RenameFinished +=
new RenameFinishedHandler(ToolBox_RenameFinished);
private void ToolBox_RenameFinished(ToolBoxItem sender,
RenameFinishedEventArgs e)
{
e.Cancel = true;
}
_toolBox.TabSelectionChanged += new
TabSelectionChangedHandler(ToolBox_TabSelectionChanged);
private void ToolBox_TabSelectionChanged(ToolBoxTab sender, EventArgs e)
{
}
_toolBox.ItemSelectionChanged += new
ItemSelectionChangedHandler(ToolBox_ItemSelectionChanged);
private void ToolBox_ItemSelectionChanged(ToolBoxItem sender,
EventArgs e)
{
}
_toolBox.TabMouseDown += new TabMouseEventHandler(ToolBox_TabMouseDown);
_toolBox.TabMouseUp += new TabMouseEventHandler(ToolBox_TabMouseUp);
_toolBox.ItemMouseDown += new ItemMouseEventHandler(ToolBox_ItemMouseDown);
_toolBox.ItemMouseUp += new ItemMouseEventHandler(ToolBox_ItemMouseUp);
Note: Some of the events in ToolBox
don't adhere to the .NET event handling system. E.g.: see RenameFinished
event handler's parameters. I thought there isn't a need for writing a RenameFinishedEventArgs
class =).
Update: 10/10/2005 - Added RenameFinishedEventArgs
.
Points of Interest
- Scrolling Items:
At first, the scrolling of items was done by repositioning the itemArea
of a tab. But I had to abandon that because I couldn't set the Graphics
object's clipping region properly. Now, scrolling is done by setting the Y co-ordinate of an item, and if its Y doesn't lie inside itemArea
completely, it is not drawn.
- Disabled Image:
While writing this control, I was looking on how to draw a disabled image as seen in the VS IDE toolbar. Those images were not drawn using a DrawState
API as it can be clearly seen. A little bit of search led me to this site in which the author specifies about a grayscale color matrix. It does the monochrome conversion, but I needed a some more grey effect in it. So, here is my grayscale color matrix: ;)
ColorMatrix cmtx = null;
float[][] matrix = new float[][]
{
new float[] {0.3f ,0.3f ,0.3f ,1, 1},
new float[] {0.1f ,0.1f ,0.1f ,1, 1},
new float[] {0.1f ,0.1f ,0.1f ,1, 1},
new float[] {0.3f ,0.3f ,0.3f ,1, 1},
new float[] {0.08f,0.08f,0.08f,0, 1},
new float[] {1 ,1 ,1 ,1, 1},
};
cmtx = new ColorMatrix(matrix);
Another really interesting thing is that I have not tested this control keenly. There might be bugs and bunnies. (Pssst! It is better to wrap the toolbox into a container like a Panel
rather than leaving it alone.)
Why the namespace Silver.UI?
My name is Aju.George. So it's AG or Ag, chemically Ag means Silver. ;) So it's Me.UI :P
Changes
- 11/06/2004
DragDelay
for toolbox items by Neal Stublen.
- Minor change in
PaintItems
, DrawPartialItem
control logic by Neal Stublen.
- 11/07/2004
- Context menu with handlers for rename textbox.
- Positioning and font for textbox.
- Item state change for both M-buttons on mouse down.
- Timer/Scroll delay get/set methods.
- 11/08/2004
- A Bug and a Bunnie pointed out by NashControl got fixed.
- Updated demo application.
- 10/10/2005
- Split code to different files.
- Changes in project settings (DLL).
- Added XML serialization methods.
- Added specialized collections of tabs and items.
- More events added (see Delegates.cs).
- Two more view modes added for toolbox items (Large Icon, Small Icon View).
- Support for large and small image lists.
- New properties to configure tab/items look 'n' feel.
- Added support to associate a control for a tab.
- More changes added in drawing.
- Improved renaming of tabs and items.
- Swapping of tabs, items by drag drop.
- Various other bug fixes.
- Updated demo application.
Notes