一步一步玩控件:自定义TabControl——从山寨Safari开始

本文作者通过一步步分析和实现,详细讲述了如何使用C#的TabControl控件并进行自定义,以模仿苹果Safari浏览器的导航标签效果,包括标签的自动缩放动画。文章涵盖了控件设计、组件分析、代码实现等多个方面,展示了如何通过自绘控件和调整窗体大小来达到类似Safari的用户体验。
摘要由CSDN通过智能技术生成


作者:野比 (conmajia@gmail.com

时间:May, 2012

封面图片为野比原创,请勿未经允许私自引用


#1-1

嗯,各位,又是我,生物钟颠倒的家伙。

今天我要山寨的是大名鼎鼎的Apple,传说中的「被山寨之王」。

没错,都被我山寨好几次了。

说起Apple,相信大家对他家的各种产品,不管他软还是硬,都有相当的好感。

最近Apple把自家的Web浏览器Safari升级到了第5版,并同步推出了Windows版,支持WinXP开始的全部Windows版本。

不得不说,这是一个很给力的浏览器,它看起来就像这样。

Icon for Safari

其实我并不是苹果控,我控红富士要多点。客观的评价Safari,这个软件界面华丽,速度快,但在Windows平台上,TopSites首页资源消耗巨大,操作习惯和常规Win浏览器有一定区别,部分网页不支持或不兼容(WebKit引擎)。

不多说了,这不是重点。重点在于它的「偏好设置(Preference)」界面,就是这个:



看到这个,你肯定会觉得怎么苹果的东西会变得这么一般呢?不过就是TabControl上面增加了几个图标嘛。

嗯,朋友,你说的似乎没错。但是,我曾经也算中肯的评价过苹果的东西,抛开外观,苹果的特点之一就是「闷骚」,还有「OCD」,也就是强迫症。

听我这么说显得很干瘪,那么就让我顺着导航标签,一路点击过去,看看会发生什么事。




没错,这窗口会自动伸缩,而且是动画的!这就是apple闷骚的地方!

为了不让他一家独骚,为了不辜负他被山寨之王的名头,我只好勉为其难的山寨一番了。


山寨前的准备

山寨其实没啥好准备的,但还是需要几样重要的东西:

  • 原装货:Apple Safari 5
  • 照相机:Snagit 10
  • 生产线:Visual Studio 2005
  • 手册:MSDN
  • 苦力:野比

分析,分析

山寨的灵魂在于分析,首先把刚才拍的高清果照扯过来分解了。



所以,我把他分解成这几个部分:

  1. 根据标签不同修改窗体标题
  2. 导航标签
  3. 标签面板
  4. 自动缩放

组件设计

分析了其中的功能,那么就要想想怎么来实现。

从功能来看,这个窗口实际上是由多个子面板切换来实现的,最多他加了点自动缩放。所以从本质来说,还是一个标签切换的窗口。

我最早想到的就是大名鼎鼎却又丑得无以复加的TabControl。



按照标签切换这个思想,TabControl完全可以胜任这次的山寨需求。但是TabControl这么丑,必须要给它整整容才行。想不到我竟然有整容的才华。


下手吧,年轻人!

因为要改动的地方会很多,所以还是完全自己来绘制标签好了。为了完全自定义TabControl,同时方便循环利用,从TabControl派生一个我们自己的标签控件TabControlEx。

[csharp]  view plain copy print ?
  1. public class TabControlEx : System.Windows.Forms.TabControl  



这就是我们的TabControlEx,看起来和TabControl没什么两样(那是当然的)。

为了让他看起来不太一样,在构造函数里加上下面的代码。

[csharp]  view plain copy print ?
  1. base.SetStyle(  
  2.      ControlStyles.UserPaint |                      // 控件将自行绘制,而不是通过操作系统来绘制  
  3.      ControlStyles.OptimizedDoubleBuffer |          // 该控件首先在缓冲区中绘制,而不是直接绘制到屏幕上,这样可以减少闪烁  
  4.      ControlStyles.AllPaintingInWmPaint |           // 控件将忽略 WM_ERASEBKGND 窗口消息以减少闪烁  
  5.      ControlStyles.ResizeRedraw |                   // 在调整控件大小时重绘控件  
  6.      ControlStyles.SupportsTransparentBackColor,    // 控件接受 alpha 组件小于 255 的 BackColor 以模拟透明  
  7.      true);                                         // 设置以上值为 true  
  8. base.UpdateStyles();  

这段代码的意思就像注释里说的,注意ControlStyles这个枚举是可以按位组合的,所以上面要用「或(|)」来进行连接,这样系统就会完全忽视TabControl这个基类的界面显示,而使用我们自己的方式来呈现UI。

现在TabControlEx看起来是这样的。


啥米?!!OMG!东西哪去了??

嗯,当我第一次玩UserPaint的时候,也被吓了一跳。其实这就是上面我们设置的那句ControlStyles.UserPaint,于是系统就不帮我们画任何东西了。

所以从现在开始,一切都要靠自己了。下面所有的绘制都在OnPaint()方法中绘制。

为了先让我们找到方向,在OnPaint()方法中,我们先把Tab的位置找到,为此我们给每个Tab的边框都画出来。

[csharp]  view plain copy print ?
  1. protected override void OnPaint(PaintEventArgs e)  
  2. {  
  3.     for (int i = 0; i < this.TabCount; i++)  
  4.     {  
  5.         e.Graphics.DrawRectangle(Pens.Red, this.GetTabRect(i));  
  6.     }  
  7. }  

TabControl.GetTabRect(int)的功能是获得指定index的标签的矩形位置。画完后,我们的TabControlEx看起来不那么迷糊了。


可是,标签的大小还是不对,我们要的不是普通的那种长条,而是闷骚的苹果的瘦高型,要像这样。


嗯,好吧,我们回到构造函数,用下面的语句来设置大小。

[csharp]  view plain copy
评论 23
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Conmajia

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值