You are on page 1of 23

Private Declare Function GdiTransparentBlt Lib "gdi32.

dll" (ByVal hDC As Long, ByVal x As Long, ByVal y As


Long, ByVal nWidth As Long, ByVal nHeight As Long, ByVal hSrcDC As Long, ByVal xSrc As Long, ByVal ySrc
As Long, ByVal nSrcWidth As Long, ByVal nSrcHeight As Long, ByVal crTransparent As Long) As Boolean

Private Declare Function CreateBitmap Lib "gdi32" (ByVal nWidth As Long, ByVal nHeight As Long, ByVal
nPlanes As Long, ByVal nBitCount As Long, lpBits As Any) As Long

Private Declare Function GetBkColor Lib "gdi32" (ByVal hDC As Long) As Long

Private Declare Function GetTextColor Lib "gdi32" (ByVal hDC As Long) As Long

Private Declare Function SetBkColor Lib "gdi32" (ByVal hDC As Long, ByVal crColor As Long) As Long

Private Declare Function SetTextColor Lib "gdi32" (ByVal hDC As Long, ByVal crColor As Long) As Long

Private Declare Function GetPixel Lib "gdi32" (ByVal hDC As Long, ByVal x As Long, ByVal y As Long) As Long

Private Declare Function GetFileAttributes Lib "kernel32" Alias "GetFileAttributesA" (ByVal lpFileName As
String) As Long

Private Const FILE_ATTRIBUTE_DIRECTORY = &H10

Private Declare Function DeleteFile Lib "kernel32" Alias "DeleteFileA" (ByVal lpFileName As String) As Long

Public Enum TabCaptionAlignment

TabCaptionAlignLeftTop = DT_LEFT Or DT_TOP

TabCaptionAlignLeftCenter = DT_LEFT Or DT_VCENTER

TabCaptionAlignLeftBottom = DT_LEFT Or DT_BOTTOM

TabCaptionAlignCenterTop = DT_CENTER Or DT_TOP

TabCaptionAlignCenterCenter = DT_CENTER Or DT_VCENTER

TabCaptionAlignCenterBottom = DT_CENTER Or DT_BOTTOM

TabCaptionAlignRightTop = DT_RIGHT Or DT_TOP

TabCaptionAlignRightCenter = DT_RIGHT Or DT_VCENTER

TabCaptionAlignRightBottom = DT_RIGHT Or DT_BOTTOM

TabCaptionSingleLine = DT_SINGLELINE

TabCaptionWordWrap = DT_WORDBREAK

TabCaptionEllipsis = DT_WORD_ELLIPSIS

TabCaptionNoPrefix = DT_NOPREFIX

End Enum
Public Event TabClick(ByVal TabIndex As Long)

Public Event BeforeTabChange(ByVal LastTab As Long, ByRef NewTab As Long)

Public Event TabOrderChanged(ByVal LastTab As Long, ByRef NewTab As Long)

Private Type tTabInfo

sCaption As String

sTag As String

sKey As String

ItemData As Long

Left As Long

Width As Long

Image As Long

Alignment As Long ' TabCaptionAlignment

Enabled As Boolean

Visible As Boolean

Active As Boolean

Top As Long

Height As Long

Right As Long

Bottom As Long

End Type

Private Type tControlInfo

ctlName As String

iTabIndex As Long

End Type

Private m_Tabs() As tTabInfo

Private m_TabCount As Long


Private m_TabOrder() As Long

Private m_Ctls() As tControlInfo

Private m_ctlCount As Long

Private mhDC As Long, hBmp As Long, hBmpOld As Long

Private lScrollX As Long, lScrollWidth As Long

Private lTabIndex As Long

Private cx As Long, cy As Long

Private lTabDragging As Boolean

Private lTabDragged As Long

Private lTabHover As Long

Private mFont As IFont

Private selIndex As Long

Private Enum ssSliderStatus

ssDisabled

ssNormal

ssDown

ssHover

End Enum

Private SliderBox As RECT

Private bSliderShown As Boolean

Private LeftSliderStatus As ssSliderStatus

Private RightSliderStatus As ssSliderStatus

Private bInFocus As Boolean

Private m_AllowReorder As Boolean

'for contained controls

' store control name, index and tabIndex: ctl1(0)1 or clt1()1 if there is no index
'Private ctlLst() As New Collection ', visibleCTLs As New Collection

'Autor: wqweto http://www.vbforums.com/showthread.php?872819

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

' 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

You might also like