最近开发WinForm频繁使用了TabControl控件,这个控件的选项卡没有BackgroundImage这个属性,那么如何为其各个选项卡添加背景图片呢?(这里说的是每个TabPage的头部,也就是标题,不是工作区域。)

最开始用到TabControl的时候,我的每个选项卡是写死的,而后由于项目需求又动态添加了TabControl并生成各个选项卡,而两次我都要重绘其标题,因此在这里把我当时两种情形下重绘的方法通过一个例子一起分享出来。

首先先在窗体拖个Tabcontrol控件,然后更改了其Alignment属性为Left,使其选项卡在左边。然后可以通过更改其ItemSize调节每个选项卡的大小。值得注意的是,因为在此是把TabControl向左旋转了90°,所以此时设置宽的时候实际上改变的是它的高,设置高的时候实际上改变的是它的宽。而且设置宽(改变高)发现无效是因为受选项卡文本字体所影响,可相应地改变字体尺寸。调整一番后的效果图:

接着就要进入正题重绘其选项卡背景了。首先要把它的DrawMode属性改为OwnerDrawFixed,改了这个才会让用户自己绘制标题生效。接着给它添加DrawItem事件。事件重绘方法如下:

 private void tabMain_DrawItem(object sender, DrawItemEventArgs e)
{
Bitmap b0 = new Bitmap(@"..\..\Images\1.jpg");
Bitmap b1 = new Bitmap(@"..\..\Images\2.jpg");
Bitmap b2 = new Bitmap(@"..\..\Images\3.jpg");
Bitmap b3 = new Bitmap(@"..\..\Images\4.jpg");
switch (e.Index)
{
case :
e.Graphics.DrawImage(b0, e.Bounds);
break;
case :
e.Graphics.DrawImage(b1, e.Bounds);
break;
case :
e.Graphics.DrawImage(b2, e.Bounds);
break;
case :
e.Graphics.DrawImage(b3, e.Bounds);
break;
}
}

本文的图片我都事先放在当前项目下的一个Images文件夹里了。

最终效果图:

以上是写死的情况下为其重绘标题,现在来介绍当选项卡是动态生成时为其重绘标题的方法。在说明此之前,我们先为原有TabControl添加SelectedIndexChanged事件,通过获取其SelectedIndex从而知道哪个选项卡被点击了,在此,我在第二个选项卡里面动态添加另一个TabControl并生成其各个TabPage。代码如下:

 private void tabMain_SelectedIndexChanged(object sender, EventArgs e)
{
switch (tabMain.SelectedIndex)
{
case :
break;
case :
//假设动态生成的TabControl有4个选项卡
for (int i = ; i < ; i++)
{
TabPage page = new TabPage();
page.Name = "page" + i.ToString();
page.Text = (i + ).ToString();
this.tabSub.Controls.Add(page);
}
this.tabSub.ItemSize = new System.Drawing.Size(, );
this.tabSub.Font = new System.Drawing.Font("宋体", );
this.tabSub.Dock = DockStyle.Fill;
this.tabMain.TabPages[].Controls.Add(tabSub);
break;
case :
break;
case :
break;
}
}

在外部预先定义好要生成的TabControl变量:

TabControl tabSub = new TabControl();

效果如下:

好了,接下来也该为它重绘下标题了。首先在上面设置tabSub属性的代码下新增这两行:

this.tabSub.DrawItem += new System.Windows.Forms.DrawItemEventHandler(this.tabSub_DrawItem);
this.tabSub.DrawMode = System.Windows.Forms.TabDrawMode.OwnerDrawFixed;

第一行是为tabSub新增绘制标题的事件,第二行是为了让系统使用我们自己绘制的样式。

然后自己写个绘制方法,代码如下:

 private void tabSub_DrawItem(object sender, DrawItemEventArgs e)
{
List<string> imgPath = new List<string>()
{
@"..\..\Images\d.jpg",
@"..\..\Images\s.jpg",
@"..\..\Images\n.jpg",
@"..\..\Images\x.jpg"
};
for (int i = ; i < this.tabSub.TabCount; i++)
{
Bitmap b = new Bitmap(imgPath[i]);
if (e.Index == i)
{
e.Graphics.DrawImage(b, e.Bounds);
}
}
}

效果如下:

OK,至此大功告成。当然上述代码是有缺陷的,当你轮换左边选项卡最后又点到第二个选项卡时,它会再加载多一次,这个只需要在当初绘制的时候加个判断就行了,可以判断当前选项卡下是否已经包含了这些控件,或者定义个布尔变量用来判断是否已经加载就可以了。

