|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Visual Basic
Window/Form Routines Simulating Owned Windows for MDI Children |
||
Posted: | Monday October 01, 2001 | |
Updated: | Monday December 26, 2011 | |
Applies to: | VB4-32, VB5, VB6 | |
Developed with: | VB6, Windows XP | |
OS restrictions: | None | |
Author: | VBnet - Randy Birch | |
Prerequisites |
None. |
|
"Normal"
(non-MDI apps)
applications use the second parameter of a form's Show
command to specify that the calling form will "own" the
second form; that is, the second form remains above the calling form similar
to a modal dialog, yet allows activity to take place on either form. MDI applications behave differently. Only the MDI parent form can own another form, be it a MDI child, a modal dialog or a form where the parent was set as the Owner param. When a MDI application shows a form whose Owner parameter is specified, the only valid value for the Owner parameter is the MDI Parent form. Thus, when a developer needs to show a popup form (henceforth called "the Dialog") in a MDI application, either a modal form or a MDI Parent-owned form must be used. Modal forms in MDI applications defeat the very concept of MDI - that the user has the ability to switch between open MDI children at will. Displaying a modal form forces the user to complete actions on that form and close it in order to use other MDI children. Should the developer opt instead to use the Owner parameter and code so the Dialog form is owned by the MDI parent, the Dialog, which only has relevance to the currently-active MDI child, becomes both screen clutter when the user switches to another MDI child (as the Dialog remains on-screen), as well as a possible point of application error when data is errantly entered into a visible Dialog that may not be relevant to the current MDI child form, yet appears to be owned by the active form since the Dialog floats over the MDI parent. This demo shows how to maintain the principles of MDI while providing individual copies of the Dialog form for each MDI child requiring such, and how to code the those dialogs so that only the dialog for the currently-active MDI child form is displayed on screen. As the user moves from one MDI child from to another, previously displayed Owned forms are hidden, while the Owned form pertaining to the active child is displayed. This code was inspired by a newsgroup request for a means to provide multiple dialogs for data entry that behaved modally, yet still allowed the user to move between MDI child forms. The principle used is fairly straightforward and frankly, explaining it takes longer than creating the demo. The MDI parent has a button to load a new copy of a base MDI child Form1, using the standard "Dim x as New Form1" syntax. Each Form1 has a button that will display a dummy Dialog form. Multiple Form1's can be opened, and for each Form1, a corresponding Dialog can also be opened. The rules of VB dictate that each of the Dialog forms shown is owned (can only be owned) by the MDI parent form, so through the use of custom properties in both Form1 and the Dialog code the demo shows how to set up properties and methods that assure only the dialog owned by the currently-active Form1 is on-screen, hiding any other open Dialog forms that are owned by other Form1's that do not have focus. As the user switches between the different open Form1 children, the corresponding dialog, if loaded, reappears on-screen, while the previous dialog disappears. And as a bonus, all this is done in straight VB without APIs. The demo consists of three forms - the MDI Parent (MDIForm1), a MDI Child (Form1), and a dialog form (Dialog). There can be multiple Form1's, and any or all Form1 forms can have and own its own corresponding Dialog form. |
BAS Module Code |
None. |
|
MDI Parent Form Code "MDIForm1" |
To the MDI parent form - MDIForm1 - add a picturebox as a container and place into it two command buttons (Command1, Command2), along with the following code: |
|
Option Explicit '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' ' Copyright ©1996-2011 VBnet/Randy Birch, All Rights Reserved. ' Some pages may also contain other copyrights by the author. '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' ' Distribution: You can freely use this code in your own ' applications, but you may not reproduce ' or publish this code on any web site, ' online service, or distribute as source ' on any media without express permission. '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' Private Sub Command1_Click() 'define and load a new copy of 'Form1 as a MDI Child Dim f As Form Set f = New Form1 'this is just used to assist in 'identifying the forms and their 'owned dialogs. Static cnt As Long cnt = cnt + 1 f.Tag = f.Name & " - number " & cnt f.Caption = f.Tag f.Show End Sub Private Sub Command2_Click() 'tile the open Child forms 'in the MDI workspace MDIForm1.Arrange 1 End Sub |
MDI Child Form Code "Form1" |
To the MDI child form - Form1 - add a command button (Command1) and the following code: |
|
Option Explicit 'HasDialog property variable Private m_dialogshowing As Boolean 'holds reference to the owned dialog Private myDlg As Form Public Sub ClearDialogParams() 'a routine called by the owned dialog to 'reset the variables as it unloads m_dialogshowing = False Set myDlg = Nothing End Sub Private Sub Command1_Click() 'Create a new copy of the shared dialog form Set myDlg = New Dialog Load myDlg 'Set the property of this form to 'reflect the form has opened a 'dialog it wants to own HasDialog = True 'Required: set the Tag property of the 'owned dialog to the current form 'tag - in this case the form title. 'This allows us to know which form owns 'the dialog. myDlg.HasOwner = Me.Tag 'for debug only: set the caption on the owned dialog myDlg.Caption = "This dialog owned by : " & myDlg.HasOwner 'Show the form. Remember that all forms, 'both MDI children and non-MDI forms, are 'actually owned by the MDI parent window. 'Attempting to set the Owner parameter to 'the MDI Child form will generate an error 'as a MDI child can not be used as an owner 'for a Show command. myDlg.Show vbModeless, MDIForm1 End Sub Private Sub Form_Activate() SetDialogState True End Sub Public Function SetDialogState(state As Long) 'if this form has opened an owned dialog, 'then set the state of the dialog according 'to the activation state of the MDI Child 'form. When the form has focus, the owned 'dialog is shown. When the form loses focus 'to another MDI Child, the owned dialog 'disappears. If HasDialog() Then myDlg.Visible = state End If End Function Public Property Get HasDialog() As Boolean 'True if MDI Child has opened a 'dialog window, or false if not. HasDialog = m_dialogshowing End Property Private Property Let HasDialog(ByVal vNewValue As Boolean) m_dialogshowing = vNewValue End Property Private Sub Form_Deactivate() SetDialogState False End Sub Private Sub Form_Unload(Cancel As Integer) 'since the child is unloading might as well 'unload any owned dialog as well If HasDialog() Then Unload myDlg End Sub |
Non-MDI Dialog Form Code - "Dialog" |
Add a non-MDI form to the project, name it Dialog, and add two command buttons to the form (Command1, Command2). These buttons do nothing but unload the form, and are placeholders for actual OK or Cancel buttons. Once set up, add the following code to Dialog: |
|
Option Explicit Private m_ownedby As String Private Sub CancelButton_Click() '<code for Cancel> Unload Me End Sub Private Sub OKButton_Click() '<code for OK> Unload Me End Sub Public Property Get HasOwner() As String 'HasOwner will be empty ("") if no 'owner, or will contain the owner's 'window caption HasOwner = m_ownedby End Property Public Property Let HasOwner(ByVal vNewValue As String) m_ownedby = vNewValue End Property Private Sub Form_Unload(Cancel As Integer) Dim f As Form 'if this form is owned by a MDI Child If Len(HasOwner) > 0 Then 'iterate through the open forms collection For Each f In Forms 'if the tag property of the form 'equals the value of the m_ownedby 'variable, then we found the 'MDI Child form that owns this dialog 'form, so execute that MDI Child's 'ClearDialogParams routine to reset 'working variables before unloading. 'This allows the MDI Child to again 'show a new dialog as an owned form. If f.Tag = m_ownedby Then f.ClearDialogParams f.Enabled = True End If Next End If End Sub |
Comments |
Set the project start-up properties to MDIForm1, assure Form1 has its MDI Child property set to True, and run. Open several Form1 copies using the "Show New Form1" button. Hit the Tile button to arrange the forms for easier testing, then press the "Open Owned Dialog" button on one form. Move the dialog to another spot on the screen, and click on one of the other Form1 copies. The dialog form will disappear until the form that owned (created) the dialog is selected, at which point it will again appear on-screen at the last location. Press the "Open Owned Dialog" buttons on other forms, and again, move the forms a bit so you can see that different forms are activated as each MDI child form becomes active. |
|
|
|
|||||
|
|||||
|
|||||
Copyright ©1996-2011 VBnet and Randy Birch. All Rights Reserved. |