最近需要做一个圆形的按钮,去CodeProject找了一下,发现有现成的可用,但不能完全满足我的需求。因此自己试着利用WinForm中的自定义组件功能,制作一个圆形按钮。圆形按钮小制作即将开始之前,先来看看最终效果(Demo程序下载链接:http://download.csdn.net/detail/keypig_zz/9440806)

下面分两步制作这个按钮。

A. 目标

想了一下,即将制作的圆形按钮需要满足几个要求:

i. 按钮呈现圆形或椭圆形,具体形状参数可调;

ii. 按钮用不同的填充色来响应鼠标进入或者离开事件;

iii. 按钮通过改变边的颜色来显示是否获取焦点状态;

iv. 按钮通过改变填充色的亮度来区分按钮是否按下。

B. 实现代码

具体的制作思路大致如下:

i. 成员变量:

(a).按钮绘制区域矩形 Rectangle rect;

(b).鼠标书否进入 bool buttonEnter;

(c).鼠标是否按下 bool buttonPressed;

(d).按钮是否被点击 bool buttonClicked。

ii. 属性:

(a).形状;

(b).填充色;

(c).边框。

iii. 构造函数

(a).按钮风格设定;

(b).成员变量初始化;

iv. 部分函数重写

(a).控件绘制OnPaint;

(b).鼠标相关函数;

v. 自定义函数

(a).图案填充;

(b).绘制边框;

(c).调整控件大小;

代码如下:

 using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Linq;
using System.Text; using System.Windows.Forms;
using System.Drawing;
using System.Drawing.Drawing2D; namespace 章鱼.Forms
{
public partial class RoundButton : Button
{
#region --成员变量-- RectangleF rect = new RectangleF();//控件矩形
bool mouseEnter;//鼠标是否进入控件区域的标志
bool buttonPressed;//按钮是否按下
bool buttonClicked;//按钮是否被点击
#endregion #region --属性-- #region 形状 /// <summary>
/// 设置或获取圆形按钮的圆的边距离方框边的距离
/// </summary>
[Browsable(true), DefaultValue()]
[Category("Appearance")]
public int DistanceToBorder { get; set; } #endregion #region 填充色 /// <summary>
/// 获取或设置按钮主体颜色
/// </summary>
/// <value>The color of the focus.</value>
[Browsable(true), DefaultValue(typeof(Color), "DodgerBlue"), Description("按钮主体渐变起始颜色")]
[Category("Appearance")]
public Color ButtonCenterColorEnd { get; set; } /// <summary>
/// 获取或设置按钮主体颜色
/// </summary>
[Browsable(true), DefaultValue(typeof(Color), "CornflowerBlue"), Description("按钮主体渐变终点颜色")]
[Category("Appearance")]
public Color ButtonCenterColorStart { get; set; } /// <summary>
/// 获取或设置按钮主体颜色渐变方向
/// </summary>
[Browsable(true), DefaultValue(), Description("按钮主体颜色渐变方向,X轴顺时针开始")]
[Category("Appearance")]
public int GradientAngle { get; set; } /// <summary>
/// 是否显示中间标志
/// </summary>
[Browsable(true), DefaultValue(typeof(bool), "true"), Description("是否显示中间标志")]
[Category("Appearance")]
public bool IsShowIcon { get; set; } /// <summary>
/// 按钮中间标志填充色
/// </summary>
[Browsable(true), DefaultValue(typeof(Color), "Black"), Description("按钮中间标志填充色")]
[Category("Appearance")]
public Color IconColor { get; set; } #endregion #region 边框 /// <summary>
/// 获取或设置边框大小
/// </summary>
[Browsable(true), DefaultValue(), Description("按钮边框大小")]
[Category("Appearance")]
public int BorderWidth { get; set; } /// <summary>
/// 获取或设置按钮边框颜色
/// </summary>
/// <value>The color of the focus.</value>
[Browsable(true), DefaultValue(typeof(Color), "Black"), Description("按钮边框颜色")]
[Category("Appearance")]
public Color BorderColor { get; set; } /// <summary>
/// 获取或设置边框透明度
/// </summary>
[Browsable(true), DefaultValue(), Description("设置边框透明度:0-255")]
[Category("Appearance")]
public int BorderTransparent { get; set; } /// <summary>
/// 获取或设置按钮获取焦点后边框颜色
/// </summary>
/// <value>The color of the focus.</value>
[Browsable(true), DefaultValue(typeof(Color), "Orange"), Description("按钮获得焦点后的边框颜色")]
[Category("Appearance")]
public Color FocusBorderColor { get; set; } #endregion #endregion #region --构造函数--
/// <summary>
/// 构造函数
/// </summary>
public RoundButton()
{
// 控件风格
SetStyle(ControlStyles.SupportsTransparentBackColor, true);
SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
SetStyle(ControlStyles.AllPaintingInWmPaint, true);
SetStyle(ControlStyles.ResizeRedraw, true);
SetStyle(ControlStyles.UserPaint, true);
//初始值设定
this.Height = this.Width = ; DistanceToBorder = ;
ButtonCenterColorStart = Color.CornflowerBlue;
ButtonCenterColorEnd = Color.DodgerBlue;
BorderColor = Color.Black;
FocusBorderColor = Color.Orange;
IconColor = Color.Black;
BorderWidth = ;
BorderTransparent = ;
GradientAngle = ; mouseEnter = false;
buttonPressed = false;
buttonClicked = false;
IsShowIcon = true; InitializeComponent();
}
#endregion #region --重写部分事件-- #region OnPaint事件 /// <summary>
/// 控件绘制
/// </summary>
/// <param name="pevent"></param>
protected override void OnPaint(PaintEventArgs pevent)
{
//base.OnPaint(pevent);
base.OnPaintBackground(pevent); Graphics g = pevent.Graphics;
g.InterpolationMode = InterpolationMode.HighQualityBicubic;
g.SmoothingMode = SmoothingMode.AntiAlias;//抗锯齿 myResize();//调整圆形区域 var brush = new LinearGradientBrush(rect, ButtonCenterColorStart, ButtonCenterColorEnd, GradientAngle); PaintShape(g, brush, rect);//绘制按钮中心区域 DrawBorder(g);//绘制边框 DrawStateIcon(g);//绘制按钮功能标志 if (mouseEnter)
{
DrawHighLight(g);//绘制高亮区域
DrawStateIcon(g);//绘制按钮功能标志
}
} #endregion #region 鼠标 /// <summary>
/// 鼠标点击事件
/// </summary>
/// <param name="e"></param>
protected override void OnMouseClick(MouseEventArgs e)
{
base.OnMouseClick(e);
buttonClicked = !buttonClicked;
}
/// <summary>
/// Raises the <see cref="E:System.Windows.Forms.Control.MouseUp"/> event.
/// </summary>
/// <param name="e">A <see cref="T:System.Windows.Forms.MouseEventArgs"/> that contains the event data.</param>
protected override void OnMouseUp(MouseEventArgs e)
{
base.OnMouseUp(e);
if (e.Button != MouseButtons.Left) return;
buttonPressed = false;
base.Invalidate();
} /// <summary>
/// Raises the <see cref="E:System.Windows.Forms.Control.MouseDown"/> event.
/// </summary>
/// <param name="e">A <see cref="T:System.Windows.Forms.MouseEventArgs"/> that contains the event data.</param>
protected override void OnMouseDown(MouseEventArgs e)
{
base.OnMouseDown(e);
if (e.Button != MouseButtons.Left) return;
buttonPressed = true;
} /// <summary>
/// 鼠标进入按钮
/// </summary>
/// <param name="e"></param>
protected override void OnMouseEnter(EventArgs e)
{
base.OnMouseEnter(e);
mouseEnter = true;
} /// <summary>
/// 鼠标离开控件
/// </summary>
/// <param name="e"></param>
protected override void OnMouseLeave(EventArgs e)
{
base.OnMouseLeave(e);
mouseEnter = false;
} #endregion
#endregion #region --自定义函数-- /// <summary>
/// 绘制中心区域标志
/// </summary>
/// <param name="g"></param>
private void DrawStateIcon(Graphics g)
{
if (IsShowIcon)
{
if (buttonClicked)
{
GraphicsPath startIconPath = new GraphicsPath();
int W = base.Width / ;
Point p1 = new Point(W, W);
Point p2 = new Point( * W, W);
Point p3 = new Point( * W, * W);
Point p4 = new Point(W, * W);
Point[] pts = { p1, p2, p3, p4 };
startIconPath.AddLines(pts);
Brush brush = new SolidBrush(IconColor);
g.FillPath(brush, startIconPath);
}
else
{
GraphicsPath stopIconPath = new GraphicsPath();
int W = base.Width / ;
Point p1 = new Point( * W / , W);
Point p2 = new Point( * W / , * W);
Point p3 = new Point( * W, * W);
Point[] pts = { p1, p2, p3, };
stopIconPath.AddLines(pts);
Brush brush = new SolidBrush(IconColor);
g.FillPath(brush, stopIconPath);
}
}
} /// <summary>
/// 重新确定控件大小
/// </summary>
protected void myResize()
{
int x = DistanceToBorder;
int y = DistanceToBorder;
int width = this.Width - * DistanceToBorder;
int height = this.Height - * DistanceToBorder;
rect = new RectangleF(x, y, width, height);
} /// <summary>
/// 绘制高亮效果
/// </summary>
/// <param name="g">Graphic对象</param>
protected virtual void DrawHighLight(Graphics g)
{
RectangleF highlightRect = rect;
highlightRect.Inflate(-BorderWidth / , -BorderWidth / );
Brush brush = Brushes.DodgerBlue;
if (buttonPressed)
{
brush = new LinearGradientBrush(rect, ButtonCenterColorStart, ButtonCenterColorEnd, GradientAngle);
} else
{
brush = new LinearGradientBrush(rect, Color.FromArgb(, Color.White),
Color.FromArgb(, Color.White), GradientAngle);
}
PaintShape(g, brush, highlightRect);
} /// <summary>
/// 绘制边框
/// </summary>
/// <param name="g">Graphics对象</param>
protected virtual void DrawBorder(Graphics g)
{
Pen p = new Pen(BorderColor);
if (Focused)
{
p.Color = FocusBorderColor;//外圈获取焦点后的颜色
p.Width = BorderWidth;
PaintShape(g, p, rect);
}
else
{
p.Width = BorderWidth;
PaintShape(g, p, rect);
} } /// <summary>
///
/// </summary>
/// <param name="g">Graphic对象</param>
protected virtual void DrawPressState(Graphics g)
{
RectangleF pressedRect = rect;
pressedRect.Inflate(-, -);
Brush brush = new LinearGradientBrush(rect, Color.FromArgb(, Color.White),
Color.FromArgb(, Color.White), GradientAngle);
PaintShape(g, brush, pressedRect);
} /// <summary>
/// 绘制图形
/// </summary>
/// <param name="g">Graphics对象</param>
/// <param name="pen">Pen对象</param>
/// <param name="rect">RectangleF对象</param>
protected virtual void PaintShape(Graphics g, Pen pen, RectangleF rect)
{
g.DrawEllipse(pen, rect);
} /// <summary>
/// 绘制图形
/// </summary>
/// <param name="g">Graphics对象</param>
/// <param name="brush">Brush对象</param>
/// <param name="rect">Rectangle对象</param>
protected virtual void PaintShape(Graphics g, Brush brush, RectangleF rect)
{
g.FillEllipse(brush, rect);
} #endregion
}
}

(^_^)

WinForm(C#)自定义控件之——RoundButton(圆形按钮)的更多相关文章

  1. WPF中添加Winform用户自定义控件

    过程:创建WPF工程->创建Winform用户自定义控件工程->WPF中引用控件->添加到Xaml页面 1.首先在WPF工程的解决方案上右击选择添加新建项目: 选择Windows窗体 ...

  2. WinForm GDI+自定义控件总结(一)

    前言 由于项目的原因好久没写博客了,也正是项目的原因开始系统的学习WinForm,从而接触到自定义控件的开发.自定义控件的开发有一定的难度,对开发者要求比较高,需要了解Windows运行的机制,熟悉w ...

  3. winform之自定义控件

    这样的一个控件 肯定得通过自定义控件来实现了 public class ProcessLabel : Control { public ProcessLabel() { //InitializeCom ...

  4. winform制作自定义控件(入门)

    原文链接:http://blog.csdn.net/bychentufeiyang/article/details/7081402   与原文基本一致,只是例子变成VS2012环境,语言采用博主常用的 ...

  5. WinForm创建自定义控件

    虽然VS为我们提供了很多控件可以使用,但有时候这些控件仍然不能满足我们的要求,比如我们要对部分控件进行一些个性化的定制,例如美化控件,这时候就需要自己绘制控件,或是在原有控件的基础上进行修改 自定义控 ...

  6. winform制作自定义控件

    一 .概述Windows 窗体控件是可再次使用的组件,它们封装了用户界面功能,并且可以用于客户端 Windows 应用程序.“Windows 窗体”不仅提供了许多现成控件,还提供了自行开发控件的基础结 ...

  7. WinForm用户自定义控件,在主窗体加载时出现闪烁;调用用户控件出现闪烁,需要鼠标才能够显示

    转载自:http://www.dotblogs.com.tw/rainmaker/archive/2012/02/22/69811.aspx 解决方案: 在调用用户控件的窗体里面添加一下代码: pro ...

  8. Winform 中 DesignMode 返回值不正确的问题。

    本文转载:http://blog.csdn.net/sabty/article/details/5325260 以前也曾遇到这样的问题,不过影响不大也没有去详细了解.今天又重新遇到此问题,实在太不便. ...

  9. Winform下让你的DataGridView控件支持点语法(即显示list中的子对象属性)

    前言: 不想看前言的直接去看正文吧!另外文末有彩蛋. DataGridView可以支持多种数据源格式,比如DataTable和List. DataTable没啥特殊的,本身就是一张二维的表,可以和Da ...

随机推荐

  1. ubuntu下 使用AB做压力测试

    1最近刚开始接触apache大数据下数据优化,讲一下apache 下ab压力测试工具. 程序“ab”尚未安装. 您可以使用以下命令安装: apt-get install apache2-utils 以 ...

  2. 在网上看到一个关于APP的测试

  3. 虚拟机显卡分配过高的警告(Insufficient video RAM)

    最近机房挪机柜,网线拔拔插插,又在虚拟机上配置了网卡的各项设置,其中一个虚拟机的网站这两天经常无法访问, 于是关注了一下虚拟机的“事件”,发现另外一个跳转网站的警告: 于是去vmware的官网上找到了 ...

  4. MetaData元数据

    一.基础 定义:数据库.表.列相关信息的描述.    何时使用:想取得对数据库的信息时使用.    一]数据库元数据——通过DataBaseMetaData            DataBaseMe ...

  5. ural 1671 Anansi's Cobweb

    这道题是并差集的简单应用 #include <cstdio> #include <cstring> #include <algorithm> #define max ...

  6. 设定PCB电路板形状和物理边界

    1 设定PCB电路板形状和物理边界 在Protel DXP的PCB板文件向导中,我们已经初步确定了电路板的形状和物理边界.但我们在绘制PCB板之前,也许还会对电路板的边界的细节加以调整.如果我们要对电 ...

  7. CH Round #55 - Streaming #6 (NOIP模拟赛day2)

    A.九九归一 题目:http://ch.ezoj.tk/contest/CH%20Round%20%2355%20-%20Streaming%20%236%20(NOIP模拟赛day2)/九九归一 题 ...

  8. sicily 1035. DNA matching

    题意:判断基因链是否匹配,匹配的双链数加1,并要标记,下次比较不能重用! 解法: 打擂台法 #include<iostream> #include<string> #inclu ...

  9. Java LinkedList 源码分析

    简介 LinkedList 是一个常用的集合类,用于顺序存储元素. LinkedList 经常和 ArrayList 一起被提及.大部分人应该都知道 ArrayList 内部采用数组保存元素,适合用于 ...

  10. 多线程面试题(Google)

    有四个线程1.2.3.4.线程1的功能就是输出1,线程2的功能就是输出2,以此类推.........现在有四个文件ABCD.初始都为空.现要让四个文件呈如下格式: A:1 2 3 4 1 2.... ...