Sunteți pe pagina 1din 20

'Private ctlLst() As New Collection ', visibleCTLs As New Collection

'=========================================================================

' The Modern Subclassing Thunk (MST)

'=========================================================================

Private Function InitAddressOfMethod(pObj As Object, ByVal MethodParamCount As Long) As TabControl

Const STR_THUNK As String =


"6AAAAABag+oFV4v6ge9QEMEAgcekEcEAuP9EJAS5+QcAAPOri8LB4AgFuQAAAKuLwsHoGAUAjYEAq7gIAAAr
q7hEJASLq7hJCIsEq7iBi1Qkq4tEJAzB4AIFCIkCM6uLRCQMweASBcDCCACriTrHQgQBAAAAi0QkCIsAiUIIi0QkEIl
CDIHqUBDBAIvCBTwRwQCri8IFUBHBAKuLwgVgEcEAq4vCBYQRwQCri8IFjBHBAKuLwgWUEcEAq4vCBZwRwQ
Cri8IFpBHBALn5BwAAq4PABOL6i8dfgcJQEMEAi0wkEIkRK8LCEAAPHwCLVCQE/0IEi0QkDIkQM8DCDABmkItU
JAT/QgSLQgTCBAAPHwCLVCQE/0oEi0IEg/gAfgPCBABZWotCDGgAgAAAagBSUf/gZpC4AUAAgMIIALgBQACA
whAAuAFAAIDCGAC4AUAAgMIkAA==" ' 25.3.2019 14:01:08

Const THUNK_SIZE As Long = 16728

Dim hThunk As Long

Dim lSize As Long

hThunk = VirtualAlloc(0, THUNK_SIZE, MEM_COMMIT, PAGE_EXECUTE_READWRITE)

Call CryptStringToBinary(STR_THUNK, Len(STR_THUNK), CRYPT_STRING_BASE64, hThunk, THUNK_SIZE)

lSize = CallWindowProc(hThunk, ObjPtr(pObj), MethodParamCount,


GetProcAddress(GetModuleHandle("kernel32"), "VirtualFree"), VarPtr(InitAddressOfMethod))

Debug.Assert lSize = THUNK_SIZE

End Function

Private Function InitSubclassingThunk(ByVal hWnd As Long, pObj As Object, ByVal pfnCallback As Long) As
IUnknown

Const STR_THUNK As String =


"6AAAAABag+oFgepwEB4BV1aLdCQUg8YIgz4AdC+L+oHHABIeAYvCBQgRHgGri8IFRBEeAauLwgVUER4Bq4vC
BXwRHgGruQkAAADzpYHCABIeAVJqGP9SEFqL+IvCq7gBAAAAqzPAq4tEJAyri3QkFKWlg+8YagBX/3IM/3cM/1I
Yi0QkGIk4Xl+4NBIeAS1wEB4BwhAAZpCLRCQIgzgAdSqDeAQAdSSBeAjAAAAAdRuBeAwAAABGdRKLVCQE/0I
Ei0QkDIkQM8DCDAC4AkAAgMIMAJCLVCQE/0IEi0IEwgQADx8Ai1QkBP9KBItCBHUYiwpS/3EM/3IM/1Eci1QkB
IsKUv9RFDPAwgQAkFWL7ItVGIsKi0EshcB0OFL/0FqJQgiD+AF3VIP4AHUJgX0MAwIAAHRGiwpS/1EwWoXAdT
uLClJq8P9xJP9RKFqpAAAACHUoUjPAUFCNRCQEUI1EJARQ/3UU/3UQ/3UM/3UI/3IQ/1IUWVhahcl1EYsK/3U
U/3UQ/3UM/3UI/1EgXcIYAA==" ' 1.4.2019 11:41:46

Const THUNK_SIZE As Long = 452


Static hThunk As Long

Dim aParams(0 To 10) As Long

Dim lSize As Long

aParams(0) = ObjPtr(pObj)

aParams(1) = pfnCallback

#If ImplSelfContained Then

If hThunk = 0 Then

hThunk = pvThunkGlobalData("InitSubclassingThunk")

End If

#End If

If hThunk = 0 Then

hThunk = VirtualAlloc(0, THUNK_SIZE, MEM_COMMIT, PAGE_EXECUTE_READWRITE)

