UI(User Interface)编程在整个项目开发过程中是个颇为重要的环节,任何好的解决方案若没有良好的用户界面呈现给最终用户,那么就算包含了最先进的技术也 不能算是好程序。UI编程体现在两个方面,一是设计精美的用户界面,再有就是符合大多数用户习惯和易于使用的操作流程,而制作出精美的、绚丽多彩的用户界 面是博得最终用户喜爱的第一步。我们就以制作一个水晶样式的三维按钮为例来丰富.Net界面素材库,为Windows 窗体程序增加亮点。

  一、 技术要点

   不可否认的是,Windows编程已经进入.Net时代,虽然现在的编程平台仍然是多家并存,但是微软的.Net框架类库已经全面占据了主流地位。. Net框架为我们提供了非常丰富的类、函数和方法,从桌面到Web它可以触及到编程的任何领域,以至于可以完全放弃Win32 API 的手工调用,因为.Net框架已经为我们准备好了一切。尤其是GDI+的发布,Win32程序员都应该非常清楚,在VC6和Delphi5、6、7下要想 绘制不规则图形、设计独特样式的窗口控件是件多么不轻松的事情,我们需要返回当前设备指针,然后坐标映射,再调用标准的Win32 GDI函数来进行绘制操作,最后还得记着释放设备指针等一系列内存清理操作,现在有了.Net类库,我们只需在控件的OnPaint事件中通过 e.Graphics返回Graphics对象,然后创建一个自定义的刷子对象Brush来填充Graphics表面,再创建一个Region对象设计好 我们需要的控件轮廓,并将其赋给控件的Region属性,在这个过程中可以使用GDI+为我们提供的丰富的类和方法来设计美轮美奂的控件外观,这样一个全 新的控件就创建完成了。

  我们的示例控件是一个水晶样式的三维按钮,设计这样一个按钮控件其实并不复杂,我们只需要捕获OnPaint 事件,并在事件中按照不同的按钮状态譬如:鼠标进入、鼠标悬停、鼠标单击以及鼠标离开等重新绘制按钮的外观。按钮的三维样式实际上就是三个矩形区域的叠 加,即阴影位于最底层、按钮本身以及最顶层的按钮头部白色泡泡部分,这三部分有效的叠加就制作成了一个惟妙惟肖的水晶样式的按钮了,如下图所示:

   在这个示例中用到的比较关键的类是GraphicsPath、LinearGradientBrush和PathGradientBrush。我们已经 知道,对于复杂的图形绘制操作都会用到GraphicsPath对象,GraphicsPath为我们提供了一个非常方便的解决方案,它由一系列直线和曲 线组成,通过创建复杂的闭合路径,我们可以轻松创建任意不规则图形;LinearGradientBrush和PathGradientBrush对象是 我们成功创建该示例程序的关键类,它们都继承于基类Brush,Brush对象定义用于填充图形形状的内部的对象。 LinearGradientBrush按照起始和结束坐标以及渐变的起始和结束颜色来创建一个该类的实例,该类支持双色渐变和自定义多色渐变,所有渐变 都是沿由矩形的宽度或两个点指定的直线定义的,默认情况下,双色渐变是沿指定直线从起始色到结束色的均匀水平线性混合,所以,根据这个特性我们利用该类来 绘制按钮本身和按钮顶部的白色渐变部分,部分代码如下:

//创建按钮本身的图形
Rectangle rc = new Rectangle(btnOffset, btnOffset, this.ClientSize.Width - 8 - btnOffset, this.ClientSize.Height - 8 - btnOffset);
GraphicsPath path1 = this.GetGraphicsPath(rc, 20);
LinearGradientBrush br1 = new LinearGradientBrush(new Point(0, 0), new Point(0, rc.Height + 6), Color.Blue, Color.White);
//创建按钮顶部的白色渐变
Rectangle rc3 = rc;
rc3.Inflate(-5, -5); //
rc3.Height = 15;
GraphicsPath path3 = GetGraphicsPath(rc3, 20);
LinearGradientBrush br3 = new LinearGradientBrush(rc3, Color.FromArgb(255, Color.White), Color.FromArgb(0, Color.White), LinearGradientMode.Vertical)

   PathGradientBrush类通过渐变填充 GraphicsPath对象的内部,它可以从路径的中点到路径的外边界边缘的进行平滑的彩色渐变,我们利用该类来创建按钮的阴影部分, CenterColor属性用来设定路径渐变的中心处的颜色即黑色,SurroundColors数组用来设定路径中点相对应的颜色的数组,部分代码如 下:

