Adit Cookbook Pages

Home
Cookbook
A Question of Sorts
Bits & Bobs
Error Event Handling
SQL for Access
Grid Copy
Temporary Files
Delete or Kill
Credit Card
Virtual Arrays
Binary Chop
Numbers
VB to HTML
Viewport
Printing Grids

Scrollable Viewport

Scrollable ViewPort

This is a simple demonstration of a facility to display a larger "screen" area than will fit on the user’s PC screen. It is very useful for things like displaying A4 pages full sized (or any other reasonably sized working area  that can not be accommodated within the bounds of a normal display screen).

I have come across some experienced VB programmers who have never given  this sort of thing any serious thought and have held the opinion that it was beyond the  reach of Visual Basic. I have also met beginners who thought it was a "no  brainer". Just goes to show – there is so much to learn and programming covers such a wide range of applications.

To try this out, create a new project and follow the instructions below  or download the code by clicking here and follow the text and code in parallel. First create a new project and add a picture box  control to the form. I have re-named this control CONTAINER and it will act as a container for the scrollable region of the form. For more on Containers please see below.

Now add another picture box to the form and rename it VIEWER. Set both the AutoRedraw and Autosize properties to True. Then, right click this new picture box and the select "Cut" from the edit menu. Now select the CONTAINER picture box  control and then right click this and take the "Paste" option from the menu. This will place the VIEWER picture box inside the CONTAINER picture box, which now acts as a VB "container".

Then stick a horizontal and a vertical scroll bar control on the form  (anywhere will do) and use the Project Menu/Components menu option to add the Microsoft Common Dialogue Control to the project. Add one of these to the form so that we can demonstrate one of the potential uses of our scrollable viewport - displaying large  pictures. Now use the Menu Editor function to add a File Menu with an "Open" option (the downloadable code includes a "Close" option as well and they are  serviced by a routine named mnuFileOption).

You will have noticed that at this stage the form is not laid out in any particular way - all this is managed by the Form_Resize() subroutine thus:

Private Sub Form_Resize()
    If Me.WindowState = 1 Then
        Exit Sub
        ’
This ensures that the code below does not execute
        ’when the window is minimised - bound to generate errors
    End If
    VScroll1.Top = 0
    VScroll1.Left = Me.ScaleWidth - VScroll1.Width
    VScroll1.Height = Me.ScaleHeight - HScroll1.Height
    HScroll1.Top = Me.ScaleHeight - HScroll1.Height
    HScroll1.Left = 0
    HScroll1.Width = Me.ScaleWidth - VScroll1.Width
    Container.Top = 0
    Container.Left = 0  
’Move the container to the top left
    Container.Height = VScroll1.Height
    Container.Width = HScroll1.Width
    If PictureShown Then
        HScrollSet
        VScrollSet
    End If
    ’
OK what is all this ScaleWidth and ScaleHeight?
    ’You can do all sorts of interesting things by setting these
    ’values but for this purpose the ScaleHeight gives you the
    ’internal dimension of the form (or other object) excluding
    ’the heading, menus bars and borders. If you used the .Height
    ’property you would need to include calculations for all these.
End Sub

And the controls are initialised in the Form_Load() subroutine:

Private Sub Form_Load()
    Viewer.Enabled = False
    VScroll1.Enabled = False
    HScroll1.Enabled = False
    PictureShown = False
End Sub

Now let us get this demo to do something useful. 
Add some code to the mnuFileOption() sub:

Private Sub mnuFileOption_Click(Index As Integer)
    Select Case Index
        Case 0  ’
Open
            OpenImageFile
           
 ’We have always held the view that as little code
            ’as possible should sit under a "click event" and
            ’experience has not changed any minds
        Case 2  ’Close this program
            End
    End Select
End Sub
Private Sub OpenImageFile()
    On Error GoTo OpenImageErr
    CommonDialog1.CancelError = True
    CommonDialog1.DialogTitle = "Open Image File"
    CommonDialog1.Filter = "Image Files (*.bmp, *.jpg, etc)|*.wmf; *.emf; *.bmp; *.jpg; *.ico"
    CommonDialog1.Flags = cdlOFNFileMustExist
    CommonDialog1.ShowOpen
    Viewer.Picture = LoadPicture(CommonDialog1.FileName)
    PictureShown = True
    Viewer.Refresh
    DoEvents
    HScrollSet
    VScrollSet
    Exit Sub
OpenImageErr:
   
 ’No file opened
    Exit Sub
End Sub

 

And we also need some code under the Vscroll1 and Hscroll1 controls:

