devxlogo

Designing Complex Interfaces in VB

Designing Complex Interfaces in VB

arge scale applications should have a consistent look and feel, a consistent interface, and a menu structure that reflects the basic operations of the application. Typically, each form’s menu contains the operations that can be performed on the current form; however large cohesive applications may contain a large number of forms. Rather than having unique menus for each form, you’re better off designing a menu structure that accommodates both application tasks common to all forms, and the unique menu items that apply to the currently active form. That’s what MDI menus do?each form’s menu merges with the application’s menu structure so that the user sees a single menu bar that adapts to the tasks available on the active form.

VB and Scrolling Forms
One of the shortcomings of standalone VB forms is that they aren’t scrollable. When users reduce the size of a form to make room for other forms on the desktop, rather than scrollbars appearing, the usually some controls get hidden. Users then have to restore the form to its original size to view all the controls on it. To solve the hidden control problem, developers sometimes insert code in the form’s Resize event handler to prevent users from resizing the form below a predetermined threshold. In addition, there’s no simple mechanism to attach scrollbars to the form, so that users can scroll to the desired section of the form. This isn’t much of a problem with most typical business applications, but it’s a necessity with graphics applications, or applications with large amounts of text.

The .NET framework addresses both of these problems by exposing some new properties available from the Form Designer in Visual Studio.NET to choose how forms display scrollbars and to set a form’s minimum size. To prevent users from resizing a form, you must set the form’s minimum width and height from within the form’s Resize event handler. A better solution for many applications is to cause the form to scroll if the user resizes it so that not all the important content is visible.

The simplest way to implement a scrolling form in VB is to create the form as a child form of a parent MDI form. If you create an MDI child form that covers the entire parent form’s client area and the user resizes the parent form so that the child form isn’t entirely visible, the VB runtime automatically attaches scrollbars to the parent form?effectively letting you scroll the content. You can exploit this behavior of MDI forms to build scrollable forms.


Many business applications need multiple forms, but building (MDI) applications isn’t always the best solution. Users often prefer Single Document Interface (SDI) applications. To build these complex SDI interfaces, you need to be able to create scrolling forms with menus that merge.


Visual Basic doesn’t support standalone scrolling forms directly, nor does it support menu merges for standalone formsbut it supports both concepts for MDI child forms. You can take advantage of that support by using MDI techniques to create complex SDI interfaces.

Building a Multiple Document Application
The MultipleDocs sample application has an interface consisting of two forms, one for editing text and another one for viewing images. These are, respectively, a parent MDI form and two child forms, one covered completely by a TextBox control (see Figure 1) and another covered completely by a PictureBox control (see Figure 2).


Figure 1. The TextBox Control: The TextBox control belongs to a child form that fills the parent form.
 
Figure 2. The PictureBox Control: The scrolling PictureBox is implemented as a child form that contains a PictureBox control with its AutoSize property set to True.

Both forms are MDI child forms without a border (BorderStyle = 0), but?unlike a normal MDI application?users can display only one form at a time. In addition, both forms cover the entire parent form. This scheme provides you with a form that looks like a single window but provides instant scroll capability. If you run the project, and resize the window, you’ll see scrollbars appear whenever the window can’t display the entire text or the entire image.

To make this happen, you must ensure that when the user resizes the parent form the child form gets resized as well. On MDIForm1, for example, you want to make the TextBox control fill all the available area on the parent control. To that do so, you execute a few statements that resize the child form and the TextBox control on it from within the parent form’s Resize event handler, as shown here:

Public Sub MDIForm_Resize()   If MDIForm1.ActiveForm Is Nothing Then       Exit Sub   End If   If MDIForm1.ActiveForm Is MDIChildForm1 Then      MDIChildForm1.Width = MDIForm1.ScaleWidth      MDIChildForm1.Height = MDIForm1.ScaleHeight      MDIChildForm1.Text1.Width = MDIForm1.ScaleWidth      MDIChildForm1.Text1.Height = _         MDIForm1.ScaleHeight   End IfEnd Sub

If there's no active child form at the time, the first If structure in the Resize event handler takes no action. The remainder of the code resizes the child form to the parent form's ScaleWidth and ScaleHeight, and then resizes the text box to cover the entire client area.

The second child form contains a PictureBox control whose AutoSize property is set to True, so that the control is sized according to the size of the image displayed on it. To make the entire control visible, you must also make sure that the child form containing the PictureBox control is sized to the dimensions of the control. This takes place from within the second child form's Load event handler:

