博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
C# GDI+绘制矩形圆角
阅读量:6912 次
发布时间:2019-06-27

本文共 9651 字,大约阅读时间需要 32 分钟。

一、前言

本文主要介绍C# GDI+如何绘制矩行的圆角,其中涉及到如何使用位操作来处理组合的技巧。GDI+的本质在于,它能够替代开发人员实现与显示器及其它外部设备的交互。对于控件美化而言,需要达到自己期望的效果,GDI+必不可少。绘制后的圆角效果图如下:

 

二、圆角枚举与相应组合处理设计

 对于矩行而言,圆角分为左上角、右上角、左下角和右下角。组合情况就分为无圆角、一个圆角、二个圆角、三个圆角以及四个圆角。枚举需要满足该组合情况,没必要在枚举中将 全部组合列出,只需要通过位操作就能计算出属于哪种组合。枚举类设计如下:

 1    [Flags]
 2     
public 
enum RoundStyle
 3     {     
 4         None = 
0,     
 5         TopLeft = 
1,
 6         TopRight = 
2,
 7         BottomLeft = 
4,
 8         BottomRight = 
8 ,
 9         All = TopLeft | TopRight | BottomLeft | BottomRight
10     }

 

矩行的圆角所有组合情况如下:
RoundStyle.None   
RoundStyle.All       
RoundStyle.BottomLeft
RoundStyle.BottomRight
RoundStyle.TopLeft

RoundStyle.TopRight

RoundStyle.BottomRight | RoundStyle.BottomLeft

RoundStyle.BottomRight | RoundStyle.TopRight
RoundStyle.TopRight | RoundStyle.TopLeft
RoundStyle.BottomLeft | RoundStyle.TopLeft
RoundStyle.BottomRight | RoundStyle.TopLeft
RoundStyle.TopRight | RoundStyle.BottomLeft

RoundStyle.BottomLeft | RoundStyle.BottomRight | RoundStyle.TopLeft

RoundStyle.BottomLeft | RoundStyle.BottomRight | RoundStyle.TopRight
RoundStyle.BottomLeft | RoundStyle.TopLeft | RoundStyle.TopRight
RoundStyle.BottomRight | RoundStyle.TopRight | RoundStyle.TopLeft

对于每一种组合,必须提供相应的操作来执行路径计算,这主要是因为GraphicsPath的路径是有顺序的。因此所有组合对应的处理方式如下:

 1         
private 
static IDictionary<RoundStyle, Action<GraphicsPath, Rectangle, 
int
int>>
 2             CreateRoundStylesEventContainer()
 3         {
 4             
var container = 
new Dictionary<RoundStyle, Action<GraphicsPath, Rectangle, 
int
int>>();
 5 
 6             container.Add(RoundStyle.None, (path, rect, radius, radiusAdjustment) => { path.AddRectangle(rect); });
 7             container.Add(RoundStyle.All, AddAllRoundStyle);
 8 
 9             container.Add(RoundStyle.BottomLeft, AddBottomLeftRoundStyle);
10             container.Add(RoundStyle.BottomRight, AddBottomRightRoundStyle);
11             container.Add(RoundStyle.TopLeft, AddTopLeftRoundStyle);
12             container.Add(RoundStyle.TopRight, AddTopRightRoundStyle);
13 
14             container.Add(RoundStyle.BottomRight | RoundStyle.BottomLeft, AddBottomRightAndBottomLeftRoundStyle);
15             container.Add(RoundStyle.BottomRight | RoundStyle.TopRight, AddBottomRightAndTopRightRoundStyle);
16             container.Add(RoundStyle.TopRight | RoundStyle.TopLeft, AddTopRightAndTopLeftRoundStyle);
17             container.Add(RoundStyle.BottomLeft | RoundStyle.TopLeft, AddBottomLeftAndTopLeftRoundStyle);
18             container.Add(RoundStyle.BottomRight | RoundStyle.TopLeft, AddBottomRightAndTopLeftRoundStyle);
19             container.Add(RoundStyle.TopRight | RoundStyle.BottomLeft, AddTopRightAndBottomLeftRoundStyle);
20 
21             container.Add(RoundStyle.BottomLeft | RoundStyle.BottomRight | RoundStyle.TopLeft, AddBottomAndTopLeftRoundStyle);
22             container.Add(RoundStyle.BottomLeft | RoundStyle.BottomRight | RoundStyle.TopRight, AddBottomAndTopRightRoundStyle);
23             container.Add(RoundStyle.BottomLeft | RoundStyle.TopLeft | RoundStyle.TopRight, AddTopAndBottomLeftRoundStyle);
24             container.Add(RoundStyle.BottomRight | RoundStyle.TopRight | RoundStyle.TopLeft, AddTopAndBottomRightRoundStyle);
25 
26             
return container;
27         }

 