Rectangle rc2 = rc;
rc2.Offset(shadowOffset, shadowOffset);
GraphicsPath path2 = this.GetGraphicsPath(rc2, 20);
PathGradientBrush br2 = new PathGradientBrush(path2);
br2.CenterColor = Color.Black;
br2.SurroundColors = new Color[] {SystemColors.ButtonFace};
//为了更逼真,我们将渐变结束颜色设定为窗体前景颜色,可以根据窗口的前景颜色适当调整

   创建完该对象的实例后,阴影图形的内部被填充为一个放射状的渐变,也许读者会问,为什么得用PathGradientBrush填充图形内部,而不用 LinearGradientBrush呢?其实原因很简单,就是为了保证按钮下方和右方的阴影渐变颜色和程度是一致的,否则若还使用线性渐变 LinearGradientBrush,结果就是这样如下图:

  三个Brush对象的实例br1、br2和br3创建完成后,我们需要按照阴影、按钮本身,最后是按钮顶部的白色渐变部分这样的顺序来 绘制它们。调用Graphics对象的FillPath方法分别使用三种不同的Brush对象来填充 GraphicsPath 的内部,这样具备水晶样式的三维按钮就基本创建完成了。最后,我们再利用.Net二级缓存绘图技术将按钮以及按钮上所显示的文字绘制到屏幕上。

  二、 实现

  我们利用C# 来制作水晶按钮控件。

  首先启动Visual Studio 2005,新建空白解决方案,我们取名为:TestCrystalButton,然后在项目导航栏上右击鼠标添加新项目,为此解决方案添加新的C# Windows 控件库,取名为MyControls。IDE会创建一个继承于UserControl名为UserControl1的类,修改代码使其继承自 Button,并将原文件中所有引用UserControl1名称的地方都更改为CrystalButton,在项目导航栏中把 UserControl1.cs更名为CrystalButton.cs,如下面一段代码:

namespace MyControls
{
 public partial class CrystalButton: Button
 {
  public CrystalButton ()
  {
   InitializeComponent();
  }
 }
}

  然后将InitializeComponent()方法中的
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;

语 句注释掉,因为从Button控件不可能有自动缩放功能,它必须依赖于其父控件。在源文件头部添加对System.Drawing.Imaging和 System.Drawing.Drawing2D程序集的引用。首先需要创建一个枚举类型MouseActionType,当按钮需要绘制时会根据当前 鼠标的位置进行不同状态的绘制,如下面一段代码:

......
private enum MouseActionType
{
 None,
 Hover,
 Click
}
private MouseActionType mouseAction;

   控件会捕获OnMouseDown、OnMouseUp、OnMouseHover、OnMouseEnter和OnMouseLeave事件并将 mouseAction变量设置为不同的枚举值,以便在OnPaint事件发生时根据mouseAction变量进行不同状态的绘制。

  控件的OnPaint事件是整个项目中最重要的代码段,它按照按钮组成的三部分分别进行绘制,最后将按钮的文本也同样绘制到按钮表面,所有操作都使用了二级缓存绘图技术,代码如下:

protected override void OnPaint(PaintEventArgs e)
{
 Graphics g = e.Graphics;
 g.Clear(SystemColors.ButtonFace );
 Color clr = this.BackColor;
 int shadowOffset = 8;
 int btnOffset = 0;
 switch (mouseAction)
 {
  case MouseActionType.Click:
   shadowOffset = 4;
   clr = Color.LightGray;
   btnOffset = 2;
   break;
  case MouseActionType.Hover:
   clr = Color.LightGray;
   break;
 }
 g.SmoothingMode = SmoothingMode.AntiAlias;
 // 创建按钮本身的图形
 Rectangle rc = new Rectangle(btnOffset, btnOffset, this.ClientSize.Width - 8 - btnOffset, this.ClientSize.Height - 8 - btnOffset);
 GraphicsPath path1 = this.GetGraphicsPath(rc, 20);
 LinearGradientBrush br1 = new LinearGradientBrush(new Point(0, 0), new Point(0, rc.Height + 6), clr, Color.White);
 // 创建按钮阴影
 Rectangle rc2 = rc;
 rc2.Offset(shadowOffset, shadowOffset);
 GraphicsPath path2 = this.GetGraphicsPath(rc2, 20);
 PathGradientBrush br2 = new PathGradientBrush(path2);
 br2.CenterColor = Color.Black;
 br2.SurroundColors = new Color[] {SystemColors.ButtonFace};
 //为了更逼真,我们将渐变结束颜色设定为窗体前景颜色,可以根据窗口的前景颜色适当调整
 //创建按钮顶部白色渐变
 Rectangle rc3 = rc;
 rc3.Inflate(-5, -5);
 rc3.Height = 15;
 GraphicsPath path3 = GetGraphicsPath(rc3, 20);
 LinearGradientBrush br3 = new LinearGradientBrush(rc3, Color.FromArgb(255, Color.White), Color.FromArgb(0, Color.White), LinearGradientMode.Vertical);
 // 绘制图形
 g.FillPath(br2, path2); //绘制阴影
 g.FillPath(br1, path1); //绘制按钮
 g.FillPath(br3, path3); //绘制顶部白色泡泡
 //设定内存位图对象,进行二级缓存绘图操作
 buttonBitmapRectangle =

注:已经找不到原文出处

转载于:https://www.cnblogs.com/hakuci/archive/2008/04/08/1142822.html

利用.NET绘图技术制作水晶按钮控件(转)相关推荐

  1. 利用.NET绘图技术制作水晶按钮控件[转]

    UI(User Interface)编程在整个项目开发过程中是个颇为重要的环节,任何好的解决方案若没有良好的用户界面呈现给最终用户,那么就算包含了最先进的技术也不能算是好程序.UI编程体现在两个方面, ...

  2. Winform中实现自定义水晶按钮控件(附代码下载)

    场景 效果 注: 博客主页: https://blog.csdn.net/badao_liumang_qizhi 关注公众号 霸道的程序猿 获取编程相关电子书.教程推送与免费下载. 实现 新建一个用户 ...

  3. qt 关闭窗口的槽函数_勇哥的VC++应用框架学习之QT(1) 信号槽、按钮控件、opencv读取显示图片...

    前言勇哥对于C语言,C++早些年有一些接触,这个系列贴子就记载一下C++应用框架的学习经验. 在写程序时,UI.基础类库.应用程序框架对于vc来讲,只能依靠MFC和QT了. 勇哥对MFC有很强的抵触, ...

  4. Delphi制作数据感知控件之浮想联翩

    王维康 编写 知识点 本文共有6个关于控件的知识点: 1.基本控件的制作:2.感知属性的添加:3.关联控件的销毁处理: 4.事件方法的赋值: 5.属性页的制作:  6.组件包设计思想 关于制作感知控件 ...

  5. 一起谈.NET技术,asp.net控件开发基础(18)

    本篇继续上篇的讨论,可能大家已经在使用asp.net2.0了,DataSource属性不再使用,而是跟数据源控件搭配使用.现在讨论的绑定技术都是基于1.1版本,先熟悉一下,本质上是一样的,这样一步步的 ...

  6. 在access窗体中加图片_Access实战:一种不用按钮控件就能控制子窗体联动的方法...

    近来宇哥潜心研究Access的设计,多有心得,在此共享一二.Access窗体若要进行控制,是需要通过按钮控件的,我经过自己探索,发现了一种更加简单的方法,也就是不用控件,通过直接点击窗体已有的表格,就 ...

  7. 【飞秋】一起学Windows Phone7开发(十三.二 按钮控件)

    在Silverlight中有多种按钮控件,这些控件在Windows phone7中也都得到了很好的支持. 一.Button: 这个控件只是一个基础控件,通过blend可以创建出多种效果的按钮来. &l ...

  8. Fixjs实践——标签、按钮控件

    <sdt id="89512093" sdtgroup="t" contentlocked="t" sdtlocked="t ...

  9. VB.NET水晶报表控件经验总结

    VB.NET水晶报表控件经验总结 http://developer.51cto.com  2009-10-16 13:30  佚名  weaseek  我要评论(0) 这里介绍对于VB.NET水晶报表 ...

最新文章

  1. JDK源码学习笔记——Integer
  2. excel批量转换日期格式,将yyyymmdd类型日期转换成yyyy-mm-dd等日期类型方法
  3. Understanding Generative Adversarial Networks (GAN)
  4. 中国式创新技术“步态识别”终于来临,你大胆地走两步,我就知道你是谁
  5. 阿里云服务器mysql默认密码_阿里云服务器修改MySQL初始密码---Linux学习笔记
  6. linux创建定时任务命令,linux设置定时任务的方法步骤
  7. java 数组 源码_Java数组转List的三种方式及对比
  8. 关于协方差矩阵的理解
  9. 解决 No module named PyQt5.QtWebKitWidgets
  10. Windows 2008 限制IP连接方法
  11. JAVA汽车4S店管理系统
  12. window下内网远程控制工具
  13. 【VOIP】yate sip客户端直接呼叫
  14. enoent ENOENT: no such file or directory,
  15. thinkadmin上传与保存资源文件
  16. python堆叠面积图_06. Matplotlib 2 |折线图| 柱状图| 堆叠图| 面积图| 填图| 饼图| 直方图| 散点图| 极坐标| 图箱型图...
  17. 聊天文字在气泡背景图片上的展示
  18. slack 开源系统_Slack团队聊天的5种开源替代品
  19. 【交换机】网络交换机的作用
  20. 原生H5实现网易云轮播图

热门文章

  1. (三)在Azure上创建您的第一个Kubernetes集群
  2. 我是如何学会不再担心和喜欢SQL中的NULL的
  3. mats测试所有显存命令_RGBLCD液晶屏层叠显示测试
  4. php金币格式转换,php 资金格式转换函数_PHP教程
  5. 网页一键生成app软件_施工方案不会写?4个工程人必备的自动生成软件,一键生成超便利!...
  6. linux 查看所有端口号_linux系统:ss命令
  7. uni-app微信小程序登录授权
  8. 微信小程序 不能跳转页面 跳转不生效
  9. mysql查看连接数命令_Mysql 查看连接数,状态
  10. no number java_java.lang.NumberFormatException问题!!!