今天看了看IssueVision的源代码,把学习中的东西记录下来,以免忘掉了。
' Custom control that draws the caption for each pane. Contains an active
' state and draws the caption different for each state. Caption is drawn
' with a gradient fill and antialias font.

Imports System.Drawing.Drawing2D '使用GDI+绘制渐变背景和表面文字需要引用的类
Imports System.ComponentModel

PaneCaption
Inherits System.Windows.Forms.UserControl

' const values
'用来控制控件表面文字绘制的属性和控件默认的缺省属性
Consts
Public Const DefaultHeight As Integer = 26
Public Const DefaultFontName As String = "Tahoma"
Public Const DefaultFontSize As Integer = 12
Public Const PosOffset As Integer = 4 '文字相对于容器的绘制坐标位移
End Class

' internal members
Private m_active As Boolean = False '控件激活和无效两种状态控制
Private m_antiAlias As Boolean = True '用来控制控件表面文字的显示质量
Private m_allowActive As Boolean = True
Private m_text As String = ""
'两种状态默认文字、背景渐变颜色
Private m_colorActiveText As Color = Color.Black
Private m_colorInactiveText As Color = Color.White

Private m_colorActiveLow As Color = Color.FromArgb(255, 165, 78)
Private m_colorActiveHigh As Color = Color.FromArgb(255, 225, 155)
Private m_colorInactiveLow As Color = Color.FromArgb(3, 55, 145)
Private m_colorInactiveHigh As Color = Color.FromArgb(90, 135, 215)

' gdi objects
'绘制显示效果的笔刷
Private m_brushActiveText As SolidBrush
Private m_brushInactiveText As SolidBrush
Private m_brushActive As LinearGradientBrush
Private m_brushInactive As LinearGradientBrush
Private m_format As StringFormat


' public properties
' the caption of the control
'设置控件中的文本,并且在属性面板中可以选择
<Description("Text displayed in the caption."), _
Category("Appearance"), DefaultValue("")> _
![]()
Get
Return m_text
End Get

Set(ByVal value As String)
m_text = value
Invalidate() '重会控件的显示
End Set
End Property

'两个同样的属性,但是在即使按照上边控制Caption属性的方式来控制Text属性,属性面板中也不显示Text属性,不知动为什么?
![]()
Get
Return Me.Caption
End Get
Set(ByVal Value As String)
Me.Caption = Value
End Set
End Property

' if the caption is active or not
<Description("The active state of the caption, draws the caption with different gradient colors."), _
Category("Appearance"), DefaultValue(False)> _
![]()
Get
Return m_active
End Get
Set(ByVal value As Boolean)
m_active = value
Invalidate()
End Set
End Property

' if should maintain an active and inactive state
<Description("True always uses the inactive state colors, false maintains an active and inactive state."), _
Category("Appearance"), DefaultValue(True)> _
![]()
Get
Return m_allowActive
End Get
Set(ByVal value As Boolean)
m_allowActive = value
Invalidate()
End Set
End Property

' if the caption is active or not
<Description("If should draw the text as antialiased."), _
Category("Appearance"), DefaultValue(True)> _
![]()
Get
Return m_antiAlias
End Get
Set(ByVal value As Boolean)
m_antiAlias = value
Invalidate()
End Set
End Property

#Region " color properties "
<Description("Color of the text when active."), _
Category("Appearance"), DefaultValue(GetType(Color), "Black")> _
Color
Get
Return m_colorActiveText
End Get
Set(ByVal Value As Color)
If Value.Equals(Color.Empty) Then Value = Color.Black
m_colorActiveText = Value
m_brushActiveText = New SolidBrush(m_colorActiveText)
Invalidate()
End Set
End Property

<Description("Color of the text when inactive."), _
Category("Appearance"), DefaultValue(GetType(Color), "White")> _
Color
Get
Return m_colorInactiveText
End Get
Set(ByVal Value As Color)
If Value.Equals(Color.Empty) Then Value = Color.White
m_colorInactiveText = Value
m_brushInactiveText = New SolidBrush(m_colorInactiveText)
Invalidate()
End Set
End Property

<Description("Low color of the active gradient."), _
Category("Appearance"), DefaultValue(GetType(Color), "255, 165, 78")> _
Color
Get
Return m_colorActiveLow
End Get
Set(ByVal Value As Color)
If Value.Equals(Color.Empty) Then Value = Color.FromArgb(255, 165, 78)
m_colorActiveLow = Value
CreateGradientBrushes()
Invalidate()
End Set
End Property

<Description("High color of the active gradient."), _
Category("Appearance"), DefaultValue(GetType(Color), "255, 225, 155")> _
Color
Get
Return m_colorActiveHigh
End Get
Set(ByVal Value As Color)
If Value.Equals(Color.Empty) Then Value = Color.FromArgb(255, 225, 155)
m_colorActiveHigh = Value
CreateGradientBrushes()
Invalidate()
End Set
End Property

<Description("Low color of the inactive gradient."), _
Category("Appearance"), DefaultValue(GetType(Color), "3, 55, 145")> _
Color
Get
Return m_colorInactiveLow
End Get
Set(ByVal Value As Color)
If Value.Equals(Color.Empty) Then Value = Color.FromArgb(3, 55, 145)
m_colorInactiveLow = Value
CreateGradientBrushes()
Invalidate()
End Set
End Property

<Description("High color of the inactive gradient."), _
Category("Appearance"), DefaultValue(GetType(Color), "90, 135, 215")> _
Color
Get
Return m_colorInactiveHigh
End Get
Set(ByVal Value As Color)
If Value.Equals(Color.Empty) Then Value = Color.FromArgb(90, 135, 215)
m_colorInactiveHigh = Value
CreateGradientBrushes()
Invalidate()
End Set
End Property