三、GraphicsPath.AddArc方法

GraphicsPath.AddArc 方法如下:

1 
public 
void AddArc(Rectangle rect, 
float startAngle, 
float sweepAngle);
2 
public 
void AddArc(RectangleF rect, 
float startAngle, 
float sweepAngle);
3 
public 
void AddArc(
float x, 
float y, 
float width, 
float height, 
float startAngle, 
float sweepAngle);
4 
public 
void AddArc(
int x, 
int y, 
int width, 
int height, 
float startAngle, 
float sweepAngle);

 

此方法主要是绘制圆角的,绘制的方式与二位坐标的角度是不一样,官方参数资料如下:

x                 矩形区域左上角的 X 轴坐标,这个矩形区域定义用來绘制弧形的橢圆形。

y                 矩形区域左上角的 Y 轴座標,这个矩形区域定义用來绘制弧形的橢圆形。
width           矩形区域的寬度,这个矩形区域定义用來绘制弧形的橢圆形。
height          矩形区域的高度,这个矩形区域定义用來绘制弧形的橢圆形。
startAngle    弧形的开始点角度,順時针自 X 轴所测得的度数。
sweepAngle  介於弧形的 startAngle 和结束点的角度。

 

如果圆形中具有先前的直线或曲线,会加入线段來将先前线段的结束点连接到弧形的开端。

弧形是沿着指定矩形范围內的橢圆形周围所描绘的。弧形的开始点是由橢圆形的 X 轴 (0 度角) 順時针测量开始点角度的度数所決定。结束点位置的決定很类似,从开始点順時针测量跨越角度的度数所決定。如果跨越的角度大於 360 度或小於 -360 度,则弧形分別跨越了 360 度或 -360 度。

 

弧形的开始点是由橢圆形的 X 轴 (0 度角) 順時针测量开始点角度的度数所決定,GraphicsPath增加对象的顺序也是需要注意的(有部分连接线是系统绘制的)。此处与数学中二位坐标定义的角度是反方向的,需要特别注意。

 

、绘制圆角组合

3.1 绘制一个圆角

矩行的一个圆角所有组合情况如下:RoundStyle.BottomLeft、RoundStyle.BottomRight、RoundStyle.TopLeft、RoundStyle.TopRight。绘制方法如下:

ExpandedBlockStart.gif
绘制一个圆角
        
private 
static 
void AddBottomLeftRoundStyle(GraphicsPath path,
            Rectangle rect, 
int radius, 
int radiusAdjustment)
        {
            AddBottomLeftArc(rect, radius, path, radiusAdjustment);
            AddTopLine(rect, path, radiusAdjustment);
            AddRightLine(rect, path, radiusAdjustment);
        }
        
private 
static 
void AddBottomRightRoundStyle(GraphicsPath path,
            Rectangle rect, 
int radius, 
int radiusAdjustment)
        {
            AddBottomRightArc(rect, radius, path, radiusAdjustment);
            AddLeftLine(rect, path, radiusAdjustment);
            AddTopLine(rect, path, radiusAdjustment);
        }
        
private 
static 
void AddTopRightRoundStyle(GraphicsPath path,
            Rectangle rect, 
int radius, 
int radiusAdjustment)
        {
            AddTopRightArc(rect, radius, path, radiusAdjustment);
            AddBottomLine(rect, path, radiusAdjustment);
            AddLeftLine(rect, path, radiusAdjustment);
        }
        
