Option Explicit
Private Type GUID
lData1 As Long
iData2 As Integer
iData3 As Integer
iData4(0 To 7) As Byte
End Type
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 PtInRect Lib "user32" (lpRect As RECT, ByVal arg2 As LongPtr) As Long
Private Declare PtrSafe Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal Length As LongPtr)
#Else
Private Declare PtrSafe Function PtInRect Lib "user32" (lpRect As RECT, ByVal arg1 As Long, ByVal arg2 As Long) As Long
#End If
Private Declare PtrSafe Function FindWindow Lib "user32" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As LongPtr
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 SetRect Lib "user32" (lpRect As RECT, ByVal X1 As Long, ByVal Y1 As Long, ByVal X2 As Long, ByVal Y2 As Long) As Long
Private Declare PtrSafe Function GetAsyncKeyState Lib "user32" (ByVal vKey As Long) As Integer
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 AccessibleObjectFromWindow Lib "OLEACC.DLL" (ByVal hwnd As LongPtr, ByVal dwId As Long, ByVal riid As LongPtr, ppvObject As Any) As Long
Private Declare PtrSafe Function IIDFromString Lib "ole32.dll" (ByVal lpsz As LongPtr, ByVal lpiid As LongPtr) As LongPtr
Private Declare PtrSafe Function GetAncestor Lib "user32" (ByVal hwnd As LongPtr, ByVal gaFlags As Long) As LongPtr
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 Declare PtrSafe Function GetWindowRect Lib "user32" (ByVal hwnd As LongPtr, lpRect As RECT) As Long
Private Declare PtrSafe Function ShowWindow Lib "user32" (ByVal hwnd As LongPtr, ByVal nCmdShow As Long) As Long
Private Declare PtrSafe Function InvalidateRect Lib "user32" (ByVal hwnd As LongPtr, ByVal lpRect As Long, ByVal bErase As Long) As Long
Private Declare PtrSafe Function SendMessage Lib "user32" Alias "SendMessageA" (ByVal hwnd As LongPtr, ByVal wMsg As Long, ByVal wParam As LongPtr, lParam As Any) As LongPtr
Private Declare PtrSafe Function IsWindow Lib "user32" (ByVal hwnd As LongPtr) As Long
Private Declare PtrSafe Function SetCursorPos Lib "user32" (ByVal X As Long, ByVal Y As Long) As Long
Private Declare PtrSafe Function GetCursorPos Lib "user32.dll" (lpPoint As POINTAPI) As Long
Private Declare PtrSafe Function SetFocus Lib "user32" (ByVal hwnd As LongPtr) As LongPtr
#Else
Private Declare Function PtInRect Lib "user32" (lpRect As RECT, ByVal arg1 As Long, ByVal arg2 As Long) As Long
Private Declare Function FindWindow Lib "user32" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) 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 SetRect Lib "user32" (lpRect As RECT, ByVal X1 As Long, ByVal Y1 As Long, ByVal X2 As Long, ByVal Y2 As Long) As Long
Private Declare Function GetAsyncKeyState Lib "user32" (ByVal vKey As Long) As Integer
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 AccessibleObjectFromWindow Lib "OLEACC.DLL" (ByVal hwnd As Long, ByVal dwId As Long, ByVal riid As Long, ppvObject As Any) As Long
Private Declare Function IIDFromString Lib "ole32.dll" (ByVal lpsz As Long, ByVal lpiid As Long) As Long
Private Declare Function GetAncestor Lib "user32" (ByVal hwnd As Long, ByVal gaFlags 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 Declare Function GetWindowRect Lib "user32" (ByVal hwnd As Long, lpRect As RECT) As Long
Private Declare Function ShowWindow Lib "user32" (ByVal hwnd As Long, ByVal nCmdShow As Long) As Long
Private Declare Function InvalidateRect Lib "user32" (ByVal hwnd As Long, ByVal lpRect As Long, ByVal bErase As Long) As Long
Private Declare Function SendMessage Lib "user32" Alias "SendMessageA" (ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, lParam As Any) As Long
Private Declare Function IsWindow Lib "user32" (ByVal hwnd As Long) As Long
Private Declare Function SetCursorPos Lib "user32" (ByVal X As Long, ByVal Y As Long) As Long
Private Declare Function GetCursorPos Lib "user32.dll" (lpPoint As POINTAPI) As Long
Private Declare Function SetFocus Lib "user32" (ByVal hwnd As Long) As Long
#End If
Private Const ID_ACCESSIBLE As String = "{618736E0-3C3D-11CF-810C-00AA00389B71}"
Private Const CHILDID_SELF = &H0&
Private Const OBJID_SELF = &H0&
Private Const NAVDIR_FIRSTCHILD = &H7&
Private Const NAVDIR_DOWN = &H2&
Private Const S_OK = &H0
Private Const SWP_NOSIZE = &H1
Private Const SWP_NOACTIVATE = &H10
Private Const SWP_SHOWWINDOW = &H40
Private Const WM_SETREDRAW = &HB
Private Const GA_PARENT = 1
Private Const GA_ROOT = 2
Private lInitCurX As Long, lInitCurY As Long
Private lTempCurX As Long, lTempCurY As Long
Private sSelectedSheet As String
Public Sub Center_Sheets_List_Dialog()
If ActiveWorkbook.Sheets.Count < 17 Then
SetFocus GetAncestor(Application.hwnd, GA_ROOT)
SetTimer Application.hwnd, Application.hwnd, 0, AddressOf SetListPos
SendMessage GetAncestor(Application.hwnd, GA_PARENT), ByVal WM_SETREDRAW, ByVal 0, 0
Application.CommandBars("Workbook Tabs").ShowPopup
Else
SetTimer Application.hwnd, 0, 0, AddressOf SetListPos
Application.CommandBars("Workbook Tabs").Controls(16).Execute
If Len(sSelectedSheet) Then Worksheets(sSelectedSheet).Activate
End If
End Sub
#If VBA7 Then
Private Sub SetListPos(ByVal hwnd As LongPtr, ByVal MSG As Long, ByVal nIDEvent As LongPtr, ByVal dwTimer As Long)
Dim hPopUp As LongPtr
#Else
Private Sub SetListPos(ByVal hwnd As Long, ByVal MSG As Long, ByVal nIDEvent As Long, ByVal dwTimer As Long)
Dim hPopUp As Long
#End If
'***************************
Dim tRectApp As RECT, tRectPopUp As RECT
Dim cxChild As Long, cyChild As Long, cxParent As Long, cyParent As Long
Dim X As Long, Y As Long
Dim sCaption As String, iLCID As Integer
Dim oCtrl As IAccessible
'*****************************************
Dim tGUID(0 To 3) As Long
Dim oIAcc As IAccessible
Dim oIAccChild As IAccessible
Dim vFocus As Variant
Dim vAcc As Variant
Dim tCursPos As POINTAPI
Dim tOKRect As RECT, tCancelRect As RECT, tListRect As RECT, tXbuttonRect As RECT
Dim lLeft As Long, lTop As Long, lWidth As Long, lHeight As Long
Dim bCancel As Boolean
'*******************************************
On Error Resume Next
KillTimer hwnd, nIDEvent
iLCID = Application.LanguageSettings.LanguageID(msoLanguageIDInstall)
Select Case iLCID
Case 1033, 3081, 10249, 4105, 6153, 8201, 5129, 7177, 11273, 2057
sCaption = "Activate" 'english
Case 2060, 3084, 5132, 4108, 1036
sCaption = "Activer" 'french
Case 1034, 11274, 16394, 13322, 9226, 5130, 7178, 12298, 4106, 18442, 2058, 19466, 6154, 10250, 20490, 15370, 17418, 8202
sCaption = "Activar" 'spanish
End Select
hPopUp = IIf(nIDEvent = hwnd, FindWindow("MsoCommandBarPopup", vbNullString), FindWindow("bosa_sdm_XL9", sCaption))
'Set the position of the workbook tabs Commandbar Pop-Up or Dialog at the center of the excel window.
'***************************************************************************************************
If hPopUp Then
GetWindowRect hwnd, tRectApp
GetWindowRect hPopUp, tRectPopUp
With tRectPopUp
cxChild = .Right - .Left
cyChild = .Bottom - .Top
End With
With tRectApp
cxParent = .Right - .Left
cyParent = .Bottom - .Top
End With
X = tRectApp.Left + (cxParent - cxChild) / 2
Y = tRectApp.Top + (cyParent - cyChild) / 2
If nIDEvent = hwnd Then
ShowWindow hPopUp, 0
SendMessage GetAncestor(hwnd, GA_PARENT), ByVal WM_SETREDRAW, ByVal 1&, 0&
InvalidateRect 0, 0, 0
For Each oCtrl In Application.CommandBars("Workbook Tabs").Controls
If oCtrl.accState(CHILDID_SELF) = &H100010 Then
oCtrl.accSelect 1, CHILDID_SELF
Exit For
End If
Next
End If
SetWindowPos hPopUp, 0, X, Y, 0, 0, SWP_NOSIZE Or SWP_SHOWWINDOW + SWP_NOACTIVATE
End If
'Handle special case when there are more than 16 sheets and the Workbooks tab Dialog is shown.
'********************************************************************************************
If FindWindow("bosa_sdm_XL9", sCaption) Then
If IIDFromString(StrPtr(ID_ACCESSIBLE), VarPtr(tGUID(0))) = S_OK Then
If AccessibleObjectFromWindow(hPopUp, OBJID_SELF, VarPtr(tGUID(0)), oIAcc) = S_OK Then
Set vAcc = oIAcc
Set oIAccChild = vAcc.accNavigate(NAVDIR_FIRSTCHILD, CHILDID_SELF)
Set oIAccChild = oIAccChild.accNavigate(NAVDIR_DOWN, CHILDID_SELF)
AccessibleChildren vAcc, 1, 1, vAcc, 1
oIAccChild.accChild(4&).accLocation lLeft, lTop, lWidth, lHeight, CHILDID_SELF
SetRect tListRect, lLeft, lTop, lWidth + lLeft, lHeight + lTop
GetCursorPos tCursPos
lInitCurX = tCursPos.X: lInitCurY = tCursPos.Y
lTempCurX = lLeft + 40: lTempCurY = lTop + 40
'brively move the mouse pointer over the dialog and back... needed to trigger 'accHitTest' !!
SetTimer Application.hwnd, 0, 0, AddressOf MoveCursor
Do While IsWindow(hPopUp)
'Store the dialog tabs List Rect.
Call oIAccChild.accChild(4&).accLocation(lLeft, lTop, lWidth, lHeight, CHILDID_SELF)
SetRect tListRect, lLeft, lTop, lWidth + lLeft, lHeight + lTop
'Store the dialog X-Close Menu Rect.
vAcc.accLocation lLeft, lTop, lWidth, lHeight, 5&
SetRect tXbuttonRect, lLeft, lTop, lLeft + lWidth, lTop + lHeight
GetCursorPos tCursPos
If Err.Number = 0 And TypeName(vFocus.accFocus) <> "Empty" And _
TypeName(vFocus.accFocus) <> "IAccessible" Then
Set vFocus = oIAcc.accHitTest(tCursPos.X, tCursPos.Y)
End If
If vFocus.accFocus = 1 Then 'OK button has the focus.
sSelectedSheet = oIAccChild.accChild(4&).accValue
bCancel = False
ElseIf vFocus.accFocus = 2 Then 'Cancel button has the focus.
bCancel = True
End If
'Dialog closed via ESC key or ALT+F4.
If (GetAsyncKeyState(vbKeyEscape) <> 0) _
Or (GetAsyncKeyState(vbKeyF4) <> 0) Then
bCancel = True
End If
'Dialog closed via the X-close menu.
#If VBA7 Then
#If Win64 Then
Dim lngPtr As LongPtr
CopyMemory lngPtr, tCursPos, LenB(tCursPos)
If PtInRect(tXbuttonRect, lngPtr) _
And (GetAsyncKeyState(vbKeyLButton) <> 0) Then
bCancel = True
End If
#Else
If PtInRect(tXbuttonRect, tCursPos.X, tCursPos.Y) _
And (GetAsyncKeyState(vbKeyLButton) <> 0) Then
bCancel = True
End If
#End If
#Else
If PtInRect(tXbuttonRect, tCursPos.X, tCursPos.Y) _
And (GetAsyncKeyState(vbKeyLButton) <> 0) Then
bCancel = True
End If
#End If
DoEvents
Loop
End If
End If
End If
Xit:
SendMessage GetAncestor(hwnd, GA_PARENT), ByVal WM_SETREDRAW, ByVal 1&, 0&
If bCancel Then sSelectedSheet = ""
End Sub
Private Sub RestoreCursorPos()
KillTimer Application.hwnd, 0
Call SetCursorPos(lInitCurX, lInitCurY)
End Sub
Private Sub MoveCursor()
KillTimer Application.hwnd, 0
Call SetCursorPos(lTempCurX, lTempCurY)
SetTimer Application.hwnd, 0, 0, AddressOf RestoreCursorPos
End Sub