Call CryptStringToBinary(STR_THUNK, Len(STR_THUNK), CRYPT_STRING_BASE64, hThunk,


THUNK_SIZE)

aParams(2) = GetProcAddress(GetModuleHandle("ole32"), "CoTaskMemAlloc")

aParams(3) = GetProcAddress(GetModuleHandle("ole32"), "CoTaskMemFree")

Call DefSubclassProc(0, 0, 0, 0) '--- load comctl32

aParams(4) = GetProcAddressByOrdinal(GetModuleHandle("comctl32"), 410) '--- 410 =


SetWindowSubclass ordinal

aParams(5) = GetProcAddressByOrdinal(GetModuleHandle("comctl32"), 412) '--- 412 =


RemoveWindowSubclass ordinal

aParams(6) = GetProcAddressByOrdinal(GetModuleHandle("comctl32"), 413) '--- 413 =


DefSubclassProc ordinal

'--- for IDE protection

Debug.Assert pvGetIdeOwner(aParams(7))

If aParams(7) <> 0 Then

aParams(8) = GetProcAddress(GetModuleHandle("user32"), "GetWindowLongA")

aParams(9) = GetProcAddress(GetModuleHandle("vba6"), "EbMode")

aParams(10) = GetProcAddress(GetModuleHandle("vba6"), "EbIsResetting")


End If

#If ImplSelfContained Then

pvThunkGlobalData("InitSubclassingThunk") = hThunk

#End If

End If

lSize = CallWindowProc(hThunk, hWnd, 0, VarPtr(aParams(0)), VarPtr(InitSubclassingThunk))

Debug.Assert lSize = THUNK_SIZE

End Function

Private Property Get ThunkPrivateData(pThunk As IUnknown, Optional ByVal Index As Long) As Long

Dim lPtr As Long

lPtr = ObjPtr(pThunk)

If lPtr <> 0 Then

Call CopyMemory(ThunkPrivateData, ByVal (lPtr Xor SIGN_BIT) + 8 + Index * 4 Xor SIGN_BIT, 4)

End If

End Property

Private Function pvGetIdeOwner(hIdeOwner As Long) As Boolean

#If Not ImplNoIdeProtection Then

Dim lProcessId As Long

Do

hIdeOwner = FindWindowEx(0, hIdeOwner, "IDEOwner", vbNullString)

Call GetWindowThreadProcessId(hIdeOwner, lProcessId)

Loop While hIdeOwner <> 0 And lProcessId <> GetCurrentProcessId()

#End If

pvGetIdeOwner = True
End Function

#If ImplSelfContained Then

Private Property Get pvThunkGlobalData(sKey As String) As Long

Dim sBuffer As String

sBuffer = String$(50, 0)

Call GetEnvironmentVariable("_MST_GLOBAL" & App.hInstance & "_" & sKey, sBuffer, Len(sBuffer) - 1)

pvThunkGlobalData = Val(Left$(sBuffer, InStr(sBuffer, vbNullChar) - 1))

End Property

Private Property Let pvThunkGlobalData(sKey As String, ByVal lValue As Long)

Call SetEnvironmentVariable("_MST_GLOBAL" & App.hInstance & "_" & sKey, lValue)

End Property

#End If

Private Sub pvSubclass()

pvUnsubclass

If mUserControlHwnd <> 0 Then

Set m_pSubclass = InitSubclassingThunk(mUserControlHwnd, Me, InitAddressOfMethod(Me,


5).SubclassProc(0, 0, 0, 0, 0))

End If

End Sub

Private Sub pvUnsubclass()

Set m_pSubclass = Nothing

End Sub

Public Function SubclassProc(ByVal hWnd As Long, ByVal wMsg As Long, ByVal wParam As Long, ByVal
lParam As Long, Handled As Boolean) As Long
'Dim x As Single

'Dim y As Single

'

' Select Case wMsg

' Case WM_LBUTTONDOWN

' x = (lParam And &HFFFF&)

' y = (lParam \ &H10000 And &HFFFF&)

'

' End Select

' '--- note: performance optimization for design-time subclassing

' If Not Handled And ThunkPrivateData(m_pSubclass) = EBMODE_DESIGN Then

