Scroll Bars
With many VB controls, such as the listbox, multi-line textbox, treeview, listview, flex grid, 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 and Horizontal Scroll Bar 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 Min property to specify the low end of your range and the Max 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 Min and Max. 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 Change event:
Private Sub vsbCount_Change()
lblCount.Caption = vsbCount.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 MS-FlexGrid, 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
To build the Zodiac example, place the controls on the form and set their properties as shown below:
The Zodiac images at the bottom of the form serve as the image repository for the images displayed to the left of each sign row (in the imgSign array). These images form a control array named imgSourceSign, indexed 0 to 11. The Visible property for these images should be set to False. These images are .ico files and are included in the download. They were obtained from this website: http://virtualgraphicsworld.freeservers.com/zodiac.htm. The Picture property for the imgSourceSign array images should be set as follows:
Index |
Picture |
0 |
aires.ico |
1 |
taurus.ico |
2 |
gemini.ico |
3 |
cancer.ico |
4 |
leo.ico |
5 |
virgo.ico |
6 |
libra.ico |
7 |
scorpio.ico |
8 |
sagittarius.ico |
9 |
capricorn.ico |
10 |
aquarius.ico |
11 |
pisces.ico |
The program reads in a comma-delimited text file named "NewZodiac.txt". The data for the file is based on the information found on the following website: http://www.extonbiz.com/yoursign.html.
General Declarations Section
The General Declarations section declares a Type record structure based on the data in the input file. A UDT array variable is then defined as that 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. Two form-level variables (mintRowStart and mintColStart) are also declared. These variables specify the row and column starting points for transferring data from the UDT array to the control arrays on the form.
Option Explicit
Private Type ZodiacRecord
SignDesc As String
House As String
Gemstone As String
NewAgeStone As String
Colors As String
OppositeSign As String
LeastCompat As String
RulingPlanet As String
Element As String
Anatomy As String
Flower As String
MostCompat As String
TarotCard As String
PositiveChars As String
NegativeChars As String
End Type
Private maudtZodiacRec(1 To 12) As ZodiacRecord
Private mintRowStart As Integer
Private mintColStart As Integer
Form_Load Event
The Form_Load event opens the "NewZodiac.txt" input file and loads it into the UDT record array. As the file is being read in, if the record count exceeds 12, an error message will be displayed and the program will end. Similarly, after the file has been read in, if there were fewer than 12 records loaded, an error message will be displayed and the program will end. 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 Form_Load()
'----------------------------------------------------------------------------
Dim intZFileNbr As Integer
Dim strFileName As String
Dim intSignX As Integer
intZFileNbr = FreeFile
strFileName = App.Path & IIf(Right$(App.Path, 1) = "\", "", "\") _
& "NewZodiac.txt"
Open strFileName For Input As #intZFileNbr
intSignX = 0
Do Until EOF(intZFileNbr)
intSignX = intSignX + 1
If intSignX > 12 Then
MsgBox "More than 12 zodiac records are present in the input file. " _
& "Please check the data and try again.", _
vbCritical, _
"Too Many Records"
End
End If
With maudtZodiacRec(intSignX)
Input #intZFileNbr, _
.SignDesc, _
.House, _
.Gemstone, _
.NewAgeStone, _
.Colors, _
.OppositeSign, _
.LeastCompat, _
.RulingPlanet, _
.Element, _
.Anatomy, _
.Flower, _
.MostCompat, _
.TarotCard, _
.PositiveChars, _
.NegativeChars
End With
Loop
Close #intZFileNbr
If intSignX < 12 Then
MsgBox "Fewer than 12 zodiac records are present in the input file. " _
& "Please check the data and try again.", _
vbCritical, _
"Too Few Records"
End
End If
mintRowStart = 1
mintColStart = 2
SetColumnHeaders
DisplayZodiacData
End Sub
hsbZGrid_Change 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_Change()
'----------------------------------------------------------------------------
mintColStart = hsbZGrid.Value
SetColumnHeaders
DisplayZodiacData
End Sub
vsbZGrid_Change 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_Change()
'----------------------------------------------------------------------------
mintRowStart = vsbZGrid.Value
DisplayZodiacData
End Sub
cmdExit_Click Event
Ends the program.
'----------------------------------------------------------------------------
Private Sub cmdExit_Click()
'----------------------------------------------------------------------------
End
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
lblColHdr(1).Caption = "House"
lblColHdr(2).Caption = "Gemstone"
lblColHdr(3).Caption = "New Age Stone"
Case 3
lblColHdr(1).Caption = "Gemstone"
lblColHdr(2).Caption = "New Age Stone"
lblColHdr(3).Caption = "Colors"
Case 4
lblColHdr(1).Caption = "New Age Stone"
lblColHdr(2).Caption = "Colors"
lblColHdr(3).Caption = "Opposite Sign"
Case 5
lblColHdr(1).Caption = "Colors"
lblColHdr(2).Caption = "Opposite Sign"
lblColHdr(3).Caption = "Least Compatible Signs"
Case 6
lblColHdr(1).Caption = "Opposite Sign"
lblColHdr(2).Caption = "Least Compatible Signs"
lblColHdr(3).Caption = "Ruling Planet"
Case 7
lblColHdr(1).Caption = "Least Compatible Signs"
lblColHdr(2).Caption = "Ruling Planet"
lblColHdr(3).Caption = "Element"
Case 8
lblColHdr(1).Caption = "Ruling Planet"
lblColHdr(2).Caption = "Element"
lblColHdr(3).Caption = "Anatomy"
Case 9
lblColHdr(1).Caption = "Element"
lblColHdr(2).Caption = "Anatomy"
lblColHdr(3).Caption = "Flower"
Case 10
lblColHdr(1).Caption = "Anatomy"
lblColHdr(2).Caption = "Flower"
lblColHdr(3).Caption = "Most Compatible Signs"
Case 11
lblColHdr(1).Caption = "Flower"
lblColHdr(2).Caption = "Most Compatible Signs"
lblColHdr(3).Caption = "Tarot Card"
Case 12
lblColHdr(1).Caption = "Most Compatible Signs"
lblColHdr(2).Caption = "Tarot Card"
lblColHdr(3).Caption = "Positive Characteristics"
Case 13
lblColHdr(1).Caption = "Tarot Card"
lblColHdr(2).Caption = "Positive Characteristics"
lblColHdr(3).Caption = "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
intRecordIndex = mintRowStart
For intX = 0 To 6
With maudtZodiacRec(intRecordIndex)
lblCell1(intX).Caption = .SignDesc
imgSign(intX).Picture = imgSourceSign(intRecordIndex - 1).Picture
Select Case mintColStart
Case 2
lblCell2(intX).Caption = .House
lblCell3(intX).Caption = .Gemstone
lblCell4(intX).Caption = .NewAgeStone
Case 3
lblCell2(intX).Caption = .Gemstone
lblCell3(intX).Caption = .NewAgeStone
lblCell4(intX).Caption = .Colors
Case 4
lblCell2(intX).Caption = .NewAgeStone
lblCell3(intX).Caption = .Colors
lblCell4(intX).Caption = .OppositeSign
Case 5
lblCell2(intX).Caption = .Colors
lblCell3(intX).Caption = .OppositeSign
lblCell4(intX).Caption = .LeastCompat
Case 6
lblCell2(intX).Caption = .OppositeSign
lblCell3(intX).Caption = .LeastCompat
lblCell4(intX).Caption = .RulingPlanet
Case 7
lblCell2(intX).Caption = .LeastCompat
lblCell3(intX).Caption = .RulingPlanet
lblCell4(intX).Caption = .Element
Case 8
lblCell2(intX).Caption = .RulingPlanet
lblCell3(intX).Caption = .Element
lblCell4(intX).Caption = .Anatomy
Case 9
lblCell2(intX).Caption = .Element
lblCell3(intX).Caption = .Anatomy
lblCell4(intX).Caption = .Flower
Case 10
lblCell2(intX).Caption = .Anatomy
lblCell3(intX).Caption = .Flower
lblCell4(intX).Caption = .MostCompat
Case 11
lblCell2(intX).Caption = .Flower
lblCell3(intX).Caption = .MostCompat
lblCell4(intX).Caption = .TarotCard
Case 12
lblCell2(intX).Caption = .MostCompat
lblCell3(intX).Caption = .TarotCard
lblCell4(intX).Caption = .PositiveChars
Case 13
lblCell2(intX).Caption = .TarotCard
lblCell3(intX).Caption = .PositiveChars
lblCell4(intX).Caption = .NegativeChars
End Select
End With
intRecordIndex = intRecordIndex + 1
Next
End Sub
Download the VB project code for the example above here.