Option Explicit
Option Base 0
'modChildForms.bas
'Win32 API function used to verify a handle
Private Declare Function IsWindow Lib "user32" _
(ByVal hwnd As Long) As Long
'Win32 API function used to change a form's parent window
Private Declare Function SetParent Lib "user32" _
(ByVal hWndChild As Long, _
ByVal hWndNewParent As Long) As Long
'VB forms are created from one of these 2 class:
Private Const VB_IDE_FORM_CLASS As String = "ThunderFormDC"
Private Const VB_RUN_FORM_CLASS As String = "ThunderRT6FormDC"
'Pass this API function the handle of a parent window and
'the address of a callback function and Windows will call
'the callback function once for each child window.
'Remember that forms are not the only "windows" ...
'Most controls (ie: textbox, button) are also "windows."
Private Declare Function EnumChildWindows Lib "user32" _
(ByVal hWndParent As Long, _
ByVal lpEnumFunc As Long, _
ByVal lParam As Long) As Long
'Pass this API function the handle to a window and Windows
'returns the name of the class from which it was created.
Private Declare Function GetClassName Lib "user32" _
Alias "GetClassNameA" _
(ByVal hwnd As Long, _
ByVal lpClassName As String, _
ByVal nMaxCount As Long) As Long
'Pass this API function the handle to a window and Windows
'returns the caption from the title bar.
Private Declare Function GetWindowText Lib "user32" _
Alias "GetWindowTextA" _
(ByVal hwnd As Long, _
ByVal lpString As String, _
ByVal cch As Long) As Long
'This UDT holds a window handle and title bar caption
Public Type VBChildFormType
hwnd As Long
TitleBar As String
End Type
Private ChildForms() As VBChildFormType
'-----------------------------------------------------------
' Procedure : LoadChildForm
' Date : 5/31/2005
' Purpose : Loads and Shows a VB form as a child form.
' Returns handle of previous parent.
'-----------------------------------------------------------
Public Function LoadChildForm(frmChild As VB.Form, _
hWndParent As Long, _
Optional bDesktop As Boolean = False) As Long
If Not bDesktop And (hWndParent = 0) Then
Err.Raise vbObjectError + 1, _
"LoadChildForm", _
"bDesktop flag must be True if you wish to set " _
& "this form to be a child of desktop."
Exit Function
End If
If Not CBool(IsWindow(hWndParent)) Then
Err.Raise vbObjectError + 1, _
"LoadChildForm", _
"Invalid parent window handle."
Exit Function
End If
Load frmChild
LoadChildForm = SetParent(frmChild.hwnd, hWndParent)
frmChild.Move 200, 200
frmChild.Show
End Function
'-----------------------------------------------------------
' Procedure : CallBackEnumChildWindows
' Date : 5/31/2005
' Purpose : This is the callback for EnumChildWindows().
' This function is called by the Windows OS once
' for each child window.
'
' The only reason this function is Public is so
' that Windows can use it as a callback. This
' function should not be directly called from
' within this project
'-----------------------------------------------------------
Public Function CallBackEnumChildWindows(ByVal hwnd As Long, _
ByVal lpData As Long) As Long
'Set return value to 1 (setting it to 0 halts the enumeration)
CallBackEnumChildWindows = 1
'What type of window is this handle?
Dim strBuffer As String
Dim lBufferLen As Long
strBuffer = String$(256, Chr(0))
lBufferLen = GetClassName(hwnd, strBuffer, 255)
strBuffer = Left$(strBuffer, lBufferLen)
'Exit if not a handle to a VB form window
If (strBuffer <> VB_IDE_FORM_CLASS) And _
(strBuffer <> VB_RUN_FORM_CLASS) Then
Exit Function
End If
'Get the title caption
strBuffer = String$(256, Chr(0))
lBufferLen = GetWindowText(hwnd, strBuffer, 255)
strBuffer = Left$(strBuffer, lBufferLen)
'Configure new UDT
Dim udtForm As VBChildFormType
udtForm.hwnd = hwnd
udtForm.TitleBar = strBuffer
'Add new element to ChildForms() UDT array
Dim lCount As Long
Err.Clear
On Error Resume Next
lCount = UBound(ChildForms)
If Err.Number = 9 Then
ReDim ChildForms(0)
Else
ReDim Preserve ChildForms(lCount + 1)
End If
Err.Clear
On Error GoTo 0
ChildForms(UBound(ChildForms)) = udtForm
End Function
'-----------------------------------------------------------
' Procedure : GetChildForms
' Date : 5/31/2005
' Purpose : Returns array of UDT elements. Each element
' contains the handle and title caption of one
' child form.
'-----------------------------------------------------------
Public Function GetChildForms(hWndParent As Long) As VBChildFormType()
If Not CBool(IsWindow(hWndParent)) Then
Err.Raise vbObjectError + 1, _
"GetChildForms", _
"Invalid parent window handle."
Exit Function
End If
Erase ChildForms
Dim lRet As Long
lRet = EnumChildWindows(hWndParent, AddressOf CallBackEnumChildWindows, 0)
If lRet = 0 Then Erase ChildForms
GetChildForms = ChildForms
End Function
'-----------------------------------------------------------
' Procedure : CountChildForms
' Date : 5/31/2005
' Purpose : Returns the number of child forms.
'-----------------------------------------------------------
Public Function CountChildForms(hWndParent As Long) As Long
If Not CBool(IsWindow(hWndParent)) Then
Err.Raise vbObjectError + 1, _
"GetChildForms", _
"Invalid parent window handle."
Exit Function
End If
GetChildForms hWndParent
Err.Clear
On Error Resume Next
CountChildForms = UBound(ChildForms)
If (Err.Number = 0) Then
'Add 1 because ChildForms is zero based array
CountChildForms = CountChildForms + 1
End If
Err.Clear
On Error GoTo 0
End Function
'-----------------------------------------------------------
' Procedure : GetChildFormsCollection
' Date : 5/31/2005
' Purpose : Returns collection object containing VB Forms
' that are child forms of the input parameter.
'-----------------------------------------------------------
Public Function GetChildFormsCollection(hWndParent As Long) As Collection
If Not CBool(IsWindow(hWndParent)) Then
Err.Raise vbObjectError + 1, _
"GetChildForms", _
"Invalid parent window handle."
Exit Function
End If
Dim lMax As Long
Dim lCount As Long
Dim frmTemp As VB.Form
Set GetChildFormsCollection = New Collection
lMax = CountChildForms(hWndParent)
If (lMax = 0) Then Exit Function
For lCount = 1 To lMax
'Find the form with matching handle
For Each frmTemp In VB.Forms
If (frmTemp.hwnd = ChildForms(lCount - 1).hwnd) Then
GetChildFormsCollection.Add frmTemp, CStr(ChildForms(lCount - 1).hwnd)
Exit For
End If
Next
Next
Set frmTemp = Nothing
End Function
'-----------------------------------------------------------
' Procedure : ShowChildForms
' Date : 5/31/2005
' Purpose : Makes all child forms visible.
'-----------------------------------------------------------
Public Sub ShowChildForms(hWndParent As Long)
If Not CBool(IsWindow(hWndParent)) Then
Err.Raise vbObjectError + 1, _
"GetChildForms", _
"Invalid parent window handle."
Exit Sub
End If
Dim colChildForms As New Collection
Dim frmTemp As VB.Form
Set colChildForms = GetChildFormsCollection(hWndParent)
For Each frmTemp In colChildForms
frmTemp.Show
Next
Set frmTemp = Nothing
Set colChildForms = Nothing
End Sub
'-----------------------------------------------------------
' Procedure : HideChildForms
' Date : 5/31/2005
' Purpose : Makes all child forms invisible.
'-----------------------------------------------------------
Public Sub HideChildForms(hWndParent As Long)
If Not CBool(IsWindow(hWndParent)) Then
Err.Raise vbObjectError + 1, _
"GetChildForms", _
"Invalid parent window handle."
Exit Sub
End If
Dim colChildForms As New Collection
Dim frmTemp As VB.Form
Set colChildForms = GetChildFormsCollection(hWndParent)
For Each frmTemp In colChildForms
frmTemp.Hide
Next
Set frmTemp = Nothing
Set colChildForms = Nothing
End Sub
'-----------------------------------------------------------
' Procedure : UnloadChildForms
' Date : 5/31/2005
' Purpose : Explicitly unloads all child forms.
'-----------------------------------------------------------
Public Sub UnloadChildForms(hWndParent As Long, _
Optional hWndOrigParent As Long = 0)
If Not CBool(IsWindow(hWndParent)) Then
Err.Raise vbObjectError + 1, _
"GetChildForms", _
"Invalid parent window handle."
Exit Sub
End If
Dim colChildForms As New Collection
Dim frmTemp As VB.Form
Set colChildForms = GetChildFormsCollection(hWndParent)
For Each frmTemp In colChildForms
If hWndOrigParent Then SetParent frmTemp.hwnd, hWndOrigParent
Unload frmTemp
Next
Set frmTemp = Nothing
Set colChildForms = Nothing
End Sub
'-----------------------------------------------------------
' Procedure : CascadeChildForms
' Date : 6/1/2005
' Purpose : Cascades child forms in top left of parent.
'-----------------------------------------------------------
Public Sub CascadeChildForms(hWndParent As Long)
If Not CBool(IsWindow(hWndParent)) Then
Err.Raise vbObjectError + 1, _
"GetChildForms", _
"Invalid parent window handle."
Exit Sub
End If
Dim lCount As Long
Dim colChildForms As New Collection
Dim oForm As VB.Form
Set colChildForms = GetChildFormsCollection(hWndParent)
For Each oForm In colChildForms
lCount = lCount + 1
oForm.WindowState = vbNormal
oForm.Move (lCount * 200), (lCount * 200)
Next
Set oForm = Nothing
Set colChildForms = Nothing
End Sub