{S0}简介
我必须强迫症(强迫性控制障碍)。标准的TrackBar我讨厌很长一段时间,但我只是把它到现在为止。我终于厌倦了枯燥的外观,代码TextBox或与它的标签显示的价值,它是什么标签。所以,这里是我需要的TrackBar的,希望它可以帮助你太多。有太多的属性,只是像我通常会列出他们,所以我决定列出的属性组的功能和整个列表截图。对照组包含控制的边界,价值和定位属性。的floatValue的价值是用鼠标移动滑块。标签是以上的TrackBar出现的文本。滑块线,刻度,滑块按钮本身。UpDownButtons的TrackBar的每个按钮增加一值。ValueBox框显示值。
属性大厦
建筑区域包含例程的设置布局,规模,岗位和控制所有的属性设置为基础的部分。
重载paint事件自定义绘制每一块控制在合适的地点以正确的方向。 Protected Overrides Sub OnPaint(ByVal e As System.Windows.Forms.PaintEventArgs)
MyBase.OnPaint(e)
'Setup the Graphics
Dim g As Graphics = e.Graphics
g.SmoothingMode = SmoothingMode.AntiAlias
g.TextRenderingHint = Drawing.Text.TextRenderingHint.AntiAlias
'Draw a Border around the control if requested
If _BorderShow Then
g.DrawRectangle(New Pen(_BorderColor), _
0, 0, Me.Width - 1, Me.Height - 1)
End If
'Add the value increment buttons if requested
If _UpDownShow Then DrawUpDnButtons(g)
'Add the Line and Tick Marks
DrawSliderLine(g)
'Draw the Label Text if requested
If _LabelShow Then
DrawLabel(g)
'g.DrawRectangle(Pens.Gray, rectLabel)
End If
'Add the Slider button
DrawSlider(g)
'Draw the Value above the Slider if requested
If _FloatValue AndAlso IsOverSlider AndAlso _
MouseState = eMouseState.Down Then
DrawFloatValue(g)
End If
'Draw the Box displaying the value if requested
If Not _ValueBox = eValueBox.None Then
DrawValueBox(g)
End If
'Draw Focus Rectangle around control if requested
If _ShowFocus AndAlso Me.Focused Then
ControlPaint.DrawFocusRectangle(g, New Rectangle( _
2 + CInt(Not _BorderShow), 2 + CInt(Not _BorderShow), _
Me.Width - ((2 + CInt(Not _BorderShow)) * 2), _
Me.Height - ((2 + CInt(Not _BorderShow)) * 2)), _
Color.Black, Me.BackColor)
End If
End Sub
我用基本的GDI函数绘制每一块的控制。我将重点介绍一些更好的部件。
在DrawUpDnButtons,我基本上有一个按钮,需要绘制的四个方向和哪一方是控制的方法之一。按钮本身就是一个渐变颜色填充的矩形。诀窍是箭头。我可以计算出每个箭头的位置和点创建为每一个单独的GraphicsPath,但我用一个矩阵来旋转和/或翻译一个简单的GraphicsPath的正确位置。
首先设置三个点,并添加行创建它们之间的三角箭头^形状:{C}
左手按钮,GraphicsPath的是方向正确,所以只需要进行翻译(移动)按钮的矩形内合适的位置。With rectDownButton
mx.Translate(5, CSng((rectDownButton.Y _
+ (rectDownButton.Height / 2)) - 6))
gp.Transform(mx)
g.DrawPath(pn, gp)
End With
为右手按钮,GraphicsPath的需要翻转,但没有一个翻转的内置函数。使用此GraphicsPath的水平,而不是翻转:新矩阵(-1,0,0,1,图像的宽度,0)。With rectUpButton
mx = New Matrix(-1, 0, 0, 1, 5, 0)
mx.Translate(.X + 9, 0, MatrixOrder.Append)
gp.Transform(mx)
g.DrawPath(pn, gp)
End With
上部按钮,GraphicsPath的需要旋转90度。寻找中心点和RotateAt这一点。With rectDownButton
mx.RotateAt(90, New PointF(gp.GetBounds.Width / 2, _
gp.GetBounds.Height / 2))
mx.Translate(CSng((rectDownButton.X + _
(rectDownButton.Width / 2)) - 3), 4, MatrixOrder.Append)
gp.Transform(mx)
g.DrawPath(pn, gp)
End With
对于较低的按钮,GraphicsPath的需求再次被翻转。使用此垂直翻转图像:新矩阵(1,0,0,-1,0,这里图像的高度)。With rectUpButton
mx = New Matrix(1, 0, 0, -1, 0, 10)
mx.Translate(0, .Y + 6, MatrixOrder.Append)
gp.Transform(mx)
g.DrawPath(pn, gp)
End With
的中心点,并在滑块刷FocusScales类型的PointF。当您创建一个新类型的PointF属性,你会发现这是在PropertyGrid中显示为灰色,但如果一个属性是Point类型,它会在PropertyGrid编辑正确。问题是,没有内置的PointF的TypeConverter。这其实是很容易解决的。
一个没有一个自定义TypeConverter的PointF类型的属性:工程代码,但你不能在PropertyGrid编辑。{S2}
随着PointFConverter,就像点属性在PropertyGrid执行。
创建一个属性,并添加引用我们要添加PointFConverter类的TypeConverter属性。Private _SliderHighlightPt As PointF = New PointF(-5.0F, -2.5F)
<Category("Appearance Slider")> _
<Description("Point on the Slider for the Highlight Color")> _
<TypeConverter(GetType(PointFConverter))> _
Public Property SliderHighlightPt() As PointF
Get
Return _SliderHighlightPt
End Get
Set(ByVal value As PointF)
_SliderHighlightPt = value
Me.Invalidate()
End Set
End Property
PointFConverter类继承ExpandableObjectConverter,覆盖的CanConvertFrom的ConvertFrom的ConvertTo功能。
鼠标事件Friend Class PointFConverter : Inherits ExpandableObjectConverter
Public Overloads Overrides Function CanConvertFrom( _
ByVal context As System.ComponentModel.ITypeDescriptorContext, _
ByVal sourceType As System.Type) As Boolean
If (sourceType Is GetType(String)) Then
Return True
End If
Return MyBase.CanConvertFrom(context, sourceType)
End Function
Public Overloads Overrides Function ConvertFrom( _
ByVal context As System.ComponentModel.ITypeDescriptorContext, _
ByVal culture As System.Globalization.CultureInfo, _
ByVal value As Object) As Object
If TypeOf value Is String Then
Try
Dim s As String = CType(value, String)
Dim ConverterParts(2) As String
ConverterParts = Split(s, ",")
If Not IsNothing(ConverterParts) Then
If IsNothing(ConverterParts(0)) Then ConverterParts(0) = "-5"
If IsNothing(ConverterParts(1)) Then ConverterParts(1) = "-2.5"
Return New PointF(CSng(ConverterParts(0).Trim), _
CSng(ConverterParts(1).Trim))
End If
Catch ex As Exception
Throw New ArgumentException("Can not convert '" & _
CStr(value) & "' to type Corners")
End Try
Else
Return New PointF(-5.0F, -2.5F)
End If
Return MyBase.ConvertFrom(context, culture, value)
End Function
Public Overloads Overrides Function ConvertTo( _
ByVal context As System.ComponentModel.ITypeDescriptorContext, _
ByVal culture As System.Globalization.CultureInfo, _
ByVal value As Object, ByVal destinationType As System.Type) As Object
If (destinationType Is GetType(System.String) _
AndAlso TypeOf value Is PointF) Then
Dim ConverterProperty As PointF = CType(value, PointF)
' build the string representation
Return String.Format("{0}, {1}", _
ConverterProperty.X, _
ConverterProperty.Y)
End If
Return MyBase.ConvertTo(context, culture, value, destinationType)
End Function
End Class 'PointFConverter Class
这里就是我们检查一下光标,如果按下鼠标按钮控制的一部分。根据这一信息,该值相应的调整。
因为在MouseDown,点击等一次性处理,需要一个计时器看到如果鼠标仍然下降,若然再次改变值。我不希望它尽快跑掉,因为它被点击的,所以有一个内置延迟权后点击鼠标,然后延迟后,将开始递增的价值。另一个问题是,如果最小/最大跨度大,它会抓取超慢和小跨度将压缩太快,所以定时器的时间间隔是调整的基础上跨度大。
关键事件Private Sub MouseTimer_Tick(ByVal sender As Object, _
ByVal e As System.EventArgs) Handles MouseTimer.Tick
'Check if mouse was just clicked
If MouseHoldDownTicker < 5 Then
MouseHoldDownTicker += 1
'Interval was set to 100 on MouseDown
'Tick off 5 times and then reset the Timer Interval
' based on the Min/Max span
If MouseHoldDownTicker = 5 Then
MouseTimer.Interval = CInt(Math.Max _
(10, 100 - ((_MaxValue - _MinValue) / 10)))
End If
Else
'Change the value until the mouse is released
Me.Value += MouseHoldDownChange
End If
End Sub
我想可以按箭头键调整值。这听起来简单。我想,我只想检查e.KeyValue KeyUp事件,并相应地调整值。好了,没有那么简单。问题是,在UserControl继承按钮,它会自动以不同的方式处理箭头键。 KeyUp事件后,重点跳转到下一个控件在Tab键顺序,即使您使用e.Handled和e.SuppressKeyPress。我无法阻止的重点有所改变。然后,我想我会用KeyDown事件,但猜测的箭头是什么,有自动忽略。要解决这种行为,我重写IsInputKey功能,让箭头键。在此之后,焦点不会跳走了。
历史版本1.0 - 2009年3月版本1.2 - 2009年4月新增焦点矩形分为自身的矩形区域的标签为更好地布局和浆纱总体布局修复版本1.3 - 2009年4月处理负范围版本1.4 - 2010年7月新增图像滑块新增UpDownShow隐藏和关闭向上/向下按钮新增计时器,直到释放鼠标改变其值(在短暂延迟之后)| SSDiver2112Protected Overrides Function IsInputKey( _
ByVal keyData As System.Windows.Forms.Keys) As Boolean
'Because a Usercontrol ignores the arrows in the KeyDown Event
'and changes focus no matter what in the KeyUp Event
'This is needed to fix the KeyDown problem
Select Case keyData And Keys.KeyCode
Case Keys.Up, Keys.Down, Keys.Right, Keys.Left
Return True
Case Else
Return MyBase.IsInputKey(keyData)
End Select
End Function
Private Sub gTrackBar_KeyUp(ByVal sender As Object, _
ByVal e As System.Windows.Forms.KeyEventArgs) Handles Me.KeyUp
Dim adjust As Integer = _ChangeSmall
If e.Shift Then
adjust = _ChangeLarge
End If
Select Case e.KeyValue
Case Keys.Up, Keys.Right
Me.Value += adjust
Case Keys.Down, Keys.Left
Me.Value -= adjust
End Select
End Sub