Private Sub Form_Load()   MDIChildForm2.Width = _      MDIChildForm2.Picture1.ScaleWidth   MDIChildForm2.Height = _      MDIChildForm2.Picture1.ScaleHeightEnd Sub

You must execute the same statements from within any procedure that loads an image on the PictureBox control (if you implement an Open command, for example). Notice that you don't have to resize the PictureBox control to the parent form's size. The PictureBox controls dimensions are determined by the image. The main MDI form attaches the appropriate scrollbars to the child form automatically. If the image is smaller than child form, part of the main form's client area will be empty.

Finally, you need a few statements to display the appropriate child form when the user selects one of the commands of the Window menu. While each child form has its own menu, the Window menu belongs to the parent form, and the following statements need not be duplicated on all child forms.

Private Sub mnuWindow1_Click()    MDIChildForm2.Hide    MDIChildForm1.Show    MDIChildForm1.Top = 0    MDIChildForm1.Left = 0End SubPrivate Sub mnuWindow2_Click()    MDIChildForm1.Hide    MDIChildForm2.Show    MDIChildForm2.Top = 0    MDIChildForm2.Left = 0End Sub

When the application starts, it displays only the parent form, which contains a menu bar with a single Window submenu (this is not implemented as a WindowList menu, because the MultipleDocs application is not a true MDI application). The Window menu contains commands that display the child forms of the application. Select one of the commands and the corresponding child form fills the parent form's area. Because the child form has no visible border, users don't perceive it as an MDI child form. The interface has the look and feel of an SDI application with added functionality that can't be implemented easily without MDI forms.

Static Child Forms
The next sample project required designing an interface for a typical business application that consists of several modules for manipulating customers, suppliers, products, orders, and so forth. Each component of the application requires a different form. You could easily implement an MDI interface for such an application; but too many open windows on a parent MDI Form can easily confuse users, especially if a menu command opens a new window rather than activating a corresponding existing window.

 
Figure 3. Fixed Size: This parent form displays a different child form, depending on the command selected from the Windows menu. The current child form is centered in the available space and can't be moved or resized. The parent form can't be resized either.

In this example, users work with one window at a time and don't need to have multiple windows open at the same time. Therefore, instead of opening new child forms and letting users rearrange them on the parent form?as in a typical MDI application?you can display static child forms: forms of fixed size that can't be moved around, or be minimized/maximized, such as the one shown in Figure 3.

Users reach other basic components of the application through appropriate menu items, each of which opens the appropriate child form. The result is a very functional SDI interface. You achieve the effect of an MDI application, but user deal with only one form at a time, depending on the current operation.

The FixedChildForms sample project, shown in Figure 3, consists of a parent MDI form and a number of child forms. Users can switch between child forms by selecting the appropriate command in the Windows menu. Each child form has its own menu, which contains commands that are specific to the form and are displayed to the right of the Windows menu on the parent form's menu bar.

The application displays each child form using a set of statements such as the following, which center the child form on the parent form.

Private Sub mnuWindow1_Click()   Form1.Width = ParentForm.ScaleWidth - _      20 * Screen.TwipsPerPixelX   Form1.Height = ParentForm.ScaleHeight - _      20 * Screen.TwipsPerPixelY   Form1.Left = 10 * Screen.TwipsPerPixelX   Form1.Top = 10 * Screen.TwipsPerPixelX   Form1.Show   Form1.Label1.Width = Form1.ScaleWidth   Form1.Label2.Width = Form1.ScaleWidth   Form1.Label1.Caption = "Window 1"   HideMenus   mnuForm1.Visible = TrueEnd Sub

The child forms have no minimize/maximize buttons on their title bar and each form's Movable property is set to False. In addition, their BorderStyle property is set to 1 (Fixed Single), so that they cant be resized either. As a result, they remain fixed on the parent form. Of course, you must make sure that the controls on each child form fit in the available space.

Each child form has its own menu, but when you display a child, VB merges its menu with the parent forms menu. That happens automatically when you set the child form's NegotiateMenus property to True. To demonstrate the functionality of this style of interface I've added a simple menu to each child form. The commands of the menus don't do much: They print the name of the selected command on a Label control on the current form. The code that enables each child form to interact with the user is contained within the corresponding form.

