The ControlArray.frm sample demonstrates some basic techniques of control arrays using labels and menus (yes, menus are controls in VB). This sample loads a menu and label control array with a list of files for a selected directory. Every time the user switches directories, the control array is reset back to its default setting. shows a sample of what ControlArray.frm looks like after the cmdBuildArray button has been clicked for the selected directory.
ControlArray.frm demonstrates control array techniques using menus and labels
shows how to build a dynamic label and menu control array when the user clicks a button.
Listing 32.1 - CONTROLARRAY.FRM - The cmdBuildArray_Click event demonstrates how to load and display a control array
'********************************************************************* ' Builds the control array for the current path in the dir control. '********************************************************************* Private Sub cmdBuildArray_Click() Dim strFileName As String Dim intIndex As Integer Dim intNewHeight As Integer Static intOrigHeight As Integer '***************************************************************** ' Get the original height of the form -- once '***************************************************************** If intOrigHeight = 0 Then intOrigHeight = Height End If '***************************************************************** ' Get the first filename from the path in the dir control '***************************************************************** strFileName = Dir(dirPath.Path & _ IIf(Right(dirPath.Path, 1) = "\", "", "\") & "*.*") '***************************************************************** ' Loop while dir is returning files '***************************************************************** Do While Len(strFileName) '************************************************************* ' If intIndex > 0, then create a new control under the prev '************************************************************* If intIndex > 0 Then Load lblControlArray(intIndex) With lblControlArray(intIndex) .Move .Left, lblControlArray(intIndex - 1).Top + _ lblControlArray(intIndex - 1).Height .Visible = True End With Load mnuArrayItems(intIndex) mnuArrayItems(intIndex).Visible = True End If '************************************************************* ' Stop at twenty and let the user know there were 20 files '************************************************************* If intIndex = 20 Then mnuArrayItems(intIndex).Caption = "More files..." With lblControlArray(intIndex) .Caption = "More files..." .Font.Bold = True End With Exit Do '************************************************************* ' Otherwise set the caption and find the next file '************************************************************* Else lblControlArray(intIndex) = strFileName mnuArrayItems(intIndex).Caption = strFileName strFileName = Dir If Len(strFileName) Then intIndex = intIndex + 1 End If Loop '**************************************************************** ' If the dir was empty, then notify the user in the first label ' and menu '**************************************************************** If intIndex = 0 Then lblControlArray(0) = "No files found!" mnuArrayItems(0).Caption = "No files found!" '**************************************************************** ' Otherwise, resize the form '**************************************************************** Else '************************************************************ ' Height of the title bar and border '************************************************************ intNewHeight = (Height - ScaleHeight) intNewHeight = intNewHeight + lblControlArray(intIndex).Top intNewHeight = intNewHeight + lblControlArray(intIndex).Height End If '**************************************************************** ' If the new calculated height > original height, then resize '**************************************************************** If intNewHeight > intOrigHeight Then Height = intNewHeight '**************************************************************** ' Otherwise resize to the default '**************************************************************** Else Height = intOrigHeight End If '**************************************************************** ' Disable the cmdButton until the user changes directories '**************************************************************** cmdBuildArray.Enabled = False End Sub
When using control arrays there are several important concepts to remember. They are:
The code in demonstrates step 2 (listed previously) about how to shrink the control array without accidentally trying unload the first element.
Listing 32.2 - CONTROLARRAY.FRM - dirPath_Change demonstrates how to unload a control array
'********************************************************************* ' Unload the control array every time the user changes the directory '********************************************************************* Private Sub dirPath_Change() Dim ctl As Control '**************************************************************** ' Iterate through the controls collection unloading the labels ' and menus '**************************************************************** For Each ctl In Controls If ctl.Name = "lblControlArray" Or ctl.Name = _ "mnuArrayItems" Then '******************************************************** ' If the index > 0 then unload it '******************************************************** If ctl.Index Then Unload ctl End If Next ctl '**************************************************************** ' Clear the first menu & label and re-enable the command button '**************************************************************** mnuArrayItems(0).Caption = "" lblControlArray(0) = "" cmdBuildArray.Enabled = True End Sub
The code in the mnuArrayItems_Clickevent below is a simplistic example of how using control arrays for menus can save you from having to write a lot of duplicate code. If you didn't have an array of menu items, the following code would have to appear in twenty separate click events, and you would have to display and hide each menu item based on the selection of dirPath.
'********************************************************************* ' Display the menu caption when a menu item is clicked '********************************************************************* Private Sub mnuArrayItems_Click(Index As Integer) MsgBox mnuArrayItems(Index).Caption, vbInformation End Sub
Can you think of some real world examples of where menu control arrays might be a real code saver? How about a Most Recently Used (MRU) menu? Perhaps the most common application is in the Window menu of a MDI application. The following code was taken from MDIChild.frmin the next chapter:
'********************************************************************* ' If you set your indexes of your Window menu properly, you can save ' yourself some code. I was careful to make sure my Window menu items ' indices were equivalent to the possible values for the Arrange ' method. '********************************************************************* Private Sub mnuWindowItems_Click(Index As Integer) MDIParent.Arrange Index End Sub
![]()
It is my humble opinion that you should always use control arrays for menus, since it is much more readable to have all of the code for a series of similar menu items (such as the Edit menu items) together.
Another more practical use for control arrays are with option buttons. I'm always amazed to see the complicated maze of code that people create to handle something as simple as option buttons. However, the average VB programmer is either unfamiliar (or uncomfortable) with control arrays, so they don't honestly see a better way to use option buttons. The code in demonstrates how easy it is to use control arrays with option buttons.
Listing 32.3 - OPTDEMO.FRM - Option Buttons were made for Control Arrays'********************************************************************* ' OptDemo.frm - Demonstrates how to use a option button control array '********************************************************************* Option Explicit '********************************************************************* ' Val(<parent frame>).Tag returns the index of the currently selected ' option button. We'll use this information to display the caption of ' the currently selected option button. '********************************************************************* Private Sub cmdCurButton_Click() Caption = optButtons(Val(fraParent.Tag)).Caption & " is selected!" End Sub '********************************************************************* ' Set the value of the initial option button (which fires the click ' event for that index) '********************************************************************* Private Sub Form_Load() optButtons(0).Value = True End Sub '********************************************************************* ' Store the index (or some other useful data) of the currently ' selected option button in the frame containing the option buttons '********************************************************************* Private Sub optButtons_Click(Index As Integer) optButtons(Index).Container.Tag = CStr(Index) End Sub