Private Type POINTAPI
End Type
Private Type RECT
End Type
Private Type MOUSEHOOKSTRUCT
pt As POINTAPI
End Type
Private Declare PtrSafe Function SetWindowsHookEx Lib
"user32" Alias
"SetWindowsHookExA" ( ByVal idHook As
Long , ByVal lpfn As LongPtr, ByVal hmod As LongPtr, ByVal dwThreadId As
Long ) As LongPtr
Private Declare PtrSafe Function CallNextHookEx Lib
"user32" ( ByVal hHook As
Long , ByVal nCode As
Long , ByVal wParam As
Long , lParam As
Any ) As
Long
Private Declare PtrSafe Function UnhookWindowsHookEx Lib
"user32" ( ByVal hhk As LongPtr
) As
Long
Private Declare PtrSafe Function GetDeviceCaps Lib
"gdi32" ( ByVal hdc As
Long , ByVal nIndex As
Long ) As
Long
Private Declare PtrSafe Function GetDC Lib
"user32" ( ByVal hwnd As
Long ) As
Long
Private Declare PtrSafe Function ReleaseDC Lib
"user32" ( ByVal hwnd As
Long , ByVal hdc As
Long ) As
Long
Private Declare PtrSafe Function PtInRect Lib
"user32" ( lpRect As RECT, ByVal X As
Long , ByVal Y As
Long ) As
Long
Private Declare PtrSafe Function ClientToScreen Lib
"user32" ( ByVal hwnd As
Long , lpPoint As POINTAPI
) As
Long
Private Declare PtrSafe Function GetClientRect Lib
"user32" ( ByVal hwnd As
Long , lpRect As RECT
) As
Long
Private Declare PtrSafe Function GetActiveWindow Lib
"user32" ( ) 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 Const WH_MOUSE_LL As
Long = 14
Private Const WM_MOUSEWHEEL As
Long = & H20A
Private Const HC_ACTION As
Long = 0
Private Const POINTSPERINCH As
Long = 72
Private Const LOGPIXELSX As
Long = 88
Private Const LOGPIXELSY As
Long = 90
Private Const SCROLL_CHANGE As
Long = 5
Private lMouseHook As
Long
Private lFormHwnd As
Long
Private oScrollableObject As
Object
Public Sub SetScrollHook
( ByVal ScrollableObject As
Object )
If Not ( IsObjectUserForm( ScrollableObject) Or TypeName( ScrollableObject) = "Frame" ) Then Exit Sub
Set oScrollableObject
= ScrollableObject
lFormHwnd = GetActiveWindow
With ScrollableObject
.ScrollBars = fmScrollBarsBoth
.KeepScrollBarsVisible = fmScrollBarsBoth
.PictureAlignment = fmPictureAlignmentTopLeft
' Adjust the values of the scroll width and height properties as required
.ScrollWidth = ScrollableObject.InsideWidth * 3
.ScrollHeight = ScrollableObject.InsideHeight * 2
End With
If Not bHookIsSet Then
lMouseHook = SetWindowsHookEx( _
WH_MOUSE_LL, AddressOf MouseProc, Application.Hinstance, 0)
bHookIsSet = lMouseHook <> 0
End If
End Sub
Public Sub RemoveScrollHook(Optional ByVal Dummy As Boolean)
If bHookIsSet Then
UnhookWindowsHookEx lMouseHook
lMouseHook = 0
bHookIsSet = False
End If
End Sub
Private Function MouseProc(ByVal nCode As Long, ByVal wParam As Long, ByRef lParam As MOUSEHOOKSTRUCT) As Long
Dim tTopLeft As POINTAPI
Dim tBottomRight As POINTAPI
Dim tRect As RECT
GetClientRect lFormHwnd, tRect
With oScrollableObject
If IsObjectUserForm(oScrollableObject) Then
tTopLeft.X = tRect.Left
tTopLeft.Y = tRect.Top
tBottomRight.X = tRect.Right
tBottomRight.Y = tRect.Bottom
Else
tTopLeft.X = PTtoPX(.Left, False) + tRect.Left
tTopLeft.Y = PTtoPX(.Top, True) + tRect.Top
tBottomRight.X = PTtoPX(.Left + .Width, False) + tRect.Left
tBottomRight.Y = PTtoPX(.Top + .Height, True) + tRect.Top
End If
End With
ClientToScreen lFormHwnd, tTopLeft
ClientToScreen lFormHwnd, tBottomRight
SetRect tRect, tTopLeft.X, tTopLeft.Y, tBottomRight.X, tBottomRight.Y
On Error GoTo errH
If (nCode = HC_ACTION) And CBool(PtInRect(tRect, lParam.pt.X, lParam.pt.Y)) Then
If wParam = WM_MOUSEWHEEL Then
With oScrollableObject
Select Case GetAsyncKeyState(VBA.vbKeyControl)
Case Is = 0 ' vertical scroll
If lParam.hwnd > 0 Then
.ScrollTop = Application.Max ( 0 , .ScrollTop - SCROLL_CHANGE)
Else
.ScrollTop = Application.Min ( .ScrollHeight - .InsideHeight , .ScrollTop + SCROLL_CHANGE)
End If
Case Else ' horiz scroll when the Ctl key down
If lParam.hwnd > 0 Then
.ScrollLeft = Application.Max(0, .ScrollLeft - SCROLL_CHANGE)
Else
.ScrollLeft = Application.Min(.ScrollWidth - .InsideWidth, .ScrollLeft + SCROLL_CHANGE)
End If
End Select
End With
End If
End If
MouseProc = CallNextHookEx( _
lMouseHook, nCode, wParam, ByVal lParam)
Exit Function
errH:
RemoveScrollHook
End Function
Private Function ScreenDPI(bVert As Boolean) As Long
Static lDPI(1), lDC
If lDPI(0) = 0 Then
lDC = GetDC(0)
lDPI(0) = GetDeviceCaps(lDC, LOGPIXELSX)
lDPI(1) = GetDeviceCaps(lDC, LOGPIXELSY)
lDC = ReleaseDC(0, lDC)
End If
ScreenDPI = lDPI(Abs(bVert))
End Function
Private Function PTtoPX _
(Points As Single, bVert As Boolean) As Long
PTtoPX = Points * ScreenDPI(bVert) / POINTSPERINCH
End Function
Private Function IsObjectUserForm(ByVal obj As Object) As Boolean
Dim oTemp As Object
On Error Resume Next
Set oTemp = obj.Parent
Set oTemp = Nothing
IsObjectUserForm = Err.Number = 438
On Error GoTo 0
End Function
T3B0aW9uIEV4cGxpY2l0CgogCgpQcml2YXRlIFR5cGUgUE9JTlRBUEkKCiAgICBYIEFzIExvbmcKCiAgICBZIEFzIExvbmcKCkVuZCBUeXBlCgpQcml2YXRlIFR5cGUgUkVDVAoKICAgIExlZnQgQXMgTG9uZwoKICAgIFRvcCBBcyBMb25nCgogICAgUmlnaHQgQXMgTG9uZwoKICAgIEJvdHRvbSBBcyBMb25nCgpFbmQgVHlwZQoKUHJpdmF0ZSBUeXBlIE1PVVNFSE9PS1NUUlVDVAoKICAgIHB0IEFzIFBPSU5UQVBJCgogICAgaHduZCBBcyBMb25nCgogICAgd0hpdFRlc3RDb2RlIEFzIExvbmcKCiAgICBkd0V4dHJhSW5mbyBBcyBMb25nCgpFbmQgVHlwZQoKIAoKUHJpdmF0ZSBEZWNsYXJlIFB0clNhZmUgRnVuY3Rpb24gU2V0V2luZG93c0hvb2tFeCBMaWIgInVzZXIzMiIgQWxpYXMgIlNldFdpbmRvd3NIb29rRXhBIiAoQnlWYWwgaWRIb29rIEFzIExvbmcsIEJ5VmFsIGxwZm4gQXMgTG9uZ1B0ciwgQnlWYWwgaG1vZCBBcyBMb25nUHRyLCBCeVZhbCBkd1RocmVhZElkIEFzIExvbmcpIEFzIExvbmdQdHIKClByaXZhdGUgRGVjbGFyZSBQdHJTYWZlIEZ1bmN0aW9uIENhbGxOZXh0SG9va0V4IExpYiAidXNlcjMyIiAoQnlWYWwgaEhvb2sgQXMgTG9uZywgQnlWYWwgbkNvZGUgQXMgTG9uZywgQnlWYWwgd1BhcmFtIEFzIExvbmcsIGxQYXJhbSBBcyBBbnkpIEFzIExvbmcKClByaXZhdGUgRGVjbGFyZSBQdHJTYWZlIEZ1bmN0aW9uIFVuaG9va1dpbmRvd3NIb29rRXggTGliICJ1c2VyMzIiIChCeVZhbCBoaGsgQXMgTG9uZ1B0cikgQXMgTG9uZwoKUHJpdmF0ZSBEZWNsYXJlIFB0clNhZmUgRnVuY3Rpb24gR2V0RGV2aWNlQ2FwcyBMaWIgImdkaTMyIiAoQnlWYWwgaGRjIEFzIExvbmcsIEJ5VmFsIG5JbmRleCBBcyBMb25nKSBBcyBMb25nCgpQcml2YXRlIERlY2xhcmUgUHRyU2FmZSBGdW5jdGlvbiBHZXREQyBMaWIgInVzZXIzMiIgKEJ5VmFsIGh3bmQgQXMgTG9uZykgQXMgTG9uZwoKUHJpdmF0ZSBEZWNsYXJlIFB0clNhZmUgRnVuY3Rpb24gUmVsZWFzZURDIExpYiAidXNlcjMyIiAoQnlWYWwgaHduZCBBcyBMb25nLCBCeVZhbCBoZGMgQXMgTG9uZykgQXMgTG9uZwoKUHJpdmF0ZSBEZWNsYXJlIFB0clNhZmUgRnVuY3Rpb24gUHRJblJlY3QgTGliICJ1c2VyMzIiIChscFJlY3QgQXMgUkVDVCwgQnlWYWwgWCBBcyBMb25nLCBCeVZhbCBZIEFzIExvbmcpIEFzIExvbmcKClByaXZhdGUgRGVjbGFyZSBQdHJTYWZlIEZ1bmN0aW9uIENsaWVudFRvU2NyZWVuIExpYiAidXNlcjMyIiAoQnlWYWwgaHduZCBBcyBMb25nLCBscFBvaW50IEFzIFBPSU5UQVBJKSBBcyBMb25nCgpQcml2YXRlIERlY2xhcmUgUHRyU2FmZSBGdW5jdGlvbiBHZXRDbGllbnRSZWN0IExpYiAidXNlcjMyIiAoQnlWYWwgaHduZCBBcyBMb25nLCBscFJlY3QgQXMgUkVDVCkgQXMgTG9uZwoKUHJpdmF0ZSBEZWNsYXJlIFB0clNhZmUgRnVuY3Rpb24gR2V0QWN0aXZlV2luZG93IExpYiAidXNlcjMyIiAoKSBBcyBMb25nCgpQcml2YXRlIERlY2xhcmUgUHRyU2FmZSBGdW5jdGlvbiBTZXRSZWN0IExpYiAidXNlcjMyIiAobHBSZWN0IEFzIFJFQ1QsIEJ5VmFsIFgxIEFzIExvbmcsIEJ5VmFsIFkxIEFzIExvbmcsIEJ5VmFsIFgyIEFzIExvbmcsIEJ5VmFsIFkyIEFzIExvbmcpIEFzIExvbmcKClByaXZhdGUgRGVjbGFyZSBQdHJTYWZlIEZ1bmN0aW9uIEdldEFzeW5jS2V5U3RhdGUgTGliICJ1c2VyMzIiIChCeVZhbCB2S2V5IEFzIExvbmcpIEFzIEludGVnZXIKCiAKClByaXZhdGUgQ29uc3QgV0hfTU9VU0VfTEwgQXMgTG9uZyA9IDE0CgpQcml2YXRlIENvbnN0IFdNX01PVVNFV0hFRUwgQXMgTG9uZyA9ICZIMjBBCgpQcml2YXRlIENvbnN0IEhDX0FDVElPTiBBcyBMb25nID0gMAoKUHJpdmF0ZSBDb25zdCBQT0lOVFNQRVJJTkNIIEFzIExvbmcgPSA3MgoKUHJpdmF0ZSBDb25zdCBMT0dQSVhFTFNYIEFzIExvbmcgPSA4OAoKUHJpdmF0ZSBDb25zdCBMT0dQSVhFTFNZIEFzIExvbmcgPSA5MAoKUHJpdmF0ZSBDb25zdCBTQ1JPTExfQ0hBTkdFIEFzIExvbmcgPSA1CgogCgpQcml2YXRlIGxNb3VzZUhvb2sgQXMgTG9uZwoKUHJpdmF0ZSBsRm9ybUh3bmQgQXMgTG9uZwoKUHJpdmF0ZSBiSG9va0lzU2V0IEFzIEJvb2xlYW4KClByaXZhdGUgb1Njcm9sbGFibGVPYmplY3QgQXMgT2JqZWN0CgogCgogCgpQdWJsaWMgU3ViIFNldFNjcm9sbEhvb2soQnlWYWwgU2Nyb2xsYWJsZU9iamVjdCBBcyBPYmplY3QpCgogICAgSWYgTm90IChJc09iamVjdFVzZXJGb3JtKFNjcm9sbGFibGVPYmplY3QpIE9yIFR5cGVOYW1lKFNjcm9sbGFibGVPYmplY3QpID0gIkZyYW1lIikgVGhlbiBFeGl0IFN1YgoKICAgIFNldCBvU2Nyb2xsYWJsZU9iamVjdCA9IFNjcm9sbGFibGVPYmplY3QKCiAgICBsRm9ybUh3bmQgPSBHZXRBY3RpdmVXaW5kb3cKCiAgICBXaXRoIFNjcm9sbGFibGVPYmplY3QKCiAgICAgICAgLlNjcm9sbEJhcnMgPSBmbVNjcm9sbEJhcnNCb3RoCgogICAgICAgIC5LZWVwU2Nyb2xsQmFyc1Zpc2libGUgPSBmbVNjcm9sbEJhcnNCb3RoCgogICAgICAgIC5QaWN0dXJlQWxpZ25tZW50ID0gZm1QaWN0dXJlQWxpZ25tZW50VG9wTGVmdAoKICAgICAgICAnIEFkanVzdCB0aGUgdmFsdWVzIG9mIHRoZSBzY3JvbGwgd2lkdGggYW5kIGhlaWdodCBwcm9wZXJ0aWVzIGFzIHJlcXVpcmVkCgogICAgICAgIC5TY3JvbGxXaWR0aCA9IFNjcm9sbGFibGVPYmplY3QuSW5zaWRlV2lkdGggKiAzCgogICAgICAgIC5TY3JvbGxIZWlnaHQgPSBTY3JvbGxhYmxlT2JqZWN0Lkluc2lkZUhlaWdodCAqIDIKCiAgICBFbmQgV2l0aAoKICAgIElmIE5vdCBiSG9va0lzU2V0IFRoZW4KCiAgICAgICAgbE1vdXNlSG9vayA9IFNldFdpbmRvd3NIb29rRXgoIF8KCiAgICAgICAgV0hfTU9VU0VfTEwsIEFkZHJlc3NPZiBNb3VzZVByb2MsIEFwcGxpY2F0aW9uLkhpbnN0YW5jZSwgMCkKCiAgICAgICAgYkhvb2tJc1NldCA9IGxNb3VzZUhvb2sgPD4gMAoKICAgIEVuZCBJZgoKRW5kIFN1YgoKIAoKUHVibGljIFN1YiBSZW1vdmVTY3JvbGxIb29rKE9wdGlvbmFsIEJ5VmFsIER1bW15IEFzIEJvb2xlYW4pCgogICAgSWYgYkhvb2tJc1NldCBUaGVuCgogICAgICAgIFVuaG9va1dpbmRvd3NIb29rRXggbE1vdXNlSG9vawoKICAgICAgICBsTW91c2VIb29rID0gMAoKICAgICAgICBiSG9va0lzU2V0ID0gRmFsc2UKCiAgICBFbmQgSWYKCkVuZCBTdWIKCiAKClByaXZhdGUgRnVuY3Rpb24gTW91c2VQcm9jKEJ5VmFsIG5Db2RlIEFzIExvbmcsIEJ5VmFsIHdQYXJhbSBBcyBMb25nLCBCeVJlZiBsUGFyYW0gQXMgTU9VU0VIT09LU1RSVUNUKSBBcyBMb25nCgogCgogICAgRGltIHRUb3BMZWZ0IEFzIFBPSU5UQVBJCgogICAgRGltIHRCb3R0b21SaWdodCBBcyBQT0lOVEFQSQoKICAgIERpbSB0UmVjdCBBcyBSRUNUCgogICAKCiAgICBHZXRDbGllbnRSZWN0IGxGb3JtSHduZCwgdFJlY3QKCiAgICBXaXRoIG9TY3JvbGxhYmxlT2JqZWN0CgogICAgICAgIElmIElzT2JqZWN0VXNlckZvcm0ob1Njcm9sbGFibGVPYmplY3QpIFRoZW4KCiAgICAgICAgICAgIHRUb3BMZWZ0LlggPSB0UmVjdC5MZWZ0CgogICAgICAgICAgICB0VG9wTGVmdC5ZID0gdFJlY3QuVG9wCgogICAgICAgICAgICB0Qm90dG9tUmlnaHQuWCA9IHRSZWN0LlJpZ2h0CgogICAgICAgICAgICB0Qm90dG9tUmlnaHQuWSA9IHRSZWN0LkJvdHRvbQoKICAgICAgICBFbHNlCgogICAgICAgICAgICB0VG9wTGVmdC5YID0gUFR0b1BYKC5MZWZ0LCBGYWxzZSkgKyB0UmVjdC5MZWZ0CgogICAgICAgICAgICB0VG9wTGVmdC5ZID0gUFR0b1BYKC5Ub3AsIFRydWUpICsgdFJlY3QuVG9wCgogICAgICAgICAgICB0Qm90dG9tUmlnaHQuWCA9IFBUdG9QWCguTGVmdCArIC5XaWR0aCwgRmFsc2UpICsgdFJlY3QuTGVmdAoKICAgICAgICAgICAgdEJvdHRvbVJpZ2h0LlkgPSBQVHRvUFgoLlRvcCArIC5IZWlnaHQsIFRydWUpICsgdFJlY3QuVG9wCgogICAgICAgIEVuZCBJZgoKICAgIEVuZCBXaXRoCgogICAgQ2xpZW50VG9TY3JlZW4gbEZvcm1Id25kLCB0VG9wTGVmdAoKICAgIENsaWVudFRvU2NyZWVuIGxGb3JtSHduZCwgdEJvdHRvbVJpZ2h0CgogICAgU2V0UmVjdCB0UmVjdCwgdFRvcExlZnQuWCwgdFRvcExlZnQuWSwgdEJvdHRvbVJpZ2h0LlgsIHRCb3R0b21SaWdodC5ZCgogICAgT24gRXJyb3IgR29UbyBlcnJICgogICAgSWYgKG5Db2RlID0gSENfQUNUSU9OKSBBbmQgQ0Jvb2woUHRJblJlY3QodFJlY3QsIGxQYXJhbS5wdC5YLCBsUGFyYW0ucHQuWSkpIFRoZW4KCiAgICAgICAgSWYgd1BhcmFtID0gV01fTU9VU0VXSEVFTCBUaGVuCgogICAgICAgICAgICBXaXRoIG9TY3JvbGxhYmxlT2JqZWN0CgogICAgICAgICAgICAgICAgU2VsZWN0IENhc2UgR2V0QXN5bmNLZXlTdGF0ZShWQkEudmJLZXlDb250cm9sKQoKICAgICAgICAgICAgICAgICAgICBDYXNlIElzID0gMCAndmVydGljYWwgc2Nyb2xsCgogICAgICAgICAgICAgICAgICAgICAgICBJZiBsUGFyYW0uaHduZCA+IDAgVGhlbgoKICAgICAgICAgICAgICAgICAgICAgICAgICAgIC5TY3JvbGxUb3AgPSBBcHBsaWNhdGlvbi5NYXgoMCwgLlNjcm9sbFRvcCAtIFNDUk9MTF9DSEFOR0UpCgogICAgICAgICAgICAgICAgICAgICAgICBFbHNlCgogICAgICAgICAgICAgICAgICAgICAgICAgICAgLlNjcm9sbFRvcCA9IEFwcGxpY2F0aW9uLk1pbiguU2Nyb2xsSGVpZ2h0IC0gLkluc2lkZUhlaWdodCwgLlNjcm9sbFRvcCArIFNDUk9MTF9DSEFOR0UpCgogICAgICAgICAgICAgICAgICAgICAgICBFbmQgSWYKCiAgICAgICAgICAgICAgICAgICAgQ2FzZSBFbHNlICcgaG9yaXogc2Nyb2xsIHdoZW4gdGhlIEN0bCBrZXkgZG93bgoKICAgICAgICAgICAgICAgICAgICAgICAgSWYgbFBhcmFtLmh3bmQgPiAwIFRoZW4KCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAuU2Nyb2xsTGVmdCA9IEFwcGxpY2F0aW9uLk1heCgwLCAuU2Nyb2xsTGVmdCAtIFNDUk9MTF9DSEFOR0UpCgogICAgICAgICAgICAgICAgICAgICAgICBFbHNlCgogICAgICAgICAgICAgICAgICAgICAgICAgICAgLlNjcm9sbExlZnQgPSBBcHBsaWNhdGlvbi5NaW4oLlNjcm9sbFdpZHRoIC0gLkluc2lkZVdpZHRoLCAuU2Nyb2xsTGVmdCArIFNDUk9MTF9DSEFOR0UpCgogICAgICAgICAgICAgICAgICAgICAgICBFbmQgSWYKCiAgICAgICAgICAgICAgICBFbmQgU2VsZWN0CgogICAgICAgICAgICBFbmQgV2l0aAoKICAgICAgICBFbmQgSWYKCiAgICBFbmQgSWYKCiAgICBNb3VzZVByb2MgPSBDYWxsTmV4dEhvb2tFeCggXwoKICAgIGxNb3VzZUhvb2ssIG5Db2RlLCB3UGFyYW0sIEJ5VmFsIGxQYXJhbSkKCiAgICBFeGl0IEZ1bmN0aW9uCgplcnJIOgoKICAgIFJlbW92ZVNjcm9sbEhvb2sKCkVuZCBGdW5jdGlvbgoKIAoKUHJpdmF0ZSBGdW5jdGlvbiBTY3JlZW5EUEkoYlZlcnQgQXMgQm9vbGVhbikgQXMgTG9uZwoKICAgIFN0YXRpYyBsRFBJKDEpLCBsREMKCiAgICBJZiBsRFBJKDApID0gMCBUaGVuCgogICAgICAgIGxEQyA9IEdldERDKDApCgogICAgICAgIGxEUEkoMCkgPSBHZXREZXZpY2VDYXBzKGxEQywgTE9HUElYRUxTWCkKCiAgICAgICAgbERQSSgxKSA9IEdldERldmljZUNhcHMobERDLCBMT0dQSVhFTFNZKQoKICAgICAgICBsREMgPSBSZWxlYXNlREMoMCwgbERDKQoKICAgIEVuZCBJZgoKICAgIFNjcmVlbkRQSSA9IGxEUEkoQWJzKGJWZXJ0KSkKCkVuZCBGdW5jdGlvbgoKIAoKUHJpdmF0ZSBGdW5jdGlvbiBQVHRvUFggXwoKKFBvaW50cyBBcyBTaW5nbGUsIGJWZXJ0IEFzIEJvb2xlYW4pIEFzIExvbmcKCiAgICBQVHRvUFggPSBQb2ludHMgKiBTY3JlZW5EUEkoYlZlcnQpIC8gUE9JTlRTUEVSSU5DSAoKRW5kIEZ1bmN0aW9uCgogCgpQcml2YXRlIEZ1bmN0aW9uIElzT2JqZWN0VXNlckZvcm0oQnlWYWwgb2JqIEFzIE9iamVjdCkgQXMgQm9vbGVhbgoKICAgIERpbSBvVGVtcCBBcyBPYmplY3QKCiAgICBPbiBFcnJvciBSZXN1bWUgTmV4dAoKICAgICAgICBTZXQgb1RlbXAgPSBvYmouUGFyZW50CgogICAgICAgIFNldCBvVGVtcCA9IE5vdGhpbmcKCiAgICAgICAgSXNPYmplY3RVc2VyRm9ybSA9IEVyci5OdW1iZXIgPSA0MzgKCiAgICBPbiBFcnJvciBHb1RvIDAKCkVuZCBGdW5jdGlvbgoKIA==