|
|||||||||||||||||||||||||||||||||
|
|||||||||||||||||||||||||||||||||
|
Announcements
Chapters
Services
Feature Zones
|
IntroductionHans Dietrich did a good job in creating a Windows Media Player like
This control is still in its infantile period and many things could be added to it. I would appreciate any advice to enhance its performance. First things firstSome introduction to GDI+GDI+ differs from GDI in two aspects:
GDI+ can be used to show images, draw custom shapes and lines, draw strings, and even image transformation. In our project, we use it to draw and fill shapes, and show images. In order to use GDI+, a Dim g as Graphics = Button1.CreateGraphics
If you want to draw lines or shapes, a Dim myPen as new Pen(Color.Red)
Then you can draw lines and shapes: g.DrawLine(myPen, 1, 1, 45, 65) 'draw line
g.DrawBezier(myPen, 15, 15, 30, 30, 45, 30, 87, 20) 'draw Bezier curve
g.DrawEllipse(myPen, New Rectangle(33, 45, 40, 50)) 'draw ellipse
g.DrawPolygon(myPen, New PointF() {New PointF(1, 1), _
New PointF (20, 10), New PointF(5, 4), New PointF(100, 2), _
New PointF(200, 50), New PointF(39, 45)}) 'draw polygon
To fill a specific area, a Dim myBrush as New SolidBrush(Color.Red)
In fact, several different brushes exist in GDI+, as listed below:
The ones we uses in our project are If you want to show an image, an Dim myBitmap as New Bitmap(System.Environment.GetFolderPath _
(System.Environment.SpecialFolder.MyPictures))
Then you can load this image to the g.DrawImage(myBitmap, 1, 1)
Don't forget to free memory after using the g.Dispose()
myBitmap.Dispose()
Please refer to GDI+ references in MSDN for details. NomenclatureThe following image shows the components and nomenclature of a Cool Scrollbar:
Drawing Cool ScrollbarBefore I started, a list of the member variables and their meanings should be made clear. In the class 'height of the arrow bitmap
Private Const BitmapHeight As Byte = 12
'width of the arrow bitmap
Private Const BitmapWidth As Byte = 25
'max possible value of the scrollbar
Private m_nMaxValue As Long = 100
'min possible value of the scrollbar
Private m_nMinValue As Long = 0
'absolute value of the scrollbar
Private m_nValue As Long = 0
'value of the scrollbar
Private m_nRealValue As Long = 0
'left arrow image
Private m_imgLeftImage As Bitmap
'right arrow image
Private m_imgRightImage As Bitmap
'left value of Thumbleft
Private m_fThumbLeft As Single = 26.0F
'flag to indicate if mouse is hover the thumb
Private m_bMouseOnThumb As Boolean = False
' flag to indicate whether left mouse button pushed
Private m_bMouseDown As Boolean = False
'which button is clicked: Left-True; Right-False
Private m_bArrowClicked As Boolean
'''color properties
'Border color
Private m_cBorderColor As Color = Color.White
'right track begin color
Private m_cRightChannelBeginColor As Color = Color.Honeydew
'right track end color
Private m_cRightChannelEndColor As Color = Color.Gray
'left track begin color
Private m_cLeftChannelBeginColor As Color = Color.Green
'left track end color
Private m_cLeftChannelEndColor As Color = Color.White
'thumb's fill color(the left and right Half eclipse's color)
Private m_cThumbFillColor As Color = Color.Blue
'center color of the thumb
Private m_cThumbRectColor As Color = Color.LightYellow
'''end color properties
'layout, horizontal or vertical
Private m_BarLayout As BarLayout = BarLayout.Horizontal
Step 1: draw arrows and track borderAs it might be a little complicated to draw arrow buttons and the user might want to customize the arrow picture, I use bitmaps as arrow picture and directly draw them onto each side of the control. Initially, I restricted the control's height to Dim gTrack As Graphics = Me.CreateGraphics
'draw track border
gTrack.DrawRectangle(New Pen(m_cBorderColor), _
0, 0, Me.Width - 1, Me.Height - 1)
'draw arrow to each side of the track
gTrack.DrawImage(m_imgLeftImage, 1, 1)
gTrack.DrawImage(m_imgRightImage, Me.Width - BitmapWidth - 1, 1)
Step 2: draw channelsFor both the channels, I use the Dim rightBrush As New Drawing2D.LinearGradientBrush(ClientRectangle,_
m_cRightChannelBeginColor, m_cRightChannelEndColor, _
Drawing2D.LinearGradientMode.Vertical)
Dim leftBrush As New Drawing2D.LinearGradientBrush(ClientRectangle, _
m_cLeftChannelBeginColor,_ m_cLeftChannelEndColor, _
Drawing2D.LinearGradientMode.BackwardDiagonal)
There are two points that must be kept in mind when drawing the channels:
Consequently, the rectangle area of each channel is defined as below: Dim fTmpRightChannelWidth As Single
Dim LeftChannel As Rectangle = _
New Rectangle(BitmapWidth + 1, 2, 0, BitmapHeight - 2), _
RightChannel As RectangleF
LeftChannel.Width = CalValue() - BitmapWidth + BitmapHeight / 2
If LeftChannel.Width <= 0 Then
LeftChannel.Width = BitmapHeight / 2
fTmpRightChannelWidth = Me.Width - BitmapWidth * 2 - 2
RightChannel = New RectangleF(BitmapWidth + 1, 1, _
fTmpRightChannelWidth, BitmapHeight)'The function CalValue() returns the current
' thumb's left edge's x-coordinate.
Private Function CalValue() As Single
Return BitmapWidth + 1 + (Me.Width - BitmapWidth * 3 - 2) _
* m_nValue / (m_nMaxValue - m_nMinValue)
End Function
Next, fill in the corresponding area using the brush defined above: gTrack.FillRectangle(rightBrush, RightChannel)
gTrack.FillRectangle(leftBrush, LeftChannel)
gTrack.DrawRectangle(New Pen(Color.Gray), LeftChannel.X, LeftChannel.Y, _
LeftChannel.Width, LeftChannel.Height - 1)
Step 3: Draw thumbUntil very recently, I haven't figured out a good-looking style of the thumb, so the current result of the style of the thumb might look a bit ugly; however, the drawing process is almost the same. The size of the thumb is the same as that of the arrow. Before drawing the thumb, you must first calculate the position of the thumb. This is done by the function Dim gThumb As Graphics = Me.CreateGraphics
'pen to draw the edge of the area
Dim linePen As New Pen(Color.Gray, 1)
Dim fX(3) As Single
'initialize edge values--------------------------------------
fX(0) = CalValue()
If (m_BarLayout = BarLayout.Horizontal) Then
fX(1) = fX(0) + BitmapHeight / 2
fX(2) = fX(1) + (BitmapWidth - BitmapHeight) / 2 '7
Else
fX(1) = fX(0) + BitmapWidth / 2
fX(2) = fX(1) + (BitmapHeight - BitmapWidth) / 2 '7
End If
'''----------------------------------------------------------
'define path and brushes
Dim rectPath As New Drawing2D.GraphicsPath
'path that will constitute the thumb area
If (m_BarLayout = BarLayout.Horizontal) Then
Dim rect2Fill As New RectangleF(fX(1), 1.0F, _
BitmapWidth - BitmapHeight, BitmapHeight)
'center rectangle area of the thumb
Dim rect2Fill As New RectangleF(fX(1), 1.0F, fX(2)_
- fX(0), BitmapHeight)
'center rectangle area of the thumb
rectPath.AddArc(fX(0), 0.3F, BitmapHeight, _
BitmapHeight, 90, 180) 'left pie
rectPath.AddRectangle(rect2Fill) 'center
rectPath.AddArc(fX(2), 0.3F, BitmapHeight, _
BitmapHeight, 90, -180) 'right pie
Else
Dim rect2Fill As New RectangleF(1.0F, fX(2), _
BitmapWidth, 2 * fX(1) - fX(0) - fX(2))
rectPath.AddArc(0.3F, 2 * fX(1) - fX(0), _
BitmapWidth, BitmapWidth, 0, 180) 'upper pie
rectPath.AddRectangle(rect2Fill) 'center
rectPath.AddArc(0.3F, fX(2) - fX(1) + fX(0), _
BitmapWidth, BitmapWidth, -180, 180) 'down pie
End If
Dim rectBrush As New Drawing2D.PathGradientBrush(rectPath)
rectBrush.CenterColor = m_cThumbRectColor
Dim rectColors As Color() = {m_cThumbFillColor, _
m_cThumbFillColor, m_cThumbFillColor, m_cThumbFillColor}
rectBrush.SurroundColors = rectColors
'draw the thumb
If (m_BarLayout = BarLayout.Horizontal) Then
gThumb.DrawArc(linePen, fX(0), 1.0F, _
BitmapHeight, BitmapHeight - 1, 90, 180)
gThumb.DrawArc(linePen, fX(2), 1.0F, _
BitmapHeight, BitmapHeight - 1, -90, 180)
Else
gThumb.DrawArc(linePen, 1.0F, 2 * fX(1) - fX(0), _
BitmapWidth, BitmapWidth - 1, 0, 180)
gThumb.DrawArc(linePen, 1.0F, fX(2) - fX(1) + fX(0), _
BitmapWidth, BitmapWidth - 1, 0, -180)
End If
gThumb.FillPath(rectBrush, rectPath)
Step 4: Add them togetherJust do the jobs described in the first three steps every time the value of the scrollbar changes and the bar will appear like the one described at the beginning of the article. Turn our scrollbar into a real Cool ScrollbarAdd overridesUp to now, our scrollbar has its “face”, but is nothing more than a picture. In order to be a real scrollbar, first it should be able to be scrolled. With the help of bunches of override subs and functions inherited from the As described in the Nomenclature section, the scrollbar has three areas: the channels, the thumb and the arrow buttons. Thus when the mouse is clicked or moved in these areas, there should be different events. For more details, please refer to my code, this section is written as clear as possible so that you can understand it well. Add propertiesAs for the properties, I currently enable the following: Behavior
Appearance
The way of enabling these properties is the same as the ordinary one, just remember to redraw the track every time the property value changes. This is what they look like in a Windows application property window:
You can modify them as you like. Add eventCurrently the Cool Scrollbar only needs one event to function correctly: Future enhancements
AcknowledgementThanks to Hans Dietrich for the idea of creating the HistoryVersion 0.1 - October 12, 2004
Version 0.2 - April 25, 2005
| ||||||||||||||||||||||||||||||||