Option Explicit
Private Declare Function SetWindowLong Lib "user32.dll" _
Alias "SetWindowLongA" _
(ByVal hwnd As Long, _
ByVal nIndex As Long, _
ByVal dwNewLong As Long) As Long
Public Declare Function CallWindowProc Lib "user32" _
Alias "CallWindowProcA" _
(ByVal lpPrevWndFunc As Long, _
ByVal hwnd As Long, _
ByVal MSG As Long, _
ByVal wParam As Long, _
ByVal lParam As Long) As Long
Private Declare Function FindWindow Lib "user32.dll" _
Alias "FindWindowA" _
(ByVal lpClassName As String, _
ByVal lpWindowName As String) As Long
Private Declare Function GetDesktopWindow Lib _
"user32.dll" () As Long
Private Declare Function ShowWindow Lib "user32.dll" _
(ByVal hwnd As Long, _
ByVal nCmdShow As Long) As Long
Private Declare Function SendMessage Lib "user32.dll" _
Alias "SendMessageA" _
(ByVal hwnd As Long, _
ByVal wMsg As Long, _
ByVal wParam As Long, _
ByRef lParam As Any) As Long
Private Declare Function PostMessage Lib "user32.dll" _
Alias "PostMessageA" _
(ByVal hwnd As Long, _
ByVal wMsg As Long, _
ByVal wParam As Long, ByVal lParam As Long) As Long
Private Declare Function SetTimer Lib "user32.dll" _
(ByVal hwnd As Long, _
ByVal nIDEvent As Long, _
ByVal uElapse As Long, _
ByVal lpTimerFunc As Long) As Long
Private Declare Function KillTimer Lib "user32.dll" _
(ByVal hwnd As Long, _
ByVal nIDEvent As Long) As Long
Private Declare Function LockWindowUpdate Lib "user32.dll" _
(ByVal hwndLock As Long) As Long
Private Declare Function GetProp Lib "user32" _
Alias "GetPropA" _
(ByVal hwnd As Long, _
ByVal lpString As String) As Long
Private Declare Function SetProp Lib "user32" _
Alias "SetPropA" _
(ByVal hwnd As Long, _
ByVal lpString As String, _
ByVal hData As Long) As Long
Private Declare Function RemoveProp Lib "user32" _
Alias "RemovePropA" _
(ByVal hwnd As Long, _
ByVal lpString As String) As Long
Private Const GWL_WNDPROC As Long = -4
Private Const WM_USER As Long = &H400
Public Const WM_ACTIVATEAPP As Long = &H1C
Private Const WM_SETREDRAW As Long = &HB
Private Const VBE_CLASS_NAME As String _
= "wndclass_desked_gsk"
Private Const EXCEL_CLASS_NAME As String _
= "XLMAIN"
Public lOldWinProc As Long
Private lVBEhwnd As Long
Sub Safe_Subclass(hwnd As Long)
'don't subclass the window twice !
If GetProp(GetDesktopWindow, "HWND") <> 0 Then
MsgBox "The Window is already Subclassed.", _
vbInformation
Exit Sub
End If
'store the target window hwnd as a desktop
'window for later use property.
SetProp GetDesktopWindow, "HWND", hwnd
'retrieve the VBE hwnd.
lVBEhwnd = FindWindow(VBE_CLASS_NAME, vbNullString)
'prevent flickering of the screen
'before posting messages to reset
'the VBE window.
LockWindowUpdate lVBEhwnd
'do the same with the desktop in the background.
SendMessage _
GetDesktopWindow, ByVal WM_SETREDRAW, ByVal 0&, 0&
'stop and reset the VBE first to safely
'proceed with our subclassing of xl.
PostMessage _
lVBEhwnd, ByVal WM_USER + &HC44, ByVal &H30, ByVal 0&
PostMessage _
lVBEhwnd, ByVal WM_USER + &HC44, ByVal &H33, ByVal 0&
PostMessage _
lVBEhwnd, ByVal WM_USER + &HC44, ByVal &H83, ByVal 0&
'run a one time timer and subclass xl
'from the timer callback function.
'if subclassing is not installed within
'the timer callback,xl will crash !
SetTimer GetProp(GetDesktopWindow, "HWND") _
, 0&, 1, AddressOf TimerProc
End Sub
Sub UnSubClassWindow(hwnd As Long)
'remove the subclass and cleanup.
SetWindowLong hwnd, GWL_WNDPROC, lOldWinProc
RemoveProp GetDesktopWindow, "HWND"
lOldWinProc = 0
End Sub
Sub TimerProc(ByVal hwnd As Long, ByVal nIDEvent As Long, _
ByVal uElapse As Long, ByVal lpTimerFunc As Long)
'we lost the hwnd stored in the lVBEhwnd var
'after reseting the VBE so let's retrieve it again.
lVBEhwnd = FindWindow(VBE_CLASS_NAME, vbNullString)
'we no longer need the timer.
KillTimer GetProp(GetDesktopWindow, "HWND"), 0&
'allow back drawing on the desktop.
SendMessage GetDesktopWindow, WM_SETREDRAW, ByVal 1, 0&
'hide the VBE.
ShowWindow lVBEhwnd, 0&
'unlock the window update.
LockWindowUpdate 0&
'and at last we can now safely
'subclass our target window.
lOldWinProc = SetWindowLong _
(GetProp(GetDesktopWindow, "HWND"), _
GWL_WNDPROC, AddressOf WindowProc)
End Sub