椭圆/圆形按钮






3.50/5 (18投票s)
2005年5月6日
4分钟阅读

113620

5432
学习如何绘制具有 3D 或弹出样式的椭圆/圆形按钮。
引言
我自认为是 VB.NET 编程的新手,因为我只有 3 个月的 VB.NET 实践经验。在我新工作的项目期间,我注意到 Visual Studio .NET 只为开发人员提供了一种按钮,那就是矩形按钮。我很好奇想创建另一种形状的按钮。我问自己创建按钮控件有多难。我认为创建它非常困难,尤其是带有 3D 效果的。因此,我决定翻书开始阅读 GDI 编程以及如何使用 VB.NET 为 .NET 构建控件。我打印了一张带有几个普通按钮的表单,然后开始盯着它们看。我注意到如果我把表单倒过来,按钮看起来就像被按下了。然后我注意到按钮的顶部和左侧线条颜色较浅,而底部和右侧线条则绘制为黑色或深色。我对自己说,这可能比我想象的要容易得多,可以画出按钮。
椭圆控件有两种样式:Standard
(标准),具有 3D 效果;Popup
(弹出),看起来是平坦的,除非鼠标光标移到它上面,这时它看起来就像 Standard
样式。
与本网站的许多作者相比,我可能只有一点点编程经验。但我非常乐意与大家分享我的新知识,如果您有任何反馈,我将非常高兴。
变量和属性
mousePressed
-Boolean
- 如果按钮被按下,则为True
。否则为False
。MeGotFocus
-Boolean
- 如果按钮获得焦点,则为True
。否则为False
。MouseOver
-Boolean
- 如果光标在按钮上,则为True
。否则为False
。ButtonStyle
-Standard
(标准)或Popup
(弹出)。ButtonImage
-Button
- 位图图像。
Image
- 获取或设置按钮的位图图像。Text
- 获取或设置与此控件关联的文本。FlatStyle
- 获取或设置Button
控件的扁平样式外观。
绘制按钮
我通过继承 Control
类开始构建按钮。继承 Class control 为我提供了所有我需要的事件,例如 onClick
、onMouseUp
、onMouseDown
、onKeyUp
、onKeyDown
,以及最重要的 onPaint
方法。
当我开始编写 onPaint
事件时,我只使用了 Graphics
类,这是错误的。在开始绘制按钮的线条之前,我们需要使用 GraphicsPath
类绘制按钮的 Region
(区域)。
Dim a As New System.Drawing.Drawing2D.GraphicsPath
recRegion = New RectangleF(0, 0, Me.Width, Me.Height)
a.AddEllipse(recRegion)
Me.Region = New Region(a)
绘制完椭圆区域后,就可以绘制线条了。我使用 DrawArc
方法绘制按钮的边缘。当按钮未被按下时,我选择 controlDarkDark
颜色绘制底部弧线,选择 controlLightLight
颜色绘制顶部弧线。在使用 Graphics
类进行绘制之前,强烈建议将 SmoothingMode
属性设置为 AntiAlias
。否则,绘制的线条将不平滑,按钮看起来会很难看。
Dim p1 As Pen
Dim p2 As Pen
recBorder = New RectangleF(1, 1, Me.Width - 2, Me.Height - 2)
'This line is very important to have smooth cruves. Otherwise,
'the button will look so ugly.
g.SmoothingMode = Drawing2D.SmoothingMode.AntiAlias
' Now we need to draw the 3D effect. Remember we can only draw on
' the ellipse now.
g.DrawArc(p1, recBorder, 180, -180)
g.DrawArc(p2, recBorder, 180, 180)
现在我们有一个空白的椭圆按钮,没有文本或图像。在这个例子中,我选择如果不存在图像,则将文本居中显示在按钮上。但是,如果用户填充了 Image
属性,文本将左对齐。
以下代码检查鼠标是否被按下以及 Image
属性是否被填充。g.MeasureString
非常有用。它返回绘制文本的尺寸,用于计算绘制文本的起始点。为了在按钮被按下时模拟 3D 效果,文本和图像(如果适用)会向右移两位像素,向下移两位像素。
' Measure the size of the String to centralize it.
' If an image is present, the text is drawn next to the icon.
Dim textSize As SizeF = g.MeasureString(Me.Text, Me.Font)
'If the Mouse is pressed draw the text and the image, if available,
' shifted 2 pixels to the right to simulate the 3D effect
If Me.mousePressed Then
If Me._Image Is Nothing Then
g.DrawString(Me.Text, Me.Font, stringBrush, _
(((Me.Width + 3) - textSize.Width) / 2) + 2, _
(((Me.Height + 2) - textSize.Height) / 2) + 2)
Else
Dim pt As New Point(((Me.Width + 3) / 12) + 1, _
((Me.Height + 2 - 16) / 2) + 1)
Dim recString As New Rectangle(pt, New Size(16, 16))
g.DrawImage(_Image, recString)
g.DrawString(Me.Text, Me.Font, stringBrush, _
recString.X + recString.Width + 3,
(((Me.Height + 2) - textSize.Height) / 2) + 2)
End If
Else
If Me._Image Is Nothing Then
g.DrawString(Me.Text, Me.Font, stringBrush, _
(((Me.Width + 3) - textSize.Width) / 2), _
(((Me.Height + 2) - textSize.Height) / 2))
Else
Dim pt As New Point((Me.Width + 3) / 12, (Me.Height + 2 - 16) / 2)
Dim recString As New Rectangle(pt, New Size(16, 16))
g.DrawImage(_Image, recString)
g.DrawString(Me.Text, Me.Font, stringBrush, _
recString.X + recString.Width + 3,
(((Me.Height + 2) - textSize.Height) / 2))
End If
End If
标准样式按钮和弹出样式之间的唯一区别是边框颜色。如前所述,标准按钮的上弧线(从 0-180 度)用 controlLightLight
颜色绘制,下弧线(从 0- (-180) 度)用 controlDarkDark
颜色绘制。然而,当鼠标光标不在按钮区域内时,弹出样式的边框是用一种颜色绘制的。
'If the mouse is over the button,
' button should look like the standard one.
If Me.MouseOver = True Then
If Me.mousePressed Then
p1 = New Pen(SystemColors.ControlDarkDark, 1)
p2 = New Pen(SystemColors.ControlDarkDark, 1)
Else
p1 = New Pen(SystemColors.ControlDarkDark, 1)
p2 = New Pen(SystemColors.ControlLightLight, 1)
End If
Else ' if mouse is not over the button, the button looks flat
p1 = New Pen(SystemColors.ControlDark, 1.5)
p2 = New Pen(SystemColors.ControlDark, 1.5)
End If
我希望这个按钮能像我的技能所允许的那样专业。因此,我决定让它显示它获得焦点,通过在按钮获得焦点时绘制一个虚线椭圆。
'If the control has focus, an elliptical dotted line is drawn to
'show that the button has focus
If Me.MeGotFocus Then
Dim gotFocusPen As New Pen(Color.Black, 1.3)
Dim recFocus As Rectangle
gotfocuspen.DashStyle = Drawing2D.DashStyle.Dot
gotfocuspen.DashCap = Drawing2D.DashCap.Round
recFocus = New Rectangle(4, 4, Me.Width - 8, Me.Height - 8)
g.DrawEllipse(gotFocusPen, recFocus)
End If
历史
这是该控件的初始发布版本。我很快还会添加扁平样式。敬请关注。如果您有任何建议,请告诉我。