科技行者

行者学院 转型私董会 科技行者专题报道 网红大战科技行者

知识库

知识库 安全导航

至顶网软件频道基础软件Visual Basic创建“五星”级控件

Visual Basic创建“五星”级控件

  • 扫一扫
    分享文章到微信

  • 扫一扫
    关注官方公众号
    至顶头条

本文的目标是 Windows MediaPlayer 中酷炫的“五星”级控件

作者:佚名 来源:MSDN 2007年10月14日

关键字:

  • 评论
  • 分享微博
  • 分享邮件
 拟定自定义和标准图像

  在我正在构建的控件中,我决定允许两种主要的图像类别:标准图像和用户提供的图像。虽然最初的控件只支持两种标准图形(圆形和正方形),但是稍后我将讨论一种将自定义图形添加到该列表中的方法。 该控件的所有绘图在 OnPaint 例程中进行处理,我重写了该例程以提供我自己的渲染代码(参见下面的示例代码)。

Protected Overrides Sub OnPaint(ByVal e As PaintEventArgs)
e.Graphics.Clear(Me.BackColor)

 Dim imageWidth, imageHeight As Integer
 imageWidth = (Me.Width-(LeftMargin + RightMargin + ( _
   Me.m_ImageSpacing * (Me.m_ImageCount-1)))) \ Me.m_ImageCount
   imageHeight = (Me.Height-(TopMargin + BottomMargin))

 Dim start As New Point(Me.LeftMargin, Me.TopMargin)

 For i As Integer = 0 To Me.ImageCount-1
  Me.ItemAreas(i).X = start.X-Me.ImageSpacing \ 2
  Me.ItemAreas(i).Y = start.Y
  Me.ItemAreas(i).Width = imageWidth + Me.ImageSpacing \ 2
  Me.ItemAreas(i).Height = imageHeight

  If Me.ImageToDraw = UserSuppliedImage Then
   DrawUserSuppliedImage(e.Graphics, _
   start.X, start.Y, imageWidth, imageHeight, i)
  Else
   DrawStandardImage(e.Graphics, Me.ImageToDraw, _
   start.X, start.Y, imageWidth, imageHeight, i)
  End If
   start.X += imageWidth + Me.ImageSpacing
 Next
 MyBase.OnPaint(e)
End Sub


Protected Overridable Sub DrawUserSuppliedImage( _
 ByVal g As Graphics, _
 ByVal x As Integer, ByVal y As Integer, _
 ByVal w As Integer, ByVal h As Integer, _
 ByVal currentPos As Integer)

 Dim img As Image
 If m_hovering And m_hoverItem > currentPos Then
  img = Me.HoverImage
 ElseIf Not m_hovering And m_selectedItem > currentPos Then
  img = Me.FilledImage
 Else
  img = Me.EmptyImage
 End If

 If Not img Is Nothing Then
  g.DrawImage(img, x, y, w, h)
 Else
  Me.DrawStandardImage(g, Me.Circle, x, y, w, h, currentPos)
 End If
End Sub

Protected Overridable Sub DrawStandardImage( _
 ByVal g As Graphics, ByVal ImageType As Integer, _
 ByVal x As Integer, ByVal y As Integer, _
 ByVal w As Integer, ByVal h As Integer, _
 ByVal currentPos As Integer)

 Dim fillBrush As Brush
 Dim outlinePen As Pen = New Pen(Me.OutlineColor, 1)

 If m_hovering And m_hoverItem > currentPos Then
  fillBrush = New SolidBrush(Me.HoverColor)
 ElseIf Not m_hovering And m_selectedItem > currentPos Then
  fillBrush = New SolidBrush(Me.SelectedColor)
 Else
  fillBrush = New SolidBrush(Me.EmptyColor)
 End If

 Select Case ImageType
  Case Me.Square
   g.FillRectangle(fillBrush, x, y, w, h)
   g.DrawRectangle(outlinePen, x, y, w, h)
  Case Me.Circle
   g.FillEllipse(fillBrush, x, y, w, h)
   g.DrawEllipse(outlinePen, x, y, w, h)
 End Select
