|
|
Title | Make a scrolled window that the user can drag with the mouse (as Adobe Acrobat Reader does) |
Description | |
Keywords | scrolled window, drag, drag window, Adobe Acrobat Reader, Acrobat Reader, Acrobat |
Categories | Controls, Graphics |
|
|
Create a horizontal scroll bar named VBar, a vertical scroll bar named HBar, and a PictureBox
named picOuter. Inside picOuter, create another PictureBox named picInner. The program scrolls the
picture by moving picInner inside picOuter.
Set picInner.AutoSize = True,
picInner.BorderStyle = None, and picOuter.BorderStyle = Fixed Single.
The most interesting part of the program is subroutine ArrangeScrollBars. It begins by determining how much room
the picture needs and how much room is available. It compares the available width with the needed width
to see if the horizontal scroll bar is needed.
Next the routine compares the available height with the needed height to see if the vertical scroll bar
is necessary. If it is, that scroll bar takes up some of the available width so the routine checks again
to see if the horizontal scroll bar is needed.
The subroutine then positions picOuter, and either hides or positions the scroll bars as appropriate.
It sets the scroll bars' Max property to the maximum amount it will need to move the picture during scrolling.
It sets LargeChange to the area visible. If the user clicks beside the scroll bar thumb, the picture
moves by its visible width or height.
|
|
' Arrange the scroll bars.
Private Sub ArrangeScrollBars()
Dim have_wid As Single
Dim have_hgt As Single
Dim need_wid As Single
Dim need_hgt As Single
Dim need_hbar As Boolean
Dim need_vbar As Boolean
' Don't bother if we're minimized.
If WindowState = vbMinimized Then Exit Sub
' See how much room we need and
' how much room we have.
need_wid = picInner.Width + (picOuter.Width - _
picOuter.ScaleWidth)
need_hgt = picInner.Height + (picOuter.Height - _
picOuter.ScaleHeight)
have_wid = ScaleWidth
have_hgt = ScaleHeight
' See which scroll bars we need.
need_hbar = (need_wid > have_wid)
If need_hbar Then have_hgt = have_hgt - HBar.Height
need_vbar = (need_hgt > have_hgt)
If need_vbar Then
' This takes away a little width so we
' might need the horizontal scroll bar now.
have_wid = have_wid - VBar.Width
If Not need_hbar Then
need_hbar = (need_wid > have_wid)
If need_hbar Then have_hgt = have_hgt - _
HBar.Height
End If
End If
' Position the outer PictureBox leaving room
' for the scroll bars.
picOuter.Move 0, 0, have_wid, have_hgt
' Position or hide the scroll bars.
If need_hbar Then
HBar.Move 0, have_hgt, have_wid
HBar.Min = 0
HBar.Max = picOuter.ScaleWidth - picInner.Width
HBar.LargeChange = picOuter.ScaleWidth
HBar.SmallChange = picOuter.ScaleWidth / 5
HBar.Visible = True
Else
HBar.Visible = False
End If
If need_vbar Then
VBar.Move have_wid, 0, VBar.Width, have_hgt
VBar.Min = 0
VBar.Max = picOuter.ScaleHeight - picInner.Height
VBar.LargeChange = picOuter.ScaleHeight
VBar.SmallChange = picOuter.ScaleHeight / 5
VBar.Visible = True
Else
VBar.Visible = False
End If
End Sub
|
|
After this setup, the scrolling is easy. The scroll bars use their values to move picInner inside picOuter.
|
|
Private Sub HBar_Change()
picInner.Left = HBar.Value
End Sub
Private Sub HBar_Scroll()
picInner.Left = HBar.Value
End Sub
Private Sub VBar_Change()
picInner.Top = VBar.Value
End Sub
Private Sub VBar_Scroll()
picInner.Top = VBar.Value
End Sub
|
|
To allow the user to drag the image, the picInner control tracks mouse events. The MouseDown event sets m_Dragging = True to indicate that a drag is in progress. It also saves the mouse's current position.
The MouseMove event handler determines how far the mouse has been dragged horizontally and vertically, and updates the scroll bar values appropriately. The scroll bars adjust the image's position.
The MouseUp event handler sets m_Dragging = False to indicate that a drag is no longer in progress.
|
|
Private m_Dragging As Boolean
Private m_X As Single
Private m_Y As Single
Private Sub picInner_MouseDown(Button As Integer, Shift As _
Integer, X As Single, Y As Single)
m_Dragging = True
m_X = X
m_Y = Y
End Sub
Private Sub picInner_MouseMove(Button As Integer, Shift As _
Integer, X As Single, Y As Single)
Dim new_hbar As Single
Dim new_vbar As Single
If Not m_Dragging Then Exit Sub
new_hbar = HBar.Value + (X - m_X)
If new_hbar < HBar.Max Then new_hbar = HBar.Max
If new_hbar > HBar.Min Then new_hbar = HBar.Min
HBar.Value = new_hbar
new_vbar = VBar.Value + (Y - m_Y)
If new_vbar < VBar.Max Then new_vbar = VBar.Max
If new_vbar > VBar.Min Then new_vbar = VBar.Min
VBar.Value = new_vbar
End Sub
Private Sub picInner_MouseUp(Button As Integer, Shift As _
Integer, X As Single, Y As Single)
m_Dragging = False
End Sub
|
|
Note that you cannot store an arbitrarily large image in picInner. In that case, you will need to display
only the piece of the scrolled area that should be visible. It is also more efficient to draw that area
for some pictures such as maps that are more easily drawn than stored in a picture.
For more information on this type of scrolling and other image display issues, see my book
Visual Basic Graphics Programming.
|
|
|
|
|
|