Option Explicit
#If VBA7 Then
#If Win64 Then
Private Declare PtrSafe Function SetWindowLong Lib "user32" Alias "SetWindowLongPtrA" (ByVal hwnd As LongPtr, ByVal nIndex As Long, ByVal dwNewLong As LongPtr) As Long
#Else
Private Declare PtrSafe Function SetWindowLong Lib "user32" Alias "SetWindowLongA" (ByVal hwnd As Long, ByVal nIndex As Long, ByVal dwNewLong As Long) As Long
#End If
Private Declare PtrSafe Function IUnknown_GetWindow Lib "shlwapi" Alias "#172" (ByVal pIUnk As IUnknown, ByVal hwnd As LongPtr) As Long
Private Declare PtrSafe Function SetActiveWindow Lib "user32" (ByVal hwnd As LongPtr) As LongPtr
Private Declare PtrSafe Function ShowWindowAsync Lib "user32" (ByVal hwnd As LongPtr, ByVal nCmdShow As Long) As Long
Private Declare PtrSafe Function IsIconic Lib "user32" (ByVal hwnd As LongPtr) As Long
Private Declare PtrSafe Function CoLockObjectExternal Lib "ole32.dll" (ByVal punk As IUnknown, ByVal fLock As Boolean, Optional ByVal fLastUnlockReleases As Boolean) As Long
#Else
Private Enum LongPtr
[_]
End Enum
Private Declare Function SetWindowLong Lib "user32" Alias "SetWindowLongA" (ByVal hwnd As Long, ByVal nIndex As Long, ByVal dwNewLong As Long) As Long
Private Declare Function IUnknown_GetWindow Lib "shlwapi" Alias "#172" (ByVal pIUnk As IUnknown, ByVal hwnd As LongPtr) As Long
Private Declare Function SetActiveWindow Lib "user32" (ByVal hwnd As LongPtr) As LongPtr
Private Declare Function ShowWindowAsync Lib "user32" (ByVal hwnd As LongPtr, ByVal nCmdShow As Long) As Long
Private Declare Function IsIconic Lib "user32" (ByVal hwnd As LongPtr) As Long
Private Declare Function CoLockObjectExternal Lib "ole32.dll" (ByVal punk As IUnknown, ByVal fLock As Boolean, Optional ByVal fLastUnlockReleases As Boolean) As Long
#End If
Private WithEvents AppEvents As Application
Private WithEvents cdbrsEvents As CommandBars
Private oForm As Object
Private hOwnerHwnd As LongPtr
Public Sub Init(Form As Object)
If Val(Application.Version) >= 15 Then
hOwnerHwnd = ThisWorkbook.Windows(1).hwnd
Call CoLockObjectExternal(Me, True)
Set oForm = Form
Set AppEvents = Application
Set cdbrsEvents = Application.CommandBars
End If
End Sub
Private Sub AppEvents_WindowActivate(ByVal Wb As Workbook, ByVal Wn As Window)
Dim hwnd As LongPtr
Call IUnknown_GetWindow(oForm, VarPtr(hwnd))
If IsIconic(Wn.hwnd) Then
Wn.WindowState = xlNormal
End If
Call SetOwner(hwnd, Wn.hwnd)
Call SetActiveWindow(hwnd)
Call ShowWindowAsync(hwnd, 1&)
Set cdbrsEvents = Wn.Parent.Parent.CommandBars
End Sub
Private Sub AppEvents_WorkbookBeforeClose(ByVal Wb As Workbook, Cancel As Boolean)
#If Win64 Then
Const NULL_PTR = 0^
#Else
Const NULL_PTR = 0&
#End If
Dim hwnd As LongPtr
Call IUnknown_GetWindow(oForm, VarPtr(hwnd))
If Wb Is ThisWorkbook Then
Call SetOwner(hwnd, NULL_PTR)
Call FreeMemory
Else
Call SetOwner(hwnd, hOwnerHwnd)
End If
End Sub
Private Sub cdbrsEvents_OnUpdate()
If FormExists = False Then
Call FreeMemory
End If
End Sub
Private Sub SetOwner(ByVal hwnd As LongPtr, Owner As LongPtr)
Const GWL_HWNDPARENT = (-8)
Call SetWindowLong(hwnd, GWL_HWNDPARENT, Owner)
End Sub
Private Function FormExists() As Boolean
Dim oUf As Object
For Each oUf In VBA.UserForms
If oForm Is oUf Then
FormExists = True: Exit Function
End If
Next oUf
End Function
Private Sub FreeMemory()
Call CoLockObjectExternal(Me, False)
Set oForm = Nothing
Set cdbrsEvents = Nothing
Debug.Print "Mem released."
End Sub