-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmdTabStripPaneHelper.bas
279 lines (240 loc) · 10.5 KB
/
mdTabStripPaneHelper.bas
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
Attribute VB_Name = "mdTabStripPaneHelper"
Option Explicit
Private Const MODULE_NAME As String = "mdTabStripPaneHelper"
'=========================================================================
' API
'=========================================================================
'--- for Get/SetThemeAppProperties
Private Const STAP_ALLOW_CONTROLS As Long = 2
'--- for InitCommonControlsEx
Private Const ICC_USEREX_CLASSES As Long = &H200
Private Declare Function GetModuleHandle Lib "kernel32" Alias "GetModuleHandleA" (ByVal lpModuleName As String) As Long
Private Declare Sub OutputDebugString Lib "kernel32" Alias "OutputDebugStringA" (ByVal lpOutputString As String)
Private Declare Function IsAppThemed Lib "uxtheme" () As Long
Private Declare Function IsThemeActive Lib "uxtheme" () As Long
Private Declare Function GetThemeAppProperties Lib "uxtheme" () As Long
Private Declare Function DllGetVersion Lib "comctl32.dll" (pdvi As DLLVERSIONINFO) As Long
Private Declare Function InitCommonControlsEx Lib "comctl32.dll" (iccex As tagInitCommonControlsEx) As Boolean
Private Declare Function LoadLibrary Lib "kernel32" Alias "LoadLibraryA" (ByVal lpLibFileName As String) As Long
Private Declare Function EnumChildWindows Lib "user32" (ByVal hWndParent As Long, ByVal lpEnumFunc As Long, ByVal lParam As Long) As Long
Private Declare Function GetClassName Lib "user32" Alias "GetClassNameA" (ByVal hWnd As Long, ByVal lpClassName As String, ByVal nMaxCount As Long) As Long
'--- hooked
Private Declare Function FillRect Lib "user32" (ByVal hDC As Long, ByVal lpRect As Long, ByVal hBrush As Long) As Long
Private Declare Function ExtTextOutW Lib "gdi32" (ByVal hDC As Long, ByVal X As Long, ByVal Y As Long, ByVal wOptions As Long, ByVal lpRect As Long, ByVal lpString As Long, ByVal nCount As Long, ByVal lpDx As Long) As Long
Private Type DLLVERSIONINFO
cbSize As Long
dwMajor As Long
dwMinor As Long
dwBuildNumber As Long
dwPlatformID As Long
End Type
Private Type tagInitCommonControlsEx
lngSize As Long
lngICC As Long
End Type
'=========================================================================
' Constants and member variables
'=========================================================================
Private Const MODULE_COMCTL32 As String = "COMCTL32.DLL"
Private Const MODULE_COMCT232 As String = "MSCOMCTL.OCX"
Private Const MODULE_MSVBVM60 As String = "MSVBVM60.DLL"
Private Const MODULE_VB6 As String = "VB6.EXE"
Private Const MODULE_USER32 As String = "USER32.DLL"
Private Const MODULE_GDI32 As String = "GDI32.DLL"
Private Const MODULE_USP10 As String = "USP10.DLL" '--- Uniscribe Unicode script processor
Private Const API_FILLRECT As String = "FillRect"
Private Const API_EXTTEXTOUTW As String = "ExtTextOutW"
Private m_oFwdTabStripPane As cTabStripPane
Private m_lHookRefCount As Long
Private m_pOrigFillRect As Long
Private m_pOrigExtTextOutW As Long
'=========================================================================
' Error handling
'=========================================================================
Private Sub PrintError(sFunc As String)
Call OutputDebugString(MODULE_NAME & "." & sFunc & ": " & Err.Description & Timer & vbCrLf)
Debug.Print MODULE_NAME & "." & sFunc & ": " & Err.Description & Timer
End Sub
'=========================================================================
' Properties
'=========================================================================
Property Get CurrentTabStripPane() As cTabStripPane
Set CurrentTabStripPane = m_oFwdTabStripPane
End Property
Property Set CurrentTabStripPane(oValue As cTabStripPane)
Set m_oFwdTabStripPane = oValue
End Property
'=========================================================================
' Redirectors
'=========================================================================
Public Function RedirectTabPaneTabWndProc( _
ByVal hWnd As Long, _
ByVal wMsg As Long, _
ByVal wParam As Long, _
ByVal lParam As Long, _
ByVal uIdSubclass As Long, _
ByVal This As cTabStripPane) As Long
#If uIdSubclass Then '--- touch args
#End If
RedirectTabPaneTabWndProc = This.frWndProc(hWnd, wMsg, wParam, lParam)
End Function
Public Function RedirectTabPaneEditWndProc( _
ByVal hWnd As Long, _
ByVal wMsg As Long, _
ByVal wParam As Long, _
ByVal lParam As Long, _
ByVal uIdSubclass As Long, _
ByVal This As cTabStripPane) As Long
#If uIdSubclass Then '--- touch args
#End If
RedirectTabPaneEditWndProc = This.frEditWndProc(hWnd, wMsg, wParam, lParam)
End Function
'=========================================================================
' Class factories
'=========================================================================
Public Function InitTabStripPane( _
ByVal hWndTab As Long, _
oContainer As Object, _
oControls As Object, _
Optional RetVal As cTabStripPane) As cTabStripPane
Set RetVal = New cTabStripPane
If RetVal.Init(hWndTab, oContainer, oControls) Then
Set InitTabStripPane = RetVal
End If
End Function
'=========================================================================
' Global Functions
'=========================================================================
Public Function InitCommonControlsVB() As Boolean
Dim iccex As tagInitCommonControlsEx
On Error Resume Next
Call LoadLibrary("shell32.dll")
With iccex
.lngSize = LenB(iccex)
.lngICC = ICC_USEREX_CLASSES
End With
Call InitCommonControlsEx(iccex)
InitCommonControlsVB = (Err.Number = 0)
On Error GoTo 0
End Function
Public Function HookApiCalls() As Boolean
Const FUNC_NAME As String = "HookApiCalls"
On Error GoTo EH
If m_lHookRefCount = 0 Then
m_pOrigFillRect = pvHookApiFunc(MODULE_USER32, API_FILLRECT, AddressOf pvCustomFillRect)
m_pOrigExtTextOutW = pvHookApiFunc(MODULE_GDI32, API_EXTTEXTOUTW, AddressOf pvCustomExtTextOutW)
End If
m_lHookRefCount = m_lHookRefCount + 1
'--- success
HookApiCalls = True
Exit Function
EH:
PrintError FUNC_NAME
Resume Next
End Function
Public Sub UnhookApiCalls()
Const FUNC_NAME As String = "UnhookApiCalls"
On Error GoTo EH
If m_lHookRefCount > 0 Then
m_lHookRefCount = m_lHookRefCount - 1
If m_lHookRefCount = 0 Then
pvHookApiFunc MODULE_USER32, API_FILLRECT, m_pOrigFillRect
pvHookApiFunc MODULE_GDI32, API_EXTTEXTOUTW, m_pOrigExtTextOutW
End If
End If
Exit Sub
EH:
PrintError FUNC_NAME
Resume Next
End Sub
Public Function IsComCtl6Loaded() As Boolean
Const FUNC_NAME As String = "IsComCtl6Loaded"
Dim uVer As DLLVERSIONINFO
On Error GoTo EH
uVer.cbSize = Len(uVer)
Call DllGetVersion(uVer)
IsComCtl6Loaded = (uVer.dwMajor >= 6)
Exit Function
EH:
PrintError FUNC_NAME
Resume Next
End Function
Public Function IsThemed() As Boolean
'--- uxtheme.dll is not present on earlier OS'es
On Error Resume Next
IsThemed = True
If IsAppThemed() = 0 Then
IsThemed = False
ElseIf IsThemeActive() = 0 Then
IsThemed = False
ElseIf (GetThemeAppProperties() And STAP_ALLOW_CONTROLS) = 0 Then
IsThemed = False
End If
On Error GoTo 0
End Function
Public Function EnumChildEdits(ByVal hWnd As Long) As Collection
Set EnumChildEdits = New Collection
Call EnumChildWindows(hWnd, AddressOf pvEnumChildEdits, VarPtr(EnumChildEdits))
End Function
Public Function VBGetClassName(ByVal hWnd As Long) As String
VBGetClassName = String(1000, 0)
Call GetClassName(hWnd, VBGetClassName, Len(VBGetClassName) - 1)
VBGetClassName = Left$(VBGetClassName, InStr(VBGetClassName, Chr$(0)) - 1)
End Function
'= private ===============================================================
Private Function pvHookApiFunc(sModule As String, sFunc As String, ByVal lAddr As Long) As Long
Const FUNC_NAME As String = "pvHookApiFunc"
Dim lPrev As Long
On Error GoTo EH
'--- sanity check
If lAddr = 0 Then Exit Function
HookImportedFunctionByName GetModuleHandle(MODULE_COMCTL32), sModule, sFunc, lAddr, lPrev
If lPrev <> 0 Then pvHookApiFunc = lPrev
HookImportedFunctionByName GetModuleHandle(MODULE_MSVBVM60), sModule, sFunc, lAddr, lPrev
If lPrev <> 0 Then pvHookApiFunc = lPrev
HookImportedFunctionByName GetModuleHandle(MODULE_VB6), sModule, sFunc, lAddr, lPrev
If lPrev <> 0 Then pvHookApiFunc = lPrev
HookImportedFunctionByName GetModuleHandle(MODULE_COMCT232), sModule, sFunc, lAddr, lPrev
If lPrev <> 0 Then pvHookApiFunc = lPrev
HookImportedFunctionByName GetModuleHandle(MODULE_USP10), sModule, sFunc, lAddr, lPrev
If lPrev <> 0 Then pvHookApiFunc = lPrev
Exit Function
EH:
PrintError FUNC_NAME
Resume Next
End Function
Private Function pvCustomFillRect(ByVal hDC As Long, ByVal lpRect As Long, ByVal hBrush As Long) As Long
Const FUNC_NAME As String = "pvCustomFillRect"
On Error GoTo EH
If Not CurrentTabStripPane Is Nothing And lpRect <> 0 Then
pvCustomFillRect = CurrentTabStripPane.frFillRectImpl(hDC, lpRect, hBrush)
End If
If pvCustomFillRect = 0 Then
pvCustomFillRect = FillRect(hDC, lpRect, hBrush)
End If
Exit Function
EH:
PrintError FUNC_NAME
Resume Next
End Function
Private Function pvCustomExtTextOutW(ByVal hDC As Long, ByVal X As Long, ByVal Y As Long, ByVal wOptions As Long, ByVal lpRect As Long, ByVal lpString As Long, ByVal nCount As Long, ByVal lpDx As Long) As Long
Const FUNC_NAME As String = "pvCustomExtTextOutW"
On Error GoTo EH
If Not CurrentTabStripPane Is Nothing Then
pvCustomExtTextOutW = CurrentTabStripPane.frExtTextOutW(hDC, X, Y, wOptions, lpRect, lpString, nCount, lpDx)
End If
If pvCustomExtTextOutW = 0 Then
pvCustomExtTextOutW = ExtTextOutW(hDC, X, Y, wOptions, lpRect, lpString, nCount, lpDx)
End If
Exit Function
EH:
PrintError FUNC_NAME
Resume Next
End Function
Private Function pvEnumChildEdits(ByVal hWnd As Long, oCol As Collection) As Long
Select Case VBGetClassName(hWnd)
Case "Edit", "ThunderTextBox", "ThunderRT6TextBox"
oCol.Add hWnd
End Select
pvEnumChildEdits = 1
End Function