WinForm中重绘TabControl选项卡标题的更多相关文章

  1. C#重绘TabControl

    C#重绘TabControl的Tabpage标签,添加图片及关闭按钮 Code highlighting produced by Actipro CodeHighlighter (freeware)h ...

  2. C# 重绘tabControl,添加关闭按钮(页签)

    C# 重绘tabControl,添加关闭按钮(页签) 调用方法 参数: /// <summary> /// 初始化 /// </summary> /// <param n ...

  3. 在WPF窗体中重绘

    原文:在WPF窗体中重绘   写这篇主要是为了验证任何元素自身都具备绘图功能. 在默认Window中重写OnRender方法 protected override void OnRender(Draw ...

  4. 上传图片时,使用GDI+中重绘方式将CMYK图片转为RGB图片

    原文:上传图片时,使用GDI+中重绘方式将CMYK图片转为RGB图片 我们知道,如果网站上传图片时,如果用户上传的是CMYK图片,那么在网站上将是无法显示的,通常的现象是出现一个红叉.下面使用将Ima ...

  5. C# 重绘tabControl,添加关闭按钮(续)

    在上一篇随笔中,添加关闭按钮是可以实现 ,但细心一点就会发现,每次关闭一个选项卡,tableControl都会自动跳到第一个页面,显然 这不是我们想要的,为此,我修改了部分的代码.除此之外,我还添加了 ...

  6. 重绘TabControl

    本文转载自:http://blog.csdn.net/conmajia/article/details/7596718 作者:野比 (conmajia@gmail.com) 时间:May, 2012 ...

  7. 【转】VC的MFC中重绘函数的使用总结(整理)

    原文网址:http://www.cnblogs.com/x8023z/archive/2008/12/09/mfc33.html 在刷新窗口时经常要调用重绘函数MFC提供了三个函数用于窗口重绘Inva ...

  8. Winform 中DataGridView控件添加行标题

    有很多种方法. 1.可以在DataGridView控件中的RowStateChanged事件改变行标题单元格的值(Row.HeaderCell.Value) /// <summary> / ...

  9. C# 自定义重绘TabControl

    using System.Drawing; using System.Windows.Forms; using System.Drawing.Drawing2D; using System.Runti ...

随机推荐

  1. linux phpexcel导出后打不开

    在PHPExcel_IOFactory::createWriter($objPHPExcel, 'Excel2007'); 后面加一行 ob_clean();

  2. Nodejs事件引擎libuv源码剖析之:请求(request)结构的设计剖析

    声明:本文为原创博文,转载请注明出处.         在libuv中,请求(request)代表一个用户向libuv发出的指令,比如uv_connect_s就表示一个tcp的连接请求.uv_work ...

  3. CPU阿甘之烦恼

    转自“码农翻身”公共号,原文地址CPU阿甘之烦恼 总结:(程序加载到内存运行的演变过程) 内存存放程序.OS负责加载程序到内存.CPU负责运行内存中的程序 1.串行:加载一个完整程序到内存,CPU运行 ...

  4. Unity游戏开发中的内存管理_资料

    内存是手游的硬伤——Unity游戏Mono内存管理及泄漏http://wetest.qq.com/lab/view/135.html 深入浅出再谈Unity内存泄漏http://wetest.qq.c ...

  5. SpringMVC学习记录4

    主题 SpringMVC有很多很多的注解.其中有2个注解@SessionAttributes @ModelAttribute我平时一般不用,因为实在是太灵活了.但是又有一定限制,用不好容易错.. 最近 ...

  6. juery学习总结(一)——juery选择器

    juery在工作中经常使用,遇到不会的问题往往百度一下,事后就忘.使用到现在也感觉不到有什么提高,为了每天进步一点点,从今天起抽时间记录下对juery的学习. 学习之前,首先要了解什么是网页元素,网页 ...

  7. AJAX请求时status返回状态明细表 readyState的五种状态

    在<Pragmatic Ajax A Web 2.0 Primer >中偶然看到对readyStae状态的介绍,感觉这个介绍很实在,摘译如下: 0: (Uninitialized) the ...

  8. Android:TextView文字跑马灯的效果实现

    解决TextView文字显示不全的问题. 简单设置跑马灯的效果: <TextView android:id="@+id/textView" android:layout_wi ...

  9. NSSearchPathForDirectoriesInDomains函数详解

    NSSearchPathForDirectoriesInDomains函数详解     #import "NSString+FilePath.h" @implementation ...

  10. Linux中find常见用法示例

    ·find   path   -option   [   -print ]   [ -exec   -ok   command ]   {} \; find命令的参数: pathname: find命 ...