End Sub


  在该例程中,计算每个图形的位置(使用 ImageCount 属性来确定应绘制的图形数量),然后调用 DrawStandardImage(绘制圆形或正方形)或 DrawUserSuppliedImage(绘制用户提供的图形)。 这些例程并不是最有效的(例如,我始终重新绘制完整的控件,而不是只将那些受特定更新影响的区域设置为无效),但是在必要时它们会考虑绘制适当的图形(或在标准选项情况下绘制适当的彩色图形)。在控件的其余代码中,每当属性或声明发生更改引起控件外观发生更改时,都会通过调用 Me.Invalidate 触发完整的重新绘图。OnMouseMove 的重写例程是这种类型代码的一个示例:

Protected Overrides Sub OnMouseMove(ByVal e As MouseEventArgs)
 For i As Integer = 0 To Me.ImageCount-1
  If Me.ItemAreas(i).Contains(e.X, e.Y) Then
   Me.m_hoverItem = i + 1
   Me.Invalidate()
   Exit For
  End If
 Next
 MyBase.OnMouseMove(e)
End Sub

  处理和启动事件

  此时,该控件运行正常,主要是因为从 System.Windows.Forms.Control 中继承了所有出色的功能。这种继承关系为控件提供了一组可用功能,包括“Click”事件和拖动到 Windows 窗体的设计表面的能力。但是所需的不只是那些标准的功能,因此,我将向几个重要域中添加新的事件和代码(参见下面的示例代码)。

Public Event SelectedItemChanged As EventHandler

Protected Overridable Sub OnSelectedItemChanged()
 RaiseEvent SelectedItemChanged(Me, EventArgs.Empty)
End Sub

Public Property SelectedItem() As Integer
 Get
  Return m_selectedItem
 End Get
 Set(ByVal Value As Integer)
  If Value >= 0 And Value <= Me.ImageCount + 1 Then
   m_selectedItem = Value
   OnSelectedItemChanged()
  Else
   Value = 0
  End If
 End Set
End Property


  这个新的 SelectedItemChanged 事件提供了许多便利,它还具有很好的辅助作用,即改善数据绑定性能。如果 Windows 窗体数据绑定代码发现一个事件,该事件具有遵循 Changed 格式的名称以及具有被定义为 System.EventHandler 的签名,则它将使用该事件作为绑定属性发生更改的通知。与轮询任何更改的属性相比,监控该事件的工作量要小得多,因此,最后将获得更有效的数据绑定。 我需要向控件中添加的其他例程只有 OnMouseEnter 和 OnMouseLeave 例程的重写,以确保用户在其上悬停时我正确地显示控件。

  如下面的代码所示,我还需要重写 OnClick 例程,这样,在用户选取新的等级值时,我可以正确地更新当前选定的项目。 此时,虽然我可以添加许多“装饰品”,例如指定工具箱位图以及对我的属性进行分类的属性,但是该控件基本上已经完成,并且可以很好地工作。尽管如此,下一个窍门是允许其他开发人员对我的工作进行扩展,以便为其他图形提供支持。

Protected Overrides Sub OnClick(ByVal e As System.EventArgs)
 Dim pt As Point = Me.PointToClient(Me.MousePosition)

 For i As Integer = 0 To Me.ImageCount-1
 If Me.ItemAreas(i).Contains(pt) Then
   Me.m_hoverItem = i + 1
   Me.SelectedItem = i + 1
   Me.Invalidate()
   Exit For
 End If
 Next
 MyBase.OnClick(e)
End Sub

    • 评论
    • 分享微博
    • 分享邮件
    邮件订阅

    如果您非常迫切的想了解IT领域最新产品与技术信息,那么订阅至顶网技术邮件将是您的最佳途径之一。

    重磅专题
    往期文章
    最新文章