Introduction
Besides all the new features of Visual Studio, there is a distinct TabControl
with a new style like no other. The code here tries to build up a control which behaves like the tab pages of VS.NET 2005.
Building a TabControl
consists of building two controls: a TabControl
itself, which is a container control, but only accepts TabPage
s as a containing control. This could be done by assigning a Designer
class to the TabControl
. Now, TabPage
is a container control too, but can accept all kinds of controls hosted in it.
The Visual Studio TabControl
slightly differs from a normal tab control, because it only shows as much TabPage
s as fits the width of the control. All the other TabPage
s are available via a context menu appearing by clicking the glyph icon. Selecting a TabPage
from the menu brings it to position 0 of the TabPageCollection
, so that it appears as the first TabPage
.
Right-To-Left Rendering of Controls
Adding the RTL drawing feature to a control requires additional coding for drawing. The developer should handle the correct drawing behavior when the control sets its RightToLeft
property to Yes
. The Graphics
class has a method to draw strings. In RTL control drawing, it is important to use the below overload with the StringFormat
setting its FormatFlags
flag to DirectionRightToLeft
. Note that since the StringFormat
class is not a lightweight class, you should dispose it after using. It's more convenient to use a using
block to achieve this:
e.Graphics.DrawString(string, Font, Brush, Rectangle, StringFormat);
using (HeavyWeightDisposableObject obj =
new HeavyWeightDisposableObject())
{
}
using(StringFormat fmt = new StringFormat())
{
fmt.FormatFlags |= StringFormatFlags.DirectionRightToLeft;
g.DrawString("Test String...", this.Font,
SystemBrushes.Control, TextRectangle, fmt);
}
Design-Time Integration
For design-time behavior of the TabStrip
control, I'm using a sub-class of the ParentControlDesigner
class. It is nice to add the design-time verbs (e.g., Add/Remove TabPages) to this class, which makes life for the developer easier.
An additional step here is to remove the properties of the Control
class which we do not want to be visible during design-time, by overriding the PreFilterProperties
of the designer:
protected override void PreFilterProperties(
System.Collections.IDictionary properties)
{
base.PreFilterProperties(properties);
properties.Remove("DockPadding");
properties.Remove("DrawGrid");
properties.Remove("Margin");
}
In a normal TabControl
, the user can change the selected tab by clicking on the TabItem
s during design-time. To do this, we could override the GetHitTest(Point pt)
method of the designer, but I don't know why it crashes my VS.NET IDE, so I had to think of another way. That's when tapping on Windows messages came in handy. Just override the WndProc(ref Message msg)
method, and listen for the MouseLeftClick
message (0x201), and check for a hit-test on TabItem
s:
protected override void WndProc(ref Message msg)
{
if (msg.Msg == 0x201)
{
Point pt = Control.PointToClient(Cursor.Position);
FATabStripItem itm = Control.GetTabItemByPoint(pt);
if (itm != null)
{
Control.SelectedItem = itm;
ArrayList selection = new ArrayList();
selection.Add(itm);
ISelectionService selectionService =
(ISelectionService)GetService(typeof(ISelectionService));
selectionService.SetSelectedComponents(selection);
}
}
base.WndProc(ref msg);
}
Points of Interest
If you want to use these controls on .NET 1.1, you'll have to change the use of ContextMenuStrip
, which is a new control in .NET 2, with the old ContextMenu
control. All the painting is done in GDI+, so it should work on Windows 98 or Windows 2000, although it is not tested yet.
For further releases or any suggestions/comments/feedbacks, please leave me a message at my address, or visit my web site.
History
Version 2
- Bug fix: Problem with the Designer which made controls added to
FATabStripItems
disappear.
- Bug fix: Disposing of heavy-weight objects when the control is being disposed (e.g., fonts, image, etc.) (reported by #sne#).
- Bug fix: Problem with anchoring of controls/usercontrols in a
FATabStripItems
(reported by #sne#).
- Added:
FATabStripItems
can now have an image which will be displayed on menu (thanks to danielku15).
- Added: A
HitTest
method which will report which part of the control is clicked by the user.
- Changes: Refactoring
Selecting
method of FATabItem
.
Version 1
- Providing base classes, and a
TabStrip
control with the Visual Studio 2005 theme implemented.
- Providing a control-designer for
TabStrip
and TabStripItem
s.