IssueVision的PaneCaption控件源码分析

 今天看了看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

Public Class PaneCaption
    
Inherits System.Windows.Forms.UserControl

    
' const values
    '用来控制控件表面文字绘制的属性和控件默认的缺省属性
    Private Class 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(25516578)
    
Private m_colorActiveHigh As Color = Color.FromArgb(255225155)
    
Private m_colorInactiveLow As Color = Color.FromArgb(355145)
    
Private m_colorInactiveHigh As Color = Color.FromArgb(90135215)

    
' 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("")> _
    
Public Property Caption() As String
        
Get
            
Return m_text
        
End Get

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


    
'两个同样的属性,但是在即使按照上边控制Caption属性的方式来控制Text属性,属性面板中也不显示Text属性,不知动为什么?
    Public Overrides Property Text() As String
        
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)> _
    
Public Property Active() As Boolean
        
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)> _
    
Public Property AllowActive() As Boolean
        
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)> _
    
Public Property AntiAlias() As Boolean
        
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")> 
_
    
Public Property ActiveTextColor() As 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")> _
    
Public Property InactiveTextColor() As 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")> _
    
Public Property ActiveGradientLowColor() As Color
        
Get
            
Return m_colorActiveLow
        
End Get
        
Set(ByVal Value As Color)
            
If Value.Equals(Color.Empty) Then Value = Color.FromArgb(25516578)
            m_colorActiveLow 
= Value
            CreateGradientBrushes()
            Invalidate()
        
End Set
    
End Property


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


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


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


#
End Region

    
' internal properties

    
' brush used to draw the caption
    Private ReadOnly Property TextBrush() As SolidBrush
        
Get
            
Return CType(IIf(m_active AndAlso m_allowActive, _
             m_brushActiveText, m_brushInactiveText), SolidBrush)
        
End Get
    
End Property


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


    
' ctor
    Public Sub New()
        
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
    Protected Overrides Sub OnPaint(ByVal e As PaintEventArgs)

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


    
' draw the caption
    Private Sub DrawCaption(ByVal g As 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
    Protected Overrides Sub OnMouseDown(ByVal e As MouseEventArgs)
        
MyBase.OnMouseDown(e)
        
If Me.m_allowActive Then Me.Focus()
    
End Sub


    
Protected Overrides Sub OnSizeChanged(ByVal e As System.EventArgs)
        
MyBase.OnSizeChanged(e)

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


    
Private 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 NothingThen m_brushActive.Dispose()
            m_brushActive 
= New LinearGradientBrush(Me.DisplayRectangle, _
             m_colorActiveHigh, m_colorActiveLow, LinearGradientMode.Vertical)

            
If Not (m_brushInactive Is NothingThen 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.
    Protected Overloads Overrides Sub Dispose(ByVal disposing As Boolean)
        
If disposing Then
            
If Not (components Is NothingThen
                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.
    <System.Diagnostics.DebuggerStepThrough()> Private Sub InitializeComponent()
        
'
        'PaneCaption
        '
        Me.Name = "PaneCaption"
        Me.Size = New System.Drawing.Size(15030)
    
End Sub


#
End Region

End Class


这是个很简单的控件,但是我想对初学者应该是有帮助的,主要体现在以下几点:

背景的渐变绘制

表面文字质量的控制

设计过程中的控件绘制控制

文字与控件调整的关系

属性面板的控制

总结一下:
由于是第一次学习制作控件,看看这个源代码对自己的帮助是很大的,在.Net中制作控件相对于VB可能略微复杂一点,但是效果要好很多,在我们现有的项目中原先的Panel控件完全是结合图片+Label来制作的,灵活性和资源利用率要差很多,采用GDI+来绘制控件,效果和质量要好很多。看这段代码应该对组件的制作和GDI+能有更好的理解和认识。

在自己仿照的编写过程中,基本上是看代码和帮助来完成的,发生了两个很笨的事情,一个是设计完组件,没有编译便想使用,结果控件无法使用,所有如果在项目中控件修改了,至少要编译一次在使用。另一个是设计完的控件找不到,后来在工具箱中找到我得用户控件才找到,笨呀.




posted on 2005-02-03 13:54  Duiker  阅读(1380)  评论(5编辑  收藏  举报

导航