TabStrips:Visual Studio 2005 风格的 TabControl!






4.82/5 (75投票s)
2006年4月25日
3分钟阅读

502297

12549
一种 Visual Studio 2005 风格的 TabControl,支持正确的从右到左 (RTL) 和从左到右 (LTR) 绘制。
引言
除了 Visual Studio 的所有新功能之外,还有一个与众不同的 TabControl
,具有与众不同的新风格。这里的代码试图构建一个控件,其行为类似于 VS.NET 2005 的选项卡页面。
构建一个 TabControl
包括构建两个控件:一个 TabControl
本身,它是一个容器控件,但只接受 TabPage
作为包含控件。这可以通过为 TabControl
分配一个 Designer
类来完成。现在,TabPage
也是一个容器控件,但可以接受托管在其中的所有类型的控件。
Visual Studio TabControl
与普通的选项卡控件略有不同,因为它只显示与控件宽度相符的 TabPage
。所有其他 TabPage
都可以通过单击字形图标出现的上下文菜单访问。从菜单中选择一个 TabPage
会将其移动到 TabPageCollection
的位置 0,使其显示为第一个 TabPage
。
控件的从右到左渲染
向控件添加 RTL 绘制功能需要额外的编码用于绘制。当控件将其 RightToLeft
属性设置为 Yes
时,开发人员应处理正确的绘制行为。Graphics
类有一个绘制字符串的方法。在 RTL 控件绘制中,重要的是使用带有 StringFormat
的以下重载,将其 FormatFlags
标志设置为 DirectionRightToLeft
。请注意,由于 StringFormat
类不是一个轻量级的类,因此您应该在使用后将其释放。使用 using
块来实现这一点更方便
e.Graphics.DrawString(string, Font, Brush, Rectangle, StringFormat);
using (HeavyWeightDisposableObject obj =
new HeavyWeightDisposableObject())
{
//Do Operation and leave; will automatically dispose
}
//
// paint method of the control
//
using(StringFormat fmt = new StringFormat())
{
fmt.FormatFlags |= StringFormatFlags.DirectionRightToLeft;
g.DrawString("Test String...", this.Font,
SystemBrushes.Control, TextRectangle, fmt);
}
设计时集成
对于 TabStrip
控件的设计时行为,我使用 ParentControlDesigner
类的子类。将设计时 *动词*(例如,添加/删除 TabPages)添加到此类是很好的,这使开发人员的生活更轻松。
这里的一个额外步骤是通过覆盖设计器的 PreFilterProperties
来删除我们不希望在设计时可见的 Control
类的属性
protected override void PreFilterProperties(
System.Collections.IDictionary properties)
{
base.PreFilterProperties(properties);
properties.Remove("DockPadding");
properties.Remove("DrawGrid");
properties.Remove("Margin");
}
在普通的 TabControl
中,用户可以通过在设计时单击 TabItem
来更改选定的选项卡。为此,我们可以覆盖设计器的 GetHitTest(Point pt)
方法,但我不知道为什么它会崩溃我的 VS.NET IDE,所以我不得不考虑另一种方法。那时,利用 Windows 消息派上了用场。只需覆盖 WndProc(ref Message msg)
方法,并监听 MouseLeftClick
消息 (0x201),并检查 TabItem
的命中测试
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);
}
关注点
如果要在 .NET 1.1 上使用这些控件,您将必须将 ContextMenuStrip
的使用(它是 .NET 2 中的一个新控件)更改为旧的 ContextMenu
控件。所有的绘图都是在 GDI+ 中完成的,所以它应该在 Windows 98 或 Windows 2000 上工作,尽管尚未测试。
对于进一步的发布或任何建议/评论/反馈,请在我的地址给我留言,或访问 我的网站。
历史
版本 2
- 错误修复:与 Designer 相关的问题,导致添加到
FATabStripItems
的控件消失。 - 错误修复:在控件被释放时释放重量级对象(例如,字体、图像等)(由 #sne# 报告)。
- 错误修复:
FATabStripItems
中控件/用户控件的锚定问题(由 #sne# 报告)。 - 已添加:
FATabStripItems
现在可以包含一个图像,该图像将显示在菜单上(感谢 danielku15)。 - 已添加:一个
HitTest
方法,它将报告用户单击了控件的哪个部分。 - 更改:重构
FATabItem
的Selecting
方法。
版本 1
- 提供基类,以及一个实现了 Visual Studio 2005 主题的
TabStrip
控件。 - 提供
TabStrip
和TabStripItem
的控件设计器。