Private Sub HScroll1_Change()
    Viewer.Left = -(HScroll1.Value)
End Sub
Private Sub VScroll1_Change()
    Viewer.Top = -(VScroll1.Value)
End Sub

You will also need to add the following subs to complete the demo application:

Private Sub HScrollSet()
    If Viewer.Width > Container.Width Then
        HScroll1.Max = Viewer.Width - Container.Width
        HScroll1.Min = 0
        HScroll1.LargeChange = Int(HScroll1.Max / 10 + 0.5)
        HScroll1.SmallChange = Int(HScroll1.Max / 100 + 0.5)
        Viewer.Left = 0
        HScroll1.Value = 0
        HScroll1.Enabled = True
    Else
        HScroll1.Enabled = False
    End If
End Sub
Private Sub VScrollSet()
    If Viewer.Height > Container.Height Then
        VScroll1.Max = Viewer.Height - Container.Height
        VScroll1.Min = 0
        VScroll1.LargeChange = Int(VScroll1.Max / 10 + 0.5)
        VScroll1.SmallChange = Int(VScroll1.Max / 100 + 0.5)
        Viewer.Top = 0
        VScroll1.Value = 0
        VScroll1.Enabled = True
    Else
        VScroll1.Enabled = False
    End If
End Sub
 

Now run the program, select the File/Open menu option and open a big fat picture file. The Viewer Picture Box will re-size to accommodate the loaded picture. The Container will be constrained by the Form. If the Viewer Picture Box is larger that the  Container Picture Box then the scroll bars will be enabled and you can scroll the relative position of the Viewer to the container. The scroll bars will thus give you access to the  whole of the loaded picture file.

Containers.

A Window is the first container you will have met. It contains controls  and has a number of special characteristics of its own. [OK Windows purists I know controls are all windows of a sort but let’s keep things simple]. Other controls (such  as Picture Boxes and Frames) can also contain controls. These are known as containers.

Why use containers you may ask? Answers range from "simplifying the  enabling and positioning of individual controls" through "displaying or hiding  groups of controls" to “grouping Option Buttons". You might need to do all three on any given form. You can also contain a group of controls within a new ActiveX control  you are developing.

You can enable or make visible a whole group of controls by enabling or  making visible their container. If you write a tabbed dialogue or a "wizard" you  will probably want to hide and display groups of controls in sequence. If the groups are contained within another control then your code will only need to set the visibility of  the container controls in sequence to achieve your ends.

Any group of Option Buttons within any given container act as a single set irrespective of their names or other attributes. If you need to display more than one  group of option buttons on your screen at once then you must use different container controls to "group" them - the obvious choice being Frame Controls as you can  use the boundary line and (often) the "Caption" to identify the group or provide a context within your UI design. Any given frame can be re-positioned, and made  visible/invisible along with all the controls contained within it. This can be a very  effective way of transforming the layout of a form as the user selects or de-selects display options in your UI.

Using the "Resize" event to lay out your forms.

Often it is effective to use the VB GUI to lay out your forms to get the windows that you need. There are circumstances when all, or part, of your form is dependent upon run-time criteria or are constrained by the actual size of the form at run-time. In such circumstances it is often a good idea to use the Form_Resize event to  position the controls on the screen or to call some other routine to achieve the same effect. If you have to write a routine to position your controls then first of all give some consideration to the extremes - by this I mean what if your user is using a 640 by 480 pixel resolution (at one extreme) or something greater than 1024 by 768 (perhaps soon to seem rather small).

At the smallest extreme it may not be possible to show all of your window. You could test the resolution at start-up and then decline to run without the user re-setting his/her display or even consider placing all of your controls within a scrollable container (a picture box probably) and offering your window within a viewport  (as above). However you should be warned about an endemic NT bug associated with this  technique. If you place controls in a viewport and their initial position is outside the bounds of the PC display screen (rather than just the viewport) then they will not be  correctly rendered (drawn) when scrolled into view. There is evidence to suggest (i.e. some good programmers we know insist) that some video card driver writers have found a  solution to this problem but be warned it is likely that any given NT machine will let you down.

The other big tip is to differentiate between the Height/ScaleHeight and Width/ScaleWidth properties of a given control. One gives you the external dimension and  the other gives you the "internal" dimensions of any container type control.  ScaleHeight and ScaleWidth can also be used to set a non standard resolution but for the  moment it is assumed you are using the default (twips) or another standard VB setting.

The Left and Top values are always relative to the container for any given control. In many circumstances this is the Form but may also be a relative position  within a containing Frame or Picture Box.

 

Google
 
Web www.adit.co.uk
www.aditsite.co.uk