A Tree Menu
One problem with this type of interface is that the menu on the parent form changes according to the active child form. In addition, users must select an item from the Windows menu to reach a different component of the application.

To solve these problems, the MDIMenu project presents a more functional interface that gives users the ability to reach any part of the application via a TreeView control in a "menu frame" that remains visible at all times. The menu contains the commands that fire basic operations. The menu hierarchically displays each child form's commands as well (see Figure 4). The hierarchical menu on the left is visible at all times, offering instant access to the application's basic operations. These operations are grouped under major headings. Users can show or hide groups of commands at will. You can easily hide certain operations from users with limited privileges by skipping selected nodes on the TreeView control that contains the menu items.

Selecting an item in the menu displays the appropriate child form in the remaining screen area. This child form is centered on its parent form. However, it doesn't exhibit the usual characteristics of an MDI interface; the placement and size of the child form are fixed so it can't be minimized of maximized, as discussed in the Static Child Forms section of this solution.

 
Figure 4. Two Menu Levels: The menu in the left pane is for navigating through the application's forms. Each form has its own menu, which is displayed on the parent forms menu bar as usual.

The interface in Figure 4 shows the MDIMenu project, which consists of an MDI parent form containing two child forms: one (the menu) docked at the left edge of the form and another one that takes up the remaining space of the parent form. Docking a child form on an MDI form is not difficult, but it does take a few lines of code. You must make sure that users can't move the child form around using the menu. To accomplish that , strip the child form of its title bar and control box by setting its BorderStyle property to 0 (None).

Visual Studio .NET's Form Designer provides mechanisms for anchoring and docking elements on a form.The menu itself is a TreeView control that fills its parent form. The nodes of the control reflect the hierarchical structure of the menu, and hold the text of the commands that show the various forms in the application. Code in the MDI forms Load event handler populates the TreeView control when the application starts.

If a user resizes the main form, you must also resize both the child form with the menu and any active child form so that their height is equal to the new height of the MDI parent form's height. The following statements set the height of the form with the menu so that it fills vertically the parent form. In addition, they resize the active child form so that it fills the available area on the parent form. You must place the statements in the parent form's Resize event, which is fired every time the user resizes the parent form.

Private Sub MDIForm_Resize()    MenuForm.Top = 0    MenuForm.Left = 0    MenuForm.Width = 250 * Screen.TwipsPerPixelX    MenuForm.Height = MDIForm1.ScaleHeight    MenuForm.TreeView1.Height = MDIForm1.ScaleHeight'RESIZE THE ACTIVE CHILD FORM SO THAT IT FILLS'THE ENTIRE PARENT FORM TO THE RIGHT OF THE MENU FORM    If Not MDIForm1.ActiveForm Is Nothing And _        Not MDIForm1.ActiveForm Is MenuForm Then                ' DO NOT RESIZE CHILD FORM            ' WITH MENU WHEN NO OTHER CHILD FORM            ' IS ACTIVE AT THE TIME            ' DO NOT RESIZE CHILD FORMS WHEN             ' PARENT FORM IS MINIMIZED            ' TO AVOID A RUN-TIME ERROR !        If Not MDIForm1.WindowState = vbMinimized Then            MDIForm1.ActiveForm.Width = _                  MDIForm1.ScaleWidth - _                  MenuForm.ScaleWidth - _                  2 * Screen.TwipsPerPixelX            MDIForm1.ActiveForm.Height = _                  MDIForm1.ScaleHeight - _                  2 * Screen.TwipsPerPixelY        End If    End IfEnd Sub

In this sample application, the child forms are simply different instances of a single form but with different background colors. In a real application each command on the you would design a different child form for each of the commands of the hierarchical menu. I've also added a few statements to print the name of the selected command on a Label control on the appropriate form to show that every child form contains its own code to interact with the user.

As you have seen, MDI interfaces are not limited to applications that open multiple documents of the same type. You can use MDI techniques to enhance your SDI interfaces, especially if they're made up of a large number of forms.

devxblackblue

About Our Editorial Process

At DevX, we’re dedicated to tech entrepreneurship. Our team closely follows industry shifts, new products, AI breakthroughs, technology trends, and funding announcements. Articles undergo thorough editing to ensure accuracy and clarity, reflecting DevX’s style and supporting entrepreneurs in the tech sphere.

See our full editorial policy.

About Our Journalist