Option Explicit
Private Type GUID
Data1 As Long
Data2 As Integer
Data3 As Integer
Data4(0 To 7) As Byte
End Type
[URL="https://www.mrexcel.com/forum/usertag.php?do=list&action=hash&hash=If"]#If[/URL] VBA7 Then
Private Declare PtrSafe Function AccessibleObjectFromWindow Lib "Oleacc" (ByVal hWnd As LongPtr, ByVal dwId As Long, ByRef riid As GUID, ByRef ppvObject As Any) As Long
Private Declare PtrSafe Function AccessibleObjectFromPoint Lib "Oleacc" (ByVal arg1 As LongPtr, ppacc As IAccessible, pvarChild As Variant) As Long
Private Declare PtrSafe Function AccessibleChildren Lib "Oleacc" (ByVal paccContainer As Office.IAccessible, ByVal iChildStart As Long, ByVal cChildren As Long, ByRef rgvarChildren As Any, ByRef pcObtained As Long) As Long
Private Declare PtrSafe Function IIDFromString Lib "ole32.dll" (ByVal lpsz As LongPtr, lpiid As GUID) As Long
Private Declare PtrSafe Function SetTimer Lib "user32" (ByVal hWnd As LongPtr, ByVal nIDEvent As LongPtr, ByVal uElapse As Long, ByVal lpTimerFunc As LongPtr) As LongPtr
Private Declare PtrSafe Function KillTimer Lib "user32" (ByVal hWnd As LongPtr, ByVal nIDEvent As LongPtr) As Long
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 GetNextWindow Lib "user32" Alias "GetWindow" (ByVal hWnd As LongPtr, ByVal wFlag As Long) As LongPtr
Private Declare PtrSafe Function GetDesktopWindow Lib "user32" () As LongPtr
Private Declare PtrSafe Function GlobalAddAtom Lib "kernel32" Alias "GlobalAddAtomA" (ByVal lpString As String) As Integer
Private Declare PtrSafe Function GlobalGetAtomName Lib "kernel32" Alias "GlobalGetAtomNameA" (ByVal nAtom As Integer, ByVal lpBuffer As String, ByVal nSize As Long) As Long
Private Declare PtrSafe Function GlobalDeleteAtom Lib "kernel32" (ByVal nAtom As Integer) As Integer
Private Declare PtrSafe Function SetProp Lib "user32" Alias "SetPropA" (ByVal hWnd As LongPtr, ByVal lpString As String, ByVal hData As LongPtr) As Long
Private Declare PtrSafe Function GetProp Lib "user32" Alias "GetPropA" (ByVal hWnd As LongPtr, ByVal lpString As String) As LongPtr
Private Declare PtrSafe Function RemoveProp Lib "user32" Alias "RemovePropA" (ByVal hWnd As LongPtr, ByVal lpString As String) As LongPtr
Private Declare PtrSafe Function CoDisconnectObject Lib "ole32.dll" (ByVal pUnk As IUnknown, pvReserved As Long) As Long
Private Declare PtrSafe Function RegisterActiveObject Lib "oleaut32.dll" (ByVal pUnk As IUnknown, rclsid As Any, ByVal dwFlags As Long, pdwRegister As Long) As Long
Private Declare PtrSafe Function GetActiveObject Lib "OleAut32" (rclsid As Any, ByVal pvReserved As LongPtr, ppunk As Any) As Long
Private Declare PtrSafe Function RevokeActiveObject Lib "oleaut32.dll" (ByVal dwRegister As Long, ByVal pvReserved As Long) As Long
Private Declare PtrSafe Function CLSIDFromString Lib "Ole32" (ByVal lpsz As LongPtr, pclsid As Any) As Long
[URL="https://www.mrexcel.com/forum/usertag.php?do=list&action=hash&hash=Else"]#Else[/URL]
Private Declare Function AccessibleObjectFromWindow Lib "Oleacc" (ByVal hwnd As Long, ByVal dwId As Long, ByRef riid As GUID, ByRef ppvObject As Any) As Long
Private Declare Function AccessibleObjectFromPoint Lib "Oleacc" (ByVal lX As Long, ByVal lY As Long, ppacc As IAccessible, pvarChild As Variant) As Long
Private Declare Function AccessibleChildren Lib "Oleacc" (ByVal paccContainer As Office.IAccessible, ByVal iChildStart As Long, ByVal cChildren As Long, ByRef rgvarChildren As Any, ByRef pcObtained As Long) As Long
Private Declare Function IIDFromString Lib "ole32.dll" (ByVal lpsz As Long, lpiid As GUID) As Long
Private Declare Function SetTimer Lib "user32" (ByVal hwnd As Long, ByVal nIDEvent As Long, ByVal uElapse As Long, ByVal lpTimerFunc As Long) As Long
Private Declare Function KillTimer Lib "user32" (ByVal hwnd As Long, ByVal nIDEvent 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 GetNextWindow Lib "user32" Alias "GetWindow" (ByVal hwnd As Long, ByVal wFlag As Long) As Long
Private Declare Function GetDesktopWindow Lib "user32" () As Long
Private Declare Function GlobalAddAtom Lib "kernel32" Alias "GlobalAddAtomA" (ByVal lpString As String) As Integer
Private Declare Function GlobalGetAtomName Lib "kernel32" Alias "GlobalGetAtomNameA" (ByVal nAtom As Integer, ByVal lpBuffer As String, ByVal nSize As Long) As Long
Private Declare Function GlobalDeleteAtom Lib "kernel32" (ByVal nAtom As Integer) As Integer
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 GetProp Lib "user32" Alias "GetPropA" (ByVal hWnd As Long, ByVal lpString As String) As Long
Private Declare Function RemoveProp Lib "user32" Alias "RemovePropA" (ByVal hWnd As Long, ByVal lpString As String) As Long
Private Declare Function CoDisconnectObject Lib "ole32.dll" (ByVal pUnk As IUnknown, pvReserved As Long) As Long
Private Declare Function RegisterActiveObject Lib "oleaut32.dll" (ByVal pUnk As IUnknown, rclsid As Any, ByVal dwFlags As Long, pdwRegister As Long) As Long
Private Declare Function GetActiveObject Lib "OleAut32" (rclsid As Any, ByVal pvReserved As Long, ppunk As Any) As Long
Private Declare Function RevokeActiveObject Lib "oleaut32.dll" (ByVal dwRegister As Long, ByVal pvReserved As Long) As Long
Private Declare Function CLSIDFromString Lib "Ole32" (ByVal lpsz As Long, pclsid As Any) As Long
[URL="https://www.mrexcel.com/forum/usertag.php?do=list&action=hash&hash=End"]#End[/URL] If
Public Function PrintWhat() As String
Dim Atom_ID As Integer, lRet As Long, sBuffer As String * 256
Atom_ID = CInt(GetProp(GetDesktopWindow, "PrintArea_String"))
lRet = GlobalGetAtomName(Atom_ID, sBuffer, Len(sBuffer))
PrintWhat = Left(sBuffer, lRet)
End Function
Public Sub CreateHiddenInstance()
Dim Atom_ID As Integer, lRet As Long, Wb As Workbook, oXl As Excel.Application
If Not ThisWorkbook.ReadOnly Then
Call DeleteHiddenInstance
If GetProp(GetDesktopWindow, "SourceXlHwnd_String") = 0 Then
Set oXl = New Application
'oXl.Visible = True '<== For Testing
oXl.EnableEvents = False
Set Wb = oXl.Workbooks.Open(ThisWorkbook.FullName, False, True)
Atom_ID = GlobalAddAtom(Application.hWnd)
SetProp GetDesktopWindow, "SourceXlHwnd_String", Atom_ID
Call oXl.Run("StartTimerFromHiddenInstance")
End If
End If
End Sub
Public Sub DeleteHiddenInstance()
Dim pUnk As IUnknown, Wb As Workbook, ClassID(0 To 3) As Long
Dim Atom_ID As Integer, lRet As Long, sBuffer As String * 256
If Not ThisWorkbook.ReadOnly And GetProp(GetDesktopWindow, "SourceXlHwnd_String") Then
Call CoDisconnectObject(ThisWorkbook, 0)
Call RevokeActiveObject(CLng(GetProp(GetDesktopWindow, "OleId")), 0)
Call CLSIDFromString(StrPtr("{88D97E8B-D351-4FF4-A8EB-BF18EDD35267}"), ClassID(0))
Call GetActiveObject(ClassID(0), 0, pUnk)
Set Wb = pUnk
Set pUnk = Nothing
If Not Wb Is Nothing Then
On Error Resume Next
Call Wb.Parent.Run("StopTimerFromHiddenInstance")
Wb.Saved = True: Wb.Parent.Quit: Set Wb = Nothing
End If
Atom_ID = CInt(GetProp(GetDesktopWindow, "SourceXlHwnd_String"))
Call GlobalDeleteAtom(Atom_ID)
Atom_ID = CInt(GetProp(GetDesktopWindow, "PrintArea_String"))
Call GlobalDeleteAtom(Atom_ID)
Call RemoveProp(GetDesktopWindow, "OleId")
Call RemoveProp(GetDesktopWindow, "SourceXlHwnd_String")
Call RemoveProp(GetDesktopWindow, "PrintArea_String")
End If
End Sub
[B][COLOR=#008000]'Hidden Instance routines:[/COLOR][/B]
[B][COLOR=#008000]'========================[/COLOR][/B]
Private Sub StartTimerFromHiddenInstance()
Dim ClassID(0 To 3) As Long, lOleId As Long
If GetProp(GetDesktopWindow, "OleId") = 0 Then
Call CLSIDFromString(StrPtr("{88D97E8B-D351-4FF4-A8EB-BF18EDD35267}"), ClassID(0))
Call RegisterActiveObject(ThisWorkbook, ClassID(0), 0, lOleId)
Call SetProp(GetDesktopWindow, "OleId", lOleId)
Call SetTimer(Application.hWnd, 0, 100, AddressOf TimerProc)
End If
End Sub
Private Sub StopTimerFromHiddenInstance()
Call KillTimer(Application.hWnd, 0)
Call RemoveProp(GetDesktopWindow, "OleId")
Call RemoveProp(GetDesktopWindow, "SourceXlHwnd_String")
Call RemoveProp(GetDesktopWindow, "PrintArea_String")
'Debug.Print "Timer stopped" '<== For Testing
End Sub
Private Sub TimerProc()
Const CHILDID_SELF = &H0&
Const OBJID_CLIENT = &HFFFFFFFC
Const IID_IAccessible = "{618736E0-3C3D-11CF-810C-00AA00389B71}"
[URL="https://www.mrexcel.com/forum/usertag.php?do=list&action=hash&hash=If"]#If[/URL] VBA7 Then
Dim hWnd As LongPtr
[URL="https://www.mrexcel.com/forum/usertag.php?do=list&action=hash&hash=Else"]#Else[/URL]
Dim hWnd As Long
[URL="https://www.mrexcel.com/forum/usertag.php?do=list&action=hash&hash=End"]#End[/URL] If
Dim oAccNetUIHWND As IAccessible, oIAccPrintWhat As IAccessible, vCopiesField As Variant
Dim lLeft As Long, lTop As Long, lWidth As Long, lHeight As Long
Dim Atom_ID As Integer, lRet As Long, sBuffer As String * 256
Dim IID As GUID
On Error Resume Next
If ThisWorkbook.ReadOnly And GetProp(GetDesktopWindow, "SourceXlHwnd_String") Then
Atom_ID = CInt(GetProp(GetDesktopWindow, "SourceXlHwnd_String"))
lRet = GlobalGetAtomName(Atom_ID, sBuffer, Len(sBuffer))
hWnd = FindWindowEx(Left(sBuffer, lRet), 0, "FullpageUIHost", vbNullString)
hWnd = GetNextWindow(hWnd, 5): hWnd = GetNextWindow(hWnd, 5)
Call IIDFromString(StrPtr(IID_IAccessible), IID)
Call AccessibleObjectFromWindow(hWnd, OBJID_CLIENT, IID, oAccNetUIHWND)
Call AccessibleChildren(oAccNetUIHWND, 0, 1, vCopiesField, 1)
Call vCopiesField.accLocation(lLeft, lTop, lWidth, lHeight, CHILDID_SELF)
[URL="https://www.mrexcel.com/forum/usertag.php?do=list&action=hash&hash=If"]#If[/URL] VBA7 Then
Dim lngPtr As LongPtr
Dim arPt(0 To 1) As Long
arPt(0) = lLeft: arPt(1) = lTop + (lHeight * 15)
lngPtr = arPt(1) * &H100000000^ Or arPt(0)
Call AccessibleObjectFromPoint(lngPtr, oIAccPrintWhat, 0)
[URL="https://www.mrexcel.com/forum/usertag.php?do=list&action=hash&hash=Else"]#Else[/URL]
Call AccessibleObjectFromPoint(lLeft, lTop + (lHeight * 15), oIAccPrintWhat, 0)
[URL="https://www.mrexcel.com/forum/usertag.php?do=list&action=hash&hash=End"]#End[/URL] If
Atom_ID = GlobalAddAtom(oIAccPrintWhat.accValue(CHILDID_SELF))
SetProp GetDesktopWindow, "PrintArea_String", Atom_ID
End If
End Sub