Option Explicit
Private Declare PtrSafe Function SetWindowLong Lib "user32" Alias "SetWindowLongPtrA" (ByVal hwnd As LongPtr, ByVal nIndex As Long, ByVal dwNewLong As LongPtr) As Long
Private Declare PtrSafe Function GetWindowLong Lib "user32" Alias "GetWindowLongPtrA" (ByVal hwnd As LongPtr, ByVal nIndex As Long) As Long
Private Const NULL_PTR = 0^
#Else
Private Declare PtrSafe Function SetWindowLong Lib "user32" Alias "SetWindowLongA" (ByVal hwnd As Long, ByVal nIndex As Long, ByVal dwNewLong As Long) As Long
Private Declare PtrSafe Function GetWindowLong Lib "user32" Alias "GetWindowLongA" (ByVal hwnd As Long, ByVal nIndex As Long) As Long
Private Const NULL_PTR = 0&
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
Private Declare PtrSafe Function CreateRectRgn Lib "gdi32" (ByVal X1 As Long, ByVal Y1 As Long, ByVal X2 As Long, ByVal Y2 As Long) As LongPtr
Private Declare PtrSafe Function SetWindowRgn Lib "user32" (ByVal hwnd As LongPtr, ByVal hRgn As LongPtr, ByVal bRedraw As Long) As Long
Private Declare PtrSafe Function DeleteObject Lib "gdi32" (ByVal hObject As LongPtr) 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 GetWindowLong Lib "user32" Alias "GetWindowLongA" (ByVal hwnd As Long, ByVal nIndex 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
Private Declare Function CreateRectRgn Lib "gdi32" (ByVal X1 As Long, ByVal Y1 As Long, ByVal X2 As Long, ByVal Y2 As Long) As LongPtr
Private Declare Function SetWindowRgn Lib "user32" (ByVal hwnd As LongPtr, ByVal hRgn As LongPtr, ByVal bRedraw As Long) As Long
Private Declare Function DeleteObject Lib "gdi32" (ByVal hObject As LongPtr) As Long
Private Const NULL_PTR = 0&
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 FakeHide(ThisWorkbook.Windows(1&), True)
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)
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 FakeHide(ByVal wnd As Window, ByVal bClipped As Boolean)
Call SetClipRegion(wnd.hwnd, bClipped)
Call SetStyles(wnd.hwnd, bClipped)
End Sub
Private Sub SetClipRegion(ByVal hwnd As LongPtr, ByVal bClipped As Boolean)
Dim hRgn As LongPtr
If bClipped Then
hRgn = CreateRectRgn(0&, 0&, 1&, 1&)
Call SetWindowRgn(hwnd, hRgn, True)
Call DeleteObject(hRgn)
Else
Call SetWindowRgn(hwnd, NULL_PTR, True)
End If
End Sub
Private Sub SetStyles(ByVal hwnd As LongPtr, ByVal bSet As Boolean)
Const GWL_EXSTYLE = (-20&), GWL_STYLE = (-16&)
Const WS_EX_TOOLWINDOW = &H80&, WS_EX_LAYERED = &H80000, WS_THICKFRAME = &H40000
Dim lStyle As Long, lExStyle As Long
lStyle = GetWindowLong(hwnd, GWL_STYLE)
lExStyle = GetWindowLong(hwnd, GWL_EXSTYLE)
If bSet Then
lStyle = lStyle And Not WS_THICKFRAME
lExStyle = (lExStyle Or WS_EX_TOOLWINDOW) Or WS_EX_LAYERED
Else
lStyle = lStyle Or WS_THICKFRAME
lExStyle = (lExStyle And Not WS_EX_TOOLWINDOW) And Not WS_EX_LAYERED
End If
Call SetWindowLong(hwnd, GWL_EXSTYLE, lExStyle)
Call SetWindowLong(hwnd, GWL_STYLE, lStyle)
End Sub
Private Sub FreeMemory()
Call CoLockObjectExternal(Me, False)
Set oForm = Nothing
Set cdbrsEvents = Nothing
Debug.Print "Mem released."
Call FakeHide(ThisWorkbook.Windows(1), False)
End Sub