' Handled = True

' SubclassProc = DefSubclassProc(hwnd, wMsg, wParam, lParam)

' End If

If mUserMode = True Then

Handled = True

SubclassProc = DefSubclassProc(hWnd, wMsg, wParam, lParam)

Exit Function

End If

Dim lTab As Long

Dim x As Single

Dim y As Single

Select Case wMsg

Case WM_LBUTTONDOWN ' UserControl message, only in design mode (Not Ambient.UserMode), to
provide change of selected tab by clicking at design time

' If TypeOf UserControl.Parent Is Form Then

' UserControl.Parent.Caption = Timer


' End If

' If Not MouseIsOverAContainedControl Then

lTab = selIndex

' Call ProcessMouseMove(vbLeftButton, 0, (lParam And &HFFFF&) * Screen_TwipsPerPixelX,


(lParam \ &H10000 And &HFFFF&) * Screen_TwipsPerPixelX)

' X = (lParam And &HFFFF&) * Screen_TwipsPerPixelX

' Y = (lParam \ &H10000 And &HFFFF&) * Screen_TwipsPerPixely

x = (lParam And &HFFFF&)

y = (lParam \ &H10000 And &HFFFF&)

' UserControl.Parent.Caption = "X " & X & " Y " & Y

Call UserControl_MouseDown(vbLeftButton, -1, x, y)

If selIndex <> lTab Then

Handled = True

SubclassProc = 0

Exit Function

End If

' End If

' If mChangeControlsBackColor And (mTabBackColor <> vbButtonFace) Then

' mLastContainedControlsCount = UserControl.ContainedControls.Count

' tmrCheckContainedControlsAdditionDesignTime.Enabled = True

' End If

End Select

Handled = False

SubclassProc = DefSubclassProc(hWnd, wMsg, wParam, lParam)

End Function

'--- End for MST subclassing (2)

Private Function MouseIsOverAContainedControl() As Boolean


Dim iPt As POINTAPI

Dim iSM As Long

Dim iCtl As Control

Dim iWidth As Long

iSM = UserControl.ScaleMode

UserControl.ScaleMode = vbTwips

GetCursorPos iPt

ScreenToClient mUserControlHwnd, iPt

iPt.x = iPt.x * Screen.TwipsPerPixelX

iPt.y = iPt.y * Screen.TwipsPerPixelY

On Error Resume Next

For Each iCtl In UserControl.ContainedControls

iWidth = -1

iWidth = iCtl.Width

If iWidth <> -1 Then

If iCtl.Left <= iPt.x Then

If iCtl.Left + iCtl.Width >= iPt.x Then

If iCtl.Top <= iPt.y Then

If iCtl.Top + iCtl.Height >= iPt.y Then

MouseIsOverAContainedControl = True

Err.Clear

Exit Function

End If

End If

End If

End If
End If

Next

Err.Clear

UserControl.ScaleMode = iSM

End Function

Public Property Get hWnd() As Long

hWnd = UserControl.hWnd

End Property

Private Sub TimerCheckMouseOut_Timer()

Dim Pos As POINTAPI

Dim WFP As Long

GetCursorPos Pos

WFP = WindowFromPoint(Pos.x, Pos.y)

If WFP <> Me.hWnd Then

UserControl_MouseMove -1, 0, -1, -1

TimerCheckMouseOut.Enabled = False 'kill that timer at once

End If

End Sub

Private Sub tmrSlide_Timer()

If tmrSlide.Enabled = False Then

Exit Sub

End If

If RightSliderStatus = ssDown Then

lScrollX = lScrollX + 10
If lScrollX > lScrollWidth Then

lScrollX = lScrollWidth

RightSliderStatus = ssDisabled

tmrSlide.Enabled = False

Me.Refresh

Exit Sub

End If

LeftSliderStatus = ssNormal

Else

lScrollX = lScrollX - 10

If lScrollX < 0 Then

lScrollX = 0

LeftSliderStatus = ssDisabled

tmrSlide.Enabled = False

Me.Refresh

Exit Sub

End If

RightSliderStatus = ssNormal

End If

'Draw

Me.Refresh

If tmrSlide.Interval > 10 Then tmrSlide.Interval = tmrSlide.Interval - 2