#End Region

' internal properties
' brush used to draw the caption
SolidBrush
Get
Return CType(IIf(m_active AndAlso m_allowActive, _
m_brushActiveText, m_brushInactiveText), SolidBrush)
End Get
End Property

' gradient brush for the background
LinearGradientBrush
Get
Return CType(IIf(m_active AndAlso m_allowActive, _
m_brushActive, m_brushInactive), LinearGradientBrush)
End Get
End Property

' ctor
()
MyBase.New()

' this call is required by the Windows Form Designer
InitializeComponent()

' set double buffer styles
'设置双重缓冲,以改善控件的显示效果
Me.SetStyle(ControlStyles.DoubleBuffer Or ControlStyles.UserPaint Or _
ControlStyles.AllPaintingInWmPaint Or ControlStyles.ResizeRedraw, True)

' init the height
Me.Height = Consts.DefaultHeight

' format used when drawing the text
m_format = New StringFormat
m_format.FormatFlags = StringFormatFlags.NoWrap
m_format.LineAlignment = StringAlignment.Center '保证控件中文字的垂直对齐效果
'在不完全适合布局形状的字符串中修整字符,指定将文本修整成最接近的字符,并在被修整的行的末尾插入一个省略号
m_format.Trimming = StringTrimming.EllipsisCharacter

' init the font
Me.Font = New Font(Consts.DefaultFontName, Consts.DefaultFontSize, FontStyle.Bold)

' create gdi objects
Me.ActiveTextColor = m_colorActiveText
Me.InactiveTextColor = m_colorInactiveText

' setting the height above actually does this, but leave
' in incase change the code (and forget to init the
' gradient brushes)
CreateGradientBrushes()
End Sub

' internal methods
' the caption needs to be drawn
PaintEventArgs)

MyBase.OnPaint(e)
DrawCaption(e.Graphics)
End Sub

' draw the caption
Graphics)
' background
g.FillRectangle(Me.BackBrush, Me.DisplayRectangle)

' caption
If m_antiAlias Then
'控制文本呈现模式,指定在无提示的情况下使用每个字符的 AntiAlias
'标志符号位图来绘制字符。由于采用了 AntiAlias,质量会得到改善。
'由于关闭了提示,主干宽度差可能会比较明显。
g.TextRenderingHint = Drawing.Text.TextRenderingHint.AntiAlias
End If

' need a rectangle when want to use ellipsis
'绘制区域相对于控件有一定的位移
Dim bounds As RectangleF = New RectangleF(Consts.PosOffset, 0, _
Me.DisplayRectangle.Width - Consts.PosOffset, Me.DisplayRectangle.Height)

g.DrawString(m_text, Me.Font, Me.TextBrush, bounds, m_format)
End Sub

' clicking on the caption does not give focus,
' handle the mouse down event and set focus to self
MouseEventArgs)
MyBase.OnMouseDown(e)
If Me.m_allowActive Then Me.Focus()
End Sub

System.EventArgs)
MyBase.OnSizeChanged(e)

' create the gradient brushes based on the new size
CreateGradientBrushes()
End Sub

CreateGradientBrushes()
' can only create brushes when have a width and height
If Me.Width > 0 AndAlso Me.Height > 0 Then
If Not (m_brushActive Is Nothing) Then m_brushActive.Dispose()
m_brushActive = New LinearGradientBrush(Me.DisplayRectangle, _
m_colorActiveHigh, m_colorActiveLow, LinearGradientMode.Vertical)

If Not (m_brushInactive Is Nothing) Then m_brushInactive.Dispose()
m_brushInactive = New LinearGradientBrush(Me.DisplayRectangle, _
m_colorInactiveHigh, m_colorInactiveLow, LinearGradientMode.Vertical)
End If
End Sub


#Region " Windows Form Designer generated code "
'UserControl overrides dispose to clean up the component list.
)
If disposing Then
If Not (components Is Nothing) Then
components.Dispose()
End If
End If
MyBase.Dispose(disposing)
End Sub

'Required by the Windows Form Designer
Private components As System.ComponentModel.IContainer

'NOTE: The following procedure is required by the Windows Form Designer
'It can be modified using the Windows Form Designer.
'Do not modify it using the code editor.
InitializeComponent()
'
'PaneCaption
'
Me.Name = "PaneCaption"
Me.Size = New System.Drawing.Size(150, 30)
End Sub

#End Region

End Class
这是个很简单的控件,但是我想对初学者应该是有帮助的,主要体现在以下几点:
背景的渐变绘制
表面文字质量的控制
设计过程中的控件绘制控制
文字与控件调整的关系
属性面板的控制
总结一下:
由于是第一次学习制作控件,看看这个源代码对自己的帮助是很大的,在.Net中制作控件相对于VB可能略微复杂一点,但是效果要好很多,在我们现有的项目中原先的Panel控件完全是结合图片+Label来制作的,灵活性和资源利用率要差很多,采用GDI+来绘制控件,效果和质量要好很多。看这段代码应该对组件的制作和GDI+能有更好的理解和认识。
在自己仿照的编写过程中,基本上是看代码和帮助来完成的,发生了两个很笨的事情,一个是设计完组件,没有编译便想使用,结果控件无法使用,所有如果在项目中控件修改了,至少要编译一次在使用。另一个是设计完的控件找不到,后来在工具箱中找到我得用户控件才找到,笨呀.
相关文章:
-
2022-02-13
-
2022-12-23
-
2022-12-23
-
2021-04-12
-
2022-01-24
-
2021-10-13
-
2021-10-31
-
2021-05-20