|
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.
|