End Sub

Private Sub UserControl_AmbientChanged(PropertyName As String)

If PropertyName = "UserMode" Then mUserMode = Ambient.UserMode

End Sub
Private Sub UserControl_EnterFocus()

bInFocus = True

Me.Refresh

End Sub

Private Sub UserControl_ExitFocus()

bInFocus = False

Me.Refresh

End Sub

Private Sub UserControl_Initialize()

Me.Refresh

End Sub

Private Sub UserControl_InitProperties()

Dim c As Long

On Error GoTo 0

mUserMode = Ambient.UserMode

mUserControlHwnd = UserControl.hWnd

mContainerHwnd = UserControl.ContainerHwnd

mUserControlHdc = UserControl.hDC

pvSubclass

CreateGraphicsDC

For c = 1 To 4

AddTab , "Tab " & c


Next

End Sub

Private Function getTabOrder(ByVal Index As Long) As Long

Dim c As Long

For c = 0 To m_TabCount - 1

If m_TabOrder(c) = Index Then

getTabOrder = c

Exit For

End If

Next

End Function

Private Sub UserControl_KeyDown(KeyCode As Integer, Shift As Integer)

Dim lTab As Long, lCount As Long

' lTab = selIndex

lTab = getTabOrder(selIndex)

NextTab:

lCount = lCount + 1

Select Case KeyCode

Case vbKeyLeft

If lCount > 2 Then

lTab = m_TabCount ' + 1

End If

If lTab > 0 Then

lTab = lTab - 1

End If

Case vbKeyRight

If lCount > 2 Then

lTab = -1 '0
End If

If lTab < m_TabCount - 1 Then

lTab = lTab + 1

End If

End Select

If lTab >= 0 And lTab < m_TabCount And lCount < m_TabCount Then

If m_Tabs(m_TabOrder(lTab)).Enabled = False Or m_Tabs(m_TabOrder(lTab)).Visible = False Then

GoTo NextTab:

End If

End If

lTab = m_TabOrder(lTab)

If selIndex <> lTab Then

RaiseEvent BeforeTabChange(selIndex, lTab)

RaiseEvent TabClick(lTab)

SelectedItem = lTab

End If

End Sub

Private Sub UserControl_Paint()

mUserControlHdc = hDC

' Draw

Me.Refresh

End Sub

Private Sub UserControl_ReadProperties(PropBag As PropertyBag)

Set mFont = PropBag.ReadProperty("Font", Ambient.Font)

Set UserControl.Font = mFont


' Set mFontActive = PropBag.ReadProperty("FontActive", Ambient.Font)

' Set mFontHover = PropBag.ReadProperty("FontHover", Ambient.Font)

' Set mFontDisabled = PropBag.ReadProperty("FontDisabled", Ambient.Font)

m_AllowReorder = PropBag.ReadProperty("AllowReorder", False)

selIndex = PropBag.ReadProperty("SelectedItem", 0)

m_TabCount = PropBag.ReadProperty("ItemCount", 4)

ReDim m_Tabs(m_TabCount - 1)

ReDim m_TabOrder(m_TabCount - 1)

ReDim ctlLst(m_TabCount - 1)

m_ctlCount = 0

ReDim m_Ctls(m_ctlCount)

Dim i As Long, z As Long

Dim mCCount As Long, ctlName As String, ItemMax As Long

For i = 0 To m_TabCount - 1

' m_TabOrder(I) = I

m_TabOrder(i) = PropBag.ReadProperty("TabOrder" & i, i)

m_Tabs(i).Image = PropBag.ReadProperty("TabIcon" & i, 0)

m_Tabs(i).Enabled = PropBag.ReadProperty("TabEnabled" & i, True)

m_Tabs(i).sKey = PropBag.ReadProperty("Key" & i, "")

m_Tabs(i).sTag = PropBag.ReadProperty("TabTag" & i, "")

m_Tabs(i).Visible = PropBag.ReadProperty("TabVisible" & i, True)

m_Tabs(i).sCaption = PropBag.ReadProperty("Item(" & i & ").Caption", "Tab " & i + 1)

mCCount = PropBag.ReadProperty("Item(" & i & ").ControlCount", 0)


For z = 0 To mCCount - 1

