Option Explicit
Private Type POINTAPI
X As Long
Y As Long
End Type
Private Type RECT
Left As Long
Top As Long
Right As Long
Bottom As Long
End Type
#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 LongPtr
Private Declare PtrSafe Function GetWindowLong Lib "user32" Alias "GetWindowLongPtrA" (ByVal hwnd As LongPtr, ByVal nIndex As Long) As LongPtr
#Else
Private Declare PtrSafe Function SetWindowLong Lib "user32" Alias "SetWindowLongA" (ByVal hwnd As LongPtr, ByVal nIndex As Long, ByVal dwNewLong As LongPtr) As LongPtr
Private Declare PtrSafe Function GetWindowLong Lib "user32" Alias "GetWindowLongA" (ByVal hwnd As LongPtr, ByVal nIndex As Long) As LongPtr
#End If
#Else
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
#End If
#If VBA7 Then
Private Type MSG
hwnd As LongPtr
message As Long
wParam As LongPtr
lParam As LongPtr
time As Long
pt As POINTAPI
End Type
Private Declare PtrSafe Function PostMessage Lib "user32" Alias "PostMessageA" (ByVal hwnd As LongPtr, ByVal wMsg As Long, ByVal wParam As LongPtr, ByVal lParam As LongPtr) As Long
Private Declare PtrSafe Function GetMessage Lib "user32" Alias "GetMessageA" (lpMsg As MSG, ByVal hwnd As LongPtr, ByVal wMsgFilterMin As Long, ByVal wMsgFilterMax As Long) As Long
Private Declare PtrSafe Function GetParent Lib "user32" (ByVal hwnd As LongPtr) As LongPtr
Private Declare PtrSafe Function FindWindowEx Lib "user32" Alias "FindWindowExA" (ByVal hWnd1 As LongPtr, ByVal hWnd2 As LongPtr, ByVal lpsz1 As String, ByVal lpsz2 As String) As LongPtr
Private Declare PtrSafe Function RedrawWindow Lib "user32" (ByVal hwnd As LongPtr, ByVal lprcUpdate As Long, ByVal hrgnUpdate As LongPtr, ByVal fuRedraw As Long) As Long
Private Declare PtrSafe Function GetSystemMetrics Lib "user32" (ByVal nIndex As Long) As Long
Private Declare PtrSafe Function GetWindowRect Lib "user32" (ByVal hwnd As LongPtr, lpRect As RECT) As Long
Private Declare PtrSafe Function SystemParametersInfo Lib "user32" Alias "SystemParametersInfoA" (ByVal uAction As Long, ByVal uParam As Long, ByRef lpvParam As Any, ByVal fuWinIni As Long) As Long
Private Declare PtrSafe Function EqualRect Lib "user32" (lpRect1 As RECT, lpRect2 As RECT) 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 DeleteObject Lib "gdi32" (ByVal hObject As LongPtr) As Long
Private Declare PtrSafe Function PtInRegion Lib "gdi32" (ByVal hRgn As LongPtr, ByVal X As Long, ByVal Y As Long) As Long
Private Declare PtrSafe Function SetWindowPos Lib "user32" (ByVal hwnd As LongPtr, ByVal hWndInsertAfter As LongPtr, ByVal X As Long, ByVal Y As Long, ByVal cx As Long, ByVal cy As Long, ByVal wFlags As Long) As Long
Private hwndXLDESK As LongPtr, hRgn As LongPtr
Private lStyle As LongPtr
#Else
Private Type MSG
hwnd As Long
message As Long
wParam As Long
lParam As Long
time As Long
pt As POINTAPI
End Type
Private Declare Function PostMessage Lib "user32" Alias "PostMessageA" (ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
Private Declare Function GetMessage Lib "user32" Alias "GetMessageA" (lpMsg As MSG, ByVal hwnd As Long, ByVal wMsgFilterMin As Long, ByVal wMsgFilterMax As Long) As Long
Private Declare Function GetParent Lib "user32" (ByVal hwnd As Long) As Long
Private Declare Function FindWindowEx Lib "user32" Alias "FindWindowExA" (ByVal hWnd1 As Long, ByVal hWnd2 As Long, ByVal lpsz1 As String, ByVal lpsz2 As String) As Long
Private Declare Function RedrawWindow Lib "user32" (ByVal hwnd As Long, ByVal lprcUpdate As Long, ByVal hrgnUpdate As Long, ByVal fuRedraw As Long) As Long
Private Declare Function GetSystemMetrics Lib "user32" (ByVal nIndex As Long) As Long
Private Declare Function GetWindowRect Lib "user32" (ByVal hwnd As Long, lpRect As RECT) As Long
Private Declare Function SystemParametersInfo Lib "user32" Alias "SystemParametersInfoA" (ByVal uAction As Long, ByVal uParam As Long, ByRef lpvParam As Any, ByVal fuWinIni As Long) As Long
Private Declare Function EqualRect Lib "user32" (lpRect1 As RECT, lpRect2 As RECT) 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 Long
Private Declare Function DeleteObject Lib "gdi32" (ByVal hObject As Long) As Long
Private Declare Function PtInRegion Lib "gdi32" (ByVal hRgn As Long, ByVal x As Long, ByVal y As Long) As Long
Private Declare Function SetWindowPos Lib "user32" (ByVal hwnd As Long, ByVal hWndInsertAfter As Long, ByVal x As Long, ByVal y As Long, ByVal cx As Long, ByVal cy As Long, ByVal wFlags As Long) As Long
Private hwndXLDESK As Long, hRgn As Long
Private lStyle As Long
#End If
Private Const WM_NCLBUTTONDOWN = &HA1
Private Const WM_NCLBUTTONDBLCLK = &HA3
Private Const WM_NCRBUTTONUP = &HA5
Private Const GWL_STYLE = (-16)
Private Const WS_MINIMIZEBOX = &H20000
Private Const WS_MAXIMIZEBOX = &H10000
Private Const WS_THICKFRAME = &H40000
Private Const HWND_TOPMOST = -1
Private Const HWND_NOTOPMOST = -2
Private Const SWP_NOSIZE = &H1
Private Const SWP_NOMOVE = &H2
Private Const SM_CXSCREEN = 0
Private Const SM_CYSCREEN = 1
Private Const SM_CXSIZE = 30
Private Const SM_CYCAPTION = 4
Private Const SM_CYBORDER = 6
Private Const SM_CYDLGFRAME = 8
Private Const SPI_GETWORKAREA = 48
Private Const RDW_INTERNALPAINT = &H2
Private bCancel As Boolean
Private bMsgsBeingIntercepted As Boolean
[B][COLOR=#008000]'Private routines.
'=================[/COLOR][/B]
Public Sub Start()
Call Prevent_Resizing_Moving_Excel(CenterExcelWindow:=True, MakeExcelTopMost:=True)
End Sub
Public Sub Finish()
Call Restore_Excel_Default
End Sub
[B][COLOR=#008000]'Private routines.
'=================[/COLOR][/B]
Private Sub Prevent_Resizing_Moving_Excel( _
Optional ByVal CenterExcelWindow As Boolean, _
Optional ByVal MakeExcelTopMost As Boolean _
)
Dim tMSG As MSG
Dim tIniWinRect As RECT
Dim tCurWinRect As RECT
Dim tWorkAreaRect As RECT
Dim lCYOffset As Long
Dim bFirstLoop As Boolean
If bMsgsBeingIntercepted Then Exit Sub
bMsgsBeingIntercepted = True
GetWindowRect Application.hwnd, tIniWinRect
Call SystemParametersInfo(SPI_GETWORKAREA, 0, tWorkAreaRect, 0)
lCYOffset = GetSystemMetrics(SM_CYCAPTION) + GetSystemMetrics(SM_CYBORDER) + GetSystemMetrics(SM_CYDLGFRAME) + 2
With tIniWinRect
Call SetWindowPos(Application.hwnd, IIf(MakeExcelTopMost, HWND_TOPMOST, HWND_NOTOPMOST), _
(GetSystemMetrics(SM_CXSCREEN) - (.Right - .Left)) / 2, _
((tWorkAreaRect.Bottom - tWorkAreaRect.Top) - (.Bottom - .Top)) / 2, _
0, 0, SWP_NOSIZE Or IIf(CenterExcelWindow, 0, SWP_NOMOVE))
GetWindowRect Application.hwnd, tIniWinRect
hRgn = CreateRectRgn(.Left, .Top, .Right - GetSystemMetrics(SM_CXSIZE), .Top + lCYOffset)
End With
lStyle = GetWindowLong(Application.hwnd, GWL_STYLE)
lStyle = lStyle And Not (WS_THICKFRAME Or WS_MAXIMIZEBOX Or WS_MINIMIZEBOX)
Call SetWindowLong(Application.hwnd, GWL_STYLE, lStyle)
hwndXLDESK = FindWindowEx(Application.hwnd, 0, "XLDESK", vbNullString)
On Error GoTo errHandler
Application.EnableCancelKey = xlErrorHandler
bCancel = False
Do While GetMessage(tMSG, 0, 0, 0) <> 0
RedrawWindow Application.hwnd, ByVal 0, ByVal 0, RDW_INTERNALPAINT
If bCancel Then Exit Do
If bFirstLoop = False Then
Application.SendKeys "{ESC}", True
DoEvents
Application.SendKeys "{ESC}", True
DoEvents
End If
bFirstLoop = True
Call GetWindowRect(Application.hwnd, tCurWinRect)
If EqualRect(tIniWinRect, tCurWinRect) = 0 Then
With tIniWinRect
Call SetWindowPos(Application.hwnd, 0, (GetSystemMetrics(SM_CXSCREEN) - (.Right - .Left)) / 2, _
((tWorkAreaRect.Bottom - tWorkAreaRect.Top) - (.Bottom - .Top)) / 2, .Right - .Left, .Bottom - .Top, 0)
End With
End If
With tMSG
If WM_NCLBUTTONDOWN Or .message = WM_NCLBUTTONDBLCLK Or .message = WM_NCRBUTTONUP Then
If GetParent(.hwnd) <> hwndXLDESK Then
If PtInRegion(hRgn, tMSG.pt.X, tMSG.pt.Y) Then
GoTo NxtLoop
End If
End If
End If
PostMessage .hwnd, .message, .wParam, .lParam
DoEvents
End With
NxtLoop:
Loop
Application.EnableCancelKey = xlInterrupt
DeleteObject hRgn
Exit Sub
errHandler:
Resume
End Sub
Private Sub Restore_Excel_Default()
bCancel = True
bMsgsBeingIntercepted = False
lStyle = GetWindowLong(Application.hwnd, GWL_STYLE)
lStyle = lStyle Or (WS_THICKFRAME Or WS_MAXIMIZEBOX Or WS_MINIMIZEBOX)
Call SetWindowLong(Application.hwnd, GWL_STYLE, lStyle)
Call SetWindowPos(Application.hwnd, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOSIZE Or SWP_NOMOVE)
End Sub
[B][COLOR=#008000]'Workbook event routines.
'====================[/COLOR][/B]
Private Sub Workbook_Open()
'Any exixting code goes here before calling the 'Restore_Excel_Default' routine !!!
Application.OnTime Now, Me.CodeName & ".Start"
End Sub
Private Sub Workbook_BeforeClose(Cancel As Boolean)
Call Finish
End Sub