Scroll Bars
With many VB controls, such as the listbox, multi-line textbox, treeview, listview and so on, vertical and/or horizontal scroll bars automatically appear on these controls and function as needed with little or no extra programming required. However, there may be times when you need to apply your own scroll bar functionality to an application. For such occasions, the Veritcal Scroll Bar (VScrollBar) and Horizontal Scroll Bar (HScrollBar) controls are available in the VB toolbox.
A scroll bar control consists of a bar with arrows at each end. Between the arrows is a square scroll box (also called a "thumb"). The scroll box slides along the scroll shaft between the two arrows.
Scroll bars are most frequently used to let the user move the contents of an area to bring into view a portion temporarily outside the visible region. A scroll bar control can also be used to specify a value within a prescribed range. By moving the scroll box between the two arrows, the user can specify a value in an intuitive, visual manner.
The scroll box on the scroll shaft indicates the current value specified by the bar. When the user clicks the arrow at either end of the scroll bar, the scroll box moves and incremental unit toward that arrow. When the user clicks the scroll shaft somewhere between an arrow and the scroll box, it moves a larger incremental unit toward the click position. In addition, the user can directly drag the scroll box along the shaft with the mouse.
When using a scroll bar control, you must determine the range of values that the control can designate. A scroll bar control can represent integer values in the range -32768 through +32767. You use the Minimum property to specify the low end of your range and the Maximum property to specify the high end of your range. The Value property specifies the current value represented by the scroll bar. The position of the scroll box along the scroll shaft graphically reflects where Value lies between Minimum and Maximum. If the user moves the scroll box, the Value property adjusts appropriately. If you modify the Vaue in program code, VB moves the scroll box to the appropriate position. The SmallChange property indicates how much the Value changes when the user clicks one of the arrows at the end of the scroll bar. The LargeChange indicates how much Value changes when the user clicks the scroll shaft between the scroll box and one of the arrows.
A Very Simple Example
In the very simple example that follows, a label is used to display the value of the scroll bar as it changes by the user clicking the arrows or moving the scroll box. To build the example, start a new project, place a label control and a vertical scroll bar (VScrollBar) control on the form and set their properties as indicated in the callouts below:
This sample program requires only a single line of code in the vertical scroll bar's ValueChanged event:
Private Sub vsbTest_ValueChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles vsbTest.ValueChanged
lblTest.Text = CStr(vsbTest.Value)
End Sub
When you run the program, you will see that the value displayed in the label will vary as you click on the scroll bar's arrows or move its scroll box.
Note: When a scroll bar has focus, its scroll box will blink. Some people find this annoying. In most cases, you can prevent this blinking by setting the TabStop property of the scroll bar to False (the default is True). An exception to this is when the scroll bar is the only control on the form that can receive focus – such is the case in this example.
Download the VB project code for the example above here.
A More Advanced Example
In this example, a "manual" data grid has been created. With the various advanced controls that can be used with VB, such as the DataGridView, ListView, third-party girds, etc., you would most likely not have the need to build something like this – but you never know. This is a "low-tech" grid built with basic toolbox controls: a handful of labels, some images, a vertical scroll bar, and a horizontal scroll bar.
The application displays data about the twelve zodiac signs (Aires, Taurus, Gemini, Cancer, Leo, Virgo, Libra, Scorpio, Sagittarius, Capricorn, Aquarius, and Pisces). Note that there are only seven "rows" on the form, so vertical scrolling is necessary to view the twelve zodiac "records".
Associated with each sign are 15 fields: sign description, house, gemstone, New Age stone, colors, opposite sign, least compatible signs, ruling planet, element, anatomy, flower, most compatible signs, Tarot card, positive characteristics, and negative characteristics. Note that there are only four "columns" on the form, so horizontal scrolling is necessary to view the 15 fields.
When the program first runs, the form looks like this:
Screen shot after scrolling down (vertically):
Screen shot after scrolling across (horizontally):
Building the Zodiac Example
The design-time form is shown on the right. To show the images for the signs, on the far left-hand side of the screen we have a set of seven PictureBoxes named picSign0 thru picSign6. Moving to the right, we have four columns of seven labels each for the data, named lblCell1_0 thru lblCell1_6, lblCell2_0 thru lblCell2_6, lblCell13_0 thru lblCell3_6, and lblCell14_0 thru lblCell4_6, respectively. The column headings going across are named lblColHdrSign (this one has the text "Sign" and does not vary, because we keep the "Sign" column frozen), followed by lblColHdr1 thru lblColHdr3. The technique to simulate control arrays is used for all sets of controls just described.
On the far right-hand side of the screen, we have a vertical scroll bar named vsbZGrid to scroll the "records" down; and on the bottom below the columns of labels we have a horizontal scroll bar named hsvbZGrid to scroll the "fields" across. |
|
The images for the signs are stored in an ImageList control named imlSigns. |
|
The images are set of icons that were loaded ImageList control via its "Images Collection Editor" dialog. |
|
A discussion of the code follows.
General Declarations Section
The General Declarations section declares a Structure named ZodiacRecord, based on the data in the input file. An array variable, maudtZodiacRec, is then defined as that structure type. It is expected that exactly 12 records will be read from the input file, so the array is declared with a fixed number (12) of elements (specified as 0 to 11). Two form-level variables (mintRowStart and mintColStart) are also declared. These variables specify the row and column starting points for transferring data from the structure array to the controls on the form.
Private Structure ZodiacRecord
Dim SignDesc As String
Dim House As String
Dim Gemstone As String
Dim NewAgeStone As String
Dim Colors As String
Dim OppositeSign As String
Dim LeastCompat As String
Dim RulingPlanet As String
Dim Element As String
Dim Anatomy As String
Dim Flower As String
Dim MostCompat As String
Dim TarotCard As String
Dim PositiveChars As String
Dim NegativeChars As String
End Structure
Private maudtZodiacRec(0 To 11) As ZodiacRecord
Private mintRowStart As Integer
Private mintColStart As Integer
Form Load Event
The Load event for the form opens the "NewZodiac.txt" input file and loads it into the structure record array. The mintRowStart and mintColStart variables are initialized to 1 and 2 respectively. The SetColumnHeaders and DisplayZodiacData Subs are then called to provide the initial display of the data.
Private Sub SetColumnHeaders()
Select Case mintColStart
Case 2
lblColHdr1.Text = "House"
lblColHdr2.Text = "Gemstone"
lblColHdr3.Text = "New Age Stone"
Case 3
lblColHdr1.Text = "Gemstone"
lblColHdr2.Text = "New Age Stone"
lblColHdr3.Text = "Colors"
Case 4
lblColHdr1.Text = "New Age Stone"
lblColHdr2.Text = "Colors"
lblColHdr3.Text = "Opposite Sign"
Case 5
lblColHdr1.Text = "Colors"
lblColHdr2.Text = "Opposite Sign"
lblColHdr3.Text = "Least Compatible Signs"
Case 6
lblColHdr1.Text = "Opposite Sign"
lblColHdr2.Text = "Least Compatible Signs"
lblColHdr3.Text = "Ruling Planet"
Case 7
lblColHdr1.Text = "Least Compatible Signs"
lblColHdr2.Text = "Ruling Planet"
lblColHdr3.Text = "Element"
Case 8
lblColHdr1.Text = "Ruling Planet"
lblColHdr2.Text = "Element"
lblColHdr3.Text = "Anatomy"
Case 9
lblColHdr1.Text = "Element"
lblColHdr2.Text = "Anatomy"
lblColHdr3.Text = "Flower"
Case 10
lblColHdr1.Text = "Anatomy"
lblColHdr2.Text = "Flower"
lblColHdr3.Text = "Most Compatible Signs"
Case 11
lblColHdr1.Text = "Flower"
lblColHdr2.Text = "Most Compatible Signs"
lblColHdr3.Text = "Tarot Card"
Case 12
lblColHdr1.Text = "Most Compatible Signs"
lblColHdr2.Text = "Tarot Card"
lblColHdr3.Text = "Positive Characteristics"
Case 13
lblColHdr1.Text = "Tarot Card"
lblColHdr2.Text = "Positive Characteristics"
lblColHdr3.Text = "Negative Characteristics"
End Select
End Sub
SetColumnHeaders Sub
This Sub sets the column headings based on the current value of mintColStart (which will be a number from 2 to 13, the min/max range of the horizontal scroll bar). A set of headings from "House" thru "New Age Stone" (fields 2 thru 4) to "Tarot Card" thru "Negative Characteristics" (fields 13 thru 15) will be assigned to elements 1 thru 3 of the lblColHdr control array. Note that only elements 1, 2, and 3 of the lblColHdr control array are changed. Element 0 is reserved for "Sign", which remains frozen as the other columns scroll to the right or left.
Private Sub SetColumnHeaders()
Select Case mintColStart
Case 2
lblColHdr1.Text = "House"
lblColHdr2.Text = "Gemstone"
lblColHdr3.Text = "New Age Stone"
Case 3
lblColHdr1.Text = "Gemstone"
lblColHdr2.Text = "New Age Stone"
lblColHdr3.Text = "Colors"
Case 4
lblColHdr1.Text = "New Age Stone"
lblColHdr2.Text = "Colors"
lblColHdr3.Text = "Opposite Sign"
Case 5
lblColHdr1.Text = "Colors"
lblColHdr2.Text = "Opposite Sign"
lblColHdr3.Text = "Least Compatible Signs"
Case 6
lblColHdr1.Text = "Opposite Sign"
lblColHdr2.Text = "Least Compatible Signs"
lblColHdr3.Text = "Ruling Planet"
Case 7
lblColHdr1.Text = "Least Compatible Signs"
lblColHdr2.Text = "Ruling Planet"
lblColHdr3.Text = "Element"
Case 8
lblColHdr1.Text = "Ruling Planet"
lblColHdr2.Text = "Element"
lblColHdr3.Text = "Anatomy"
Case 9
lblColHdr1.Text = "Element"
lblColHdr2.Text = "Anatomy"
lblColHdr3.Text = "Flower"
Case 10
lblColHdr1.Text = "Anatomy"
lblColHdr2.Text = "Flower"
lblColHdr3.Text = "Most Compatible Signs"
Case 11
lblColHdr1.Text = "Flower"
lblColHdr2.Text = "Most Compatible Signs"
lblColHdr3.Text = "Tarot Card"
Case 12
lblColHdr1.Text = "Most Compatible Signs"
lblColHdr2.Text = "Tarot Card"
lblColHdr3.Text = "Positive Characteristics"
Case 13
lblColHdr1.Text = "Tarot Card"
lblColHdr2.Text = "Positive Characteristics"
lblColHdr3.Text = "Negative Characteristics"
End Select
End Sub
DisplayZodiacData Sub
This Sub populates the lblCell1, lblCell2, lblCell3, and lblCell4 control arrays based on the current values of mintRowStart and mintColStart. The mintRowStart variable will contain a value between 1 and 6, the min/max range of the vertical scroll bar. This means that data for records 1 thru 7, 2 thru 8, 3 thru 9, 4 thru 10, 5 thru 11, or 6 thru 12 will be loaded into elements 0 thru 6 of the lblCellx arrays. Similarly, the value of mintColStart will be a number from 2 to 13, the min/max range of the horizontal scroll bar. This means that the set of fields from "House" thru "NewAgeStone" (fields 2 thru 4) to "TarotCard" thru "NegativeChars" (fields 13 thru 15) will be loaded into the appropriate element of lblCell2, lblCell3, and lblCell4.
Private Sub DisplayZodiacData()
Dim intX As Integer
Dim intRecordIndex As Integer
Dim picSign As PictureBox
Dim lblCell1 As Label
Dim lblCell2 As Label
Dim lblCell3 As Label
Dim lblCell4 As Label
intRecordIndex = mintRowStart - 1
For intX = 0 To 6
picSign = DirectCast(GetControlByName(Me, "picSign" & intX), PictureBox)
lblCell1 = DirectCast(GetControlByName(Me, "lblCell1_" & intX), Label)
lblCell2 = DirectCast(GetControlByName(Me, "lblCell2_" & intX), Label)
lblCell3 = DirectCast(GetControlByName(Me, "lblCell3_" & intX), Label)
lblCell4 = DirectCast(GetControlByName(Me, "lblCell4_" & intX), Label)
With maudtZodiacRec(intRecordIndex)
lblCell1.Text = .SignDesc
picSign.Image = imlSigns.Images(intRecordIndex)
Select Case mintColStart
Case 2
lblCell2.Text = .House
lblCell3.Text = .Gemstone
lblCell4.Text = .NewAgeStone
Case 3
lblCell2.Text = .Gemstone
lblCell3.Text = .NewAgeStone
lblCell4.Text = .Colors
Case 4
lblCell2.Text = .NewAgeStone
lblCell3.Text = .Colors
lblCell4.Text = .OppositeSign
Case 5
lblCell2.Text = .Colors
lblCell3.Text = .OppositeSign
lblCell4.Text = .LeastCompat
Case 6
lblCell2.Text = .OppositeSign
lblCell3.Text = .LeastCompat
lblCell4.Text = .RulingPlanet
Case 7
lblCell2.Text = .LeastCompat
lblCell3.Text = .RulingPlanet
lblCell4.Text = .Element
Case 8
lblCell2.Text = .RulingPlanet
lblCell3.Text = .Element
lblCell4.Text = .Anatomy
Case 9
lblCell2.Text = .Element
lblCell3.Text = .Anatomy
lblCell4.Text = .Flower
Case 10
lblCell2.Text = .Anatomy
lblCell3.Text = .Flower
lblCell4.Text = .MostCompat
Case 11
lblCell2.Text = .Flower
lblCell3.Text = .MostCompat
lblCell4.Text = .TarotCard
Case 12
lblCell2.Text = .MostCompat
lblCell3.Text = .TarotCard
lblCell4.Text = .PositiveChars
Case 13
lblCell2.Text = .TarotCard
lblCell3.Text = .PositiveChars
lblCell4.Text = .NegativeChars
End Select
End With
intRecordIndex = intRecordIndex + 1
Next
End Sub
GetControlByName Function
Helper function to implement "control array" functionality.
Private Function GetControlByName(ByVal pobjParent As Control, _
ByVal pstrCtlName As String) _
As Control
Dim objCtl As Control
For Each objCtl In pobjParent.Controls
If objCtl.Name = pstrCtlName Then
Return (objCtl)
End If
Next
' if control is not found
Return Nothing
End Function
hsbZGrid_ValueChanged Event
This event will occur when the user changes the value of the horizontal scroll bar by clicking on its arrows or dragging its scroll box. The value will be set to a number between 2 and 13, and this is assigned to mintColStart. The SetColumnHeaders and DisplayZodiacData Subs are then called to update the display based on the new value of the horizontal scroll bar.
Private Sub hsbZGrid_ValueChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles hsbZGrid.ValueChanged
mintColStart = hsbZGrid.Value
SetColumnHeaders()
DisplayZodiacData()
End Sub
vsbZGrid_ValueChanged Event
This event will occur when the user changes the value of the vertical scroll bar by clicking on its arrows or dragging its scroll box. The value will be set to a number between 1 and 6, and this is assigned to mintRowStart. The DisplayZodiacData Sub is then called to update the display based on the new value of the vertical scroll bar.
Private Sub vsbZGrid_ValueChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles vsbZGrid.ValueChanged
mintRowStart = vsbZGrid.Value
DisplayZodiacData()
End Sub
btnExit_Click Event
Ends the program.
Private Sub btnExit_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnExit.Click
Me.Close()
End Sub
Download the VB project code for the example above here.