ctlName = PropBag.ReadProperty("Item(" & i & ").Control(" & z & ")", "")

If ctlName <> "" Then

ReDim Preserve m_Ctls(m_ctlCount)

m_Ctls(m_ctlCount).ctlName = ctlName

m_Ctls(m_ctlCount).iTabIndex = i

m_ctlCount = m_ctlCount + 1

End If

Next z

Next i

ItemMax = PropBag.ReadProperty("ItemMax", 0)

For i = m_TabCount To ItemMax

mCCount = PropBag.ReadProperty("Item(" & i & ").ControlCount", 0)

For z = 0 To mCCount - 1

ctlName = PropBag.ReadProperty("Item(" & i & ").Control(" & z & ")", "")

If ctlName <> "" Then

ReDim Preserve m_Ctls(m_ctlCount)

m_Ctls(m_ctlCount).ctlName = ctlName

m_Ctls(m_ctlCount).iTabIndex = i

m_ctlCount = m_ctlCount + 1

End If

Next z

Next

If selIndex > m_TabCount - 1 Then

selIndex = m_TabCount - 1

End If
'' handleControls 0, selIndex

SelectedItem = selIndex

On Error GoTo 0

mUserMode = Ambient.UserMode

mUserControlHwnd = UserControl.hWnd

mContainerHwnd = UserControl.ContainerHwnd

mUserControlHdc = UserControl.hDC

pvSubclass

CreateGraphicsDC

' Draw

Me.Refresh

End Sub

Private Sub UserControl_WriteProperties(PropBag As PropertyBag)

PropBag.WriteProperty "Font", mFont, Ambient.Font

' PropBag.WriteProperty "FontActive", mFontActive, Ambient.Font

' PropBag.WriteProperty "FontHover", mFontHover, Ambient.Font

' PropBag.WriteProperty "FontDisabled", mFontDisabled, Ambient.Font

PropBag.WriteProperty "AllowReorder", m_AllowReorder, False

PropBag.WriteProperty "SelectedItem", selIndex, 0

PropBag.WriteProperty "ItemCount", m_TabCount, 4

'

Dim i As Long, z As Long, c As Long, MaxIndex As Long

For i = 0 To m_TabCount - 1

PropBag.WriteProperty "TabOrder" & i, m_TabOrder(i), i

PropBag.WriteProperty "TabIcon" & i, m_Tabs(i).Image, 0


PropBag.WriteProperty "TabEnabled" & i, m_Tabs(i).Enabled, True

PropBag.WriteProperty "TabTag" & i, m_Tabs(i).sTag, ""

PropBag.WriteProperty "TabKey" & i, m_Tabs(i).sKey, ""

PropBag.WriteProperty "TabVisible" & i, m_Tabs(i).Visible, True

PropBag.WriteProperty "Item(" & i & ").Caption", m_Tabs(i).sCaption, "Tab " & i + 1

c=0

For z = 0 To m_ctlCount - 1

If m_Ctls(z).iTabIndex = i Then

PropBag.WriteProperty "Item(" & i & ").Control(" & c & ")", m_Ctls(z).ctlName, ""

c=c+1

End If

If MaxIndex < m_Ctls(z).iTabIndex Then

MaxIndex = m_Ctls(z).iTabIndex

End If

Next z

PropBag.WriteProperty "Item(" & i & ").ControlCount", c, 0

Next i

PropBag.WriteProperty "ItemMax", MaxIndex, 0

For i = m_TabCount To MaxIndex

c=0

For z = 0 To m_ctlCount - 1

If m_Ctls(z).iTabIndex = i Then

PropBag.WriteProperty "Item(" & i & ").Control(" & c & ")", m_Ctls(z).ctlName, ""

c=c+1

End If

Next z

PropBag.WriteProperty "Item(" & i & ").ControlCount", c, 0

Next
End Sub

Private Function TranslateColor(ByVal OLE_COLOR As Long) As Long

apiTranslateColor OLE_COLOR, 0, TranslateColor

End Function

Private Sub TransBlt(ByVal hdcScreen As Long, ByVal hdcDest As Long, ByVal xDest As Long, ByVal yDest As
Long, _

ByVal nWidth As Long, ByVal nHeight As Long, ByVal hdcSrc As Long, _

ByVal xSrc As Long, ByVal ySrc As Long, ByVal nWidthSrc As Long, ByVal nHeightSrc As Long, ByVal
clrMask As OLE_COLOR)

'one check to see if GdiTransparentBlt is supported

'better way to check if function is suported is using LoadLibrary and GetProcAdress

'than using GetVersion or GetVersionEx

'=====================================================

Dim Lib As Long

Dim ProcAdress As Long

Dim lMaskColor As Long

lMaskColor = TranslateColor(clrMask)

Lib = LoadLibrary("gdi32.dll")

'--------------------->make sure to specify corect name for function

ProcAdress = GetProcAddress(Lib, "GdiTransparentBlt")

FreeLibrary Lib

If ProcAdress <> 0 Then

'works on XP

GdiTransparentBlt hdcDest, xDest, yDest, nWidth, nHeight, hdcSrc, xSrc, ySrc, nWidthSrc, nHeightSrc,
lMaskColor

'Debug.Print "Gdi transparent blt"

Exit Sub 'make it short

End If
'=====================================================

Const DSna As Long = &H220326

Dim hdcMask As Long

Dim hdcColor As Long

Dim hbmMask As Long

Dim hbmColor As Long

Dim hbmColorOld As Long

Dim hbmMaskOld As Long

Dim hdcScnBuffer As Long

Dim hbmScnBuffer As Long

Dim hbmScnBufferOld As Long

lMaskColor = TranslateColor(clrMask)

hbmScnBuffer = CreateCompatibleBitmap(hdcScreen, nWidth, nHeight)

hdcScnBuffer = CreateCompatibleDC(hdcScreen)

hbmScnBufferOld = SelectObject(hdcScnBuffer, hbmScnBuffer)

BitBlt hdcScnBuffer, 0, 0, nWidth, nHeight, hdcDest, xDest, yDest, vbSrcCopy

hbmColor = CreateCompatibleBitmap(hdcScreen, nWidth, nHeight)

hbmMask = CreateBitmap(nWidth, nHeight, 1, 1, ByVal 0&)

hdcColor = CreateCompatibleDC(hdcScreen)

hbmColorOld = SelectObject(hdcColor, hbmColor)


Call SetBkColor(hdcColor, GetBkColor(hdcSrc))

Call SetTextColor(hdcColor, GetTextColor(hdcSrc))

' Call BitBlt(hdcColor, 0, 0, nWidth, nHeight, hdcSrc, xSrc, ySrc, vbSrcCopy)

Call StretchBlt(hdcColor, 0, 0, nWidth, nHeight, hdcSrc, xSrc, ySrc, nWidthSrc, nHeightSrc, vbSrcCopy)

hdcMask = CreateCompatibleDC(hdcScreen)

hbmMaskOld = SelectObject(hdcMask, hbmMask)

SetBkColor hdcColor, lMaskColor

SetTextColor hdcColor, vbWhite

BitBlt hdcMask, 0, 0, nWidth, nHeight, hdcColor, 0, 0, vbSrcCopy

' StretchBlt hdcMask, 0, 0, nWidth, nHeight, hdcColor, 0, 0, nWidthSrc, nHeightSrc, vbSrcCopy

SetTextColor hdcColor, vbBlack

SetBkColor hdcColor, vbWhite

BitBlt hdcColor, 0, 0, nWidth, nHeight, hdcMask, 0, 0, DSna

BitBlt hdcScnBuffer, 0, 0, nWidth, nHeight, hdcMask, 0, 0, vbSrcAnd

BitBlt hdcScnBuffer, 0, 0, nWidth, nHeight, hdcColor, 0, 0, vbSrcPaint

BitBlt hdcDest, xDest, yDest, nWidth, nHeight, hdcScnBuffer, 0, 0, vbSrcCopy

'clear

DeleteObject SelectObject(hdcColor, hbmColorOld)

DeleteDC hdcColor

DeleteObject SelectObject(hdcScnBuffer, hbmScnBufferOld)

DeleteDC hdcScnBuffer

DeleteObject SelectObject(hdcMask, hbmMaskOld)

DeleteDC hdcMask
'ReleaseDC 0, hdcScreen

End Sub

S-ar putea să vă placă și