private 
static 
void AddTopLeftRoundStyle(GraphicsPath path,
            Rectangle rect, 
int radius, 
int radiusAdjustment)
        {
            AddTopLeftArc(rect, radius, path, radiusAdjustment);
            AddRightLine(rect, path, radiusAdjustment);
            AddBottomLine(rect, path, radiusAdjustment);
        }

效果图如下:

 

3.2 绘制二个圆角

矩行的一个圆角所有组合情况如下:

RoundStyle.BottomRight | RoundStyle.BottomLeft

RoundStyle.BottomRight | RoundStyle.TopRight
RoundStyle.TopRight | RoundStyle.TopLeft
RoundStyle.BottomLeft | RoundStyle.TopLeft
RoundStyle.BottomRight | RoundStyle.TopLeft
RoundStyle.TopRight | RoundStyle.BottomLeft。

绘制方法如下:

ExpandedBlockStart.gif
绘制二个圆角
        
private 
static 
void AddTopRightAndBottomLeftRoundStyle(GraphicsPath path,
            Rectangle rect, 
int radius, 
int radiusAdjustment)
        {
            AddTopRightArc(rect, radius, path, radiusAdjustment);
            AddBottomLineWithLeftOffset(path, rect, radius, radiusAdjustment, 
false);
            AddBottomLeftArc(rect, radius, path, radiusAdjustment);
            AddTopLineWithRightOffset(path, rect, radius, radiusAdjustment);
        }
        
private 
static 
void AddBottomRightAndTopLeftRoundStyle(GraphicsPath path,
            Rectangle rect, 
int radius, 
int radiusAdjustment)
        {
            AddBottomRightArc(rect, radius, path, radiusAdjustment);
            AddBottomLineWithRightOffset(path, rect, radius, radiusAdjustment);
            AddTopLeftArc(rect, radius, path, radiusAdjustment);
            AddTopLineWithLeftOffset(path, rect, radius, radiusAdjustment);
        }
        
private 
static 
void AddBottomLeftAndTopLeftRoundStyle(GraphicsPath path,
            Rectangle rect, 
int radius, 
int radiusAdjustment)
        {
            AddBottomLeftArc(rect, radius, path, radiusAdjustment);
            AddTopLeftArc(rect, radius, path, radiusAdjustment);
            AddRightLine(rect, path, radiusAdjustment);
        }
        
private 
static 
void AddTopRightAndTopLeftRoundStyle(GraphicsPath path,
            Rectangle rect, 
int radius, 
int radiusAdjustment)
        {
            AddTopLeftArc(rect, radius, path, radiusAdjustment);
            AddTopRightArc(rect, radius, path, radiusAdjustment);
            AddBottomLine(rect, path, radiusAdjustment);
        }
        
private 
static 
void AddBottomRightAndTopRightRoundStyle(GraphicsPath path,
            Rectangle rect, 
int radius, 
int radiusAdjustment)
        {
            AddTopRightArc(rect, radius, path, radiusAdjustment);
            AddBottomRightArc(rect, radius, path, radiusAdjustment);
            AddLeftLine(rect, path, radiusAdjustment);
        }
        
private 
static 
void AddBottomRightAndBottomLeftRoundStyle(GraphicsPath path,
            Rectangle rect, 
int radius, 
int radiusAdjustment)
        {
            AddBottomRightArc(rect, radius, path, radiusAdjustment);
            AddBottomLeftArc(rect, radius, path, radiusAdjustment);
            AddTopLine(rect, path, radiusAdjustment);
        }

效果图如下:

 

3.2 绘制三个圆角

矩行的一个圆角所有组合情况如下:

RoundStyle.BottomLeft | RoundStyle.BottomRight | RoundStyle.TopLeft

RoundStyle.BottomLeft | RoundStyle.BottomRight | RoundStyle.TopRight
RoundStyle.BottomLeft | RoundStyle.TopLeft | RoundStyle.TopRight
RoundStyle.BottomRight | RoundStyle.TopRight | RoundStyle.TopLeft。

绘制方法如下:

ExpandedBlockStart.gif
绘制三个圆角
        
private 
static 
void AddTopAndBottomRightRoundStyle(GraphicsPath path,
            Rectangle rect, 
int radius, 
int radiusAdjustment)
        {
            AddTopLeftArc(rect, radius, path, radiusAdjustment);
            AddTopRightArc(rect, radius, path, radiusAdjustment);
            AddBottomRightArc(rect, radius, path, radiusAdjustment);
            AddBottomLineWithRightOffset(path, rect, radius, radiusAdjustment);
        }
        
private 
static 
void AddTopAndBottomLeftRoundStyle(GraphicsPath path,
            Rectangle rect, 
int radius, 
int radiusAdjustment)
        {
            AddTopLeftArc(rect, radius, path, radiusAdjustment);
            AddTopRightArc(rect, radius, path, radiusAdjustment);
            AddBottomLineWithLeftOffset(path, rect, radius, radiusAdjustment, 
false);
            AddBottomLeftArc(rect, radius, path, radiusAdjustment);
        }
        
private 
static 
void AddBottomAndTopRightRoundStyle(GraphicsPath path,
            Rectangle rect, 
int radius, 
int radiusAdjustment)
        {
            AddBottomRightArc(rect, radius, path, radiusAdjustment);
            AddBottomLeftArc(rect, radius, path, radiusAdjustment);
            AddTopLineWithRightOffset(path, rect, radius, radiusAdjustment);
            AddTopRightArc(rect, radius, path, radiusAdjustment);
        }
        
private 
static 
void AddBottomAndTopLeftRoundStyle(GraphicsPath path,
            Rectangle rect, 
int radius, 
int radiusAdjustment)
        {
            AddBottomRightArc(rect, radius, path, radiusAdjustment);
            AddBottomLeftArc(rect, radius, path, radiusAdjustment);
            AddTopLeftArc(rect, radius, path, radiusAdjustment);
            AddTopLineWithLeftOffset(path, rect, radius, radiusAdjustment);
        }

效果图如下:

 

3.4 绘制四个圆角

矩行的四个圆角所有组合情况如下:RoundStyle.All或者RoundStyle.BottomLeft | RoundStyle.BottomRight | RoundStyle.TopLeft | RoundStyle.TopRight。

绘制方法如下:

ExpandedBlockStart.gif
绘制四个圆角
        
private 
static 
void AddAllRoundStyle(GraphicsPath path,
            Rectangle rect, 
int radius, 
int radiusAdjustment)
        {
            AddTopLeftArc(rect, radius, path, radiusAdjustment);
            AddTopRightArc(rect, radius, path, radiusAdjustment);
            AddBottomRightArc(rect, radius, path, radiusAdjustment);
            AddBottomLeftArc(rect, radius, path, radiusAdjustment);
        }

效果图如下:

 

、总结

绘制圆角在美化控件方面的场景还是比较多的,本文采用枚举的位操作来对所有情况进行操作。有一段时间没写随笔了,可以写的东西很多,由于个人的时间问题却一直拖到现在。上面的圆角绘制例子是昨天作为练习写的,只是简单的手动测试了一下,如有BUG请及时通知本人,不胜感激。目前开发的产品很多控件都需要自绘,统计学需要写的算法也比较多。虽然项目成员总人数为100,但开发所占的比例才40%不到,任重而道远。

 

源码下载:

转载地址:http://apicl.baihongyu.com/

你可能感兴趣的文章
寻找&删除大文件及大文件夹
查看>>
关于黑板的独特创意
查看>>
1003. Emergency
查看>>
内置函数
查看>>
学C++之感悟
查看>>
vue的一些注意点
查看>>
使用Selenium抓取百度指数一
查看>>
python 日志工具 Dict4ini 的简单使用示例
查看>>
我的友情链接
查看>>
Java OOP初探
查看>>
Linux中配置ftp服务器
查看>>
DHCP 服务器 Server2003 到 Server 2012 迁移(一)
查看>>
shell中“2 > &1”的含义
查看>>
Puppet 源码安装篇
查看>>
Ignoring query to other database
查看>>
Centos6.4安装OTRS必须成功版!
查看>>
List,ArrayList,Map循环遍历
查看>>
我的友情链接
查看>>
objectclass and objectcategory
查看>>
常用模块自动化安装脚本
查看>>