65.9K
CodeProject 正在变化。 阅读更多。
Home

TabStrips:Visual Studio 2005 风格的 TabControl!

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.82/5 (75投票s)

2006年4月25日

3分钟阅读

viewsIcon

502297

downloadIcon

12549

一种 Visual Studio 2005 风格的 TabControl,支持正确的从右到左 (RTL) 和从左到右 (LTR) 绘制。

Sample Image - TabStrip.gif

引言

除了 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 方法,它将报告用户单击了控件的哪个部分。
  • 更改:重构 FATabItemSelecting 方法。
版本 1
  • 提供基类,以及一个实现了 Visual Studio 2005 主题的 TabStrip 控件。
  • 提供 TabStripTabStripItem 的控件设计器。
© . All rights reserved.