Skip to content

Commit 8d49985

Browse files
committed
Allow graceful degrade on older OSes by using native GDI
1 parent b3d2406 commit 8d49985

File tree

3 files changed

+159
-72
lines changed

3 files changed

+159
-72
lines changed

contrib/AlphaBlendLabel.ctl

+147-66
Original file line numberDiff line numberDiff line change
@@ -32,27 +32,27 @@ Private Const MODULE_NAME As String = "AlphaBlendLabel"
3232
' Public enums
3333
'=========================================================================
3434

35-
Public Enum UcsTextAlignEnum
36-
ucsBflHorLeft = 0
37-
ucsBflHorCenter = 1
38-
ucsBflHorRight = 2
39-
ucsBflVertTop = 0
40-
ucsBflVertCenter = 4
41-
ucsBflVertBottom = 8
42-
ucsBflCenter = ucsBflHorCenter Or ucsBflVertCenter
35+
Public Enum UcsLabelTextAlignEnum
36+
ucsLtaHorLeft = 0
37+
ucsLtaHorCenter = 1
38+
ucsLtaHorRight = 2
39+
ucsLtaVertTop = 0
40+
ucsLtaVertCenter = 4
41+
ucsLtaVertBottom = 8
42+
ucsLtaCenter = ucsLtaHorCenter Or ucsLtaVertCenter
4343
End Enum
4444

45-
Public Enum UcsTextFlagsEnum
46-
ucsBflNone = 0
47-
ucsBflDirectionRightToLeft = &H1 * 16
48-
ucsBflDirectionVertical = &H2 * 16
49-
ucsBflNoFitBlackBox = &H4 * 16
50-
ucsBflDisplayFormatControl = &H20 * 16
51-
ucsBflNoFontFallback = &H400 * 16
52-
ucsBflMeasureTrailingSpaces = &H800& * 16
53-
ucsBflNoWrap = &H1000& * 16
54-
ucsBflLineLimit = &H2000& * 16
55-
ucsBflNoClip = &H4000& * 16
45+
Public Enum UcsLabelTextFlagsEnum
46+
ucsLtfNone = 0
47+
ucsLtfDirectionRightToLeft = &H1 * 16
48+
ucsLtfDirectionVertical = &H2 * 16
49+
ucsLtfNoFitBlackBox = &H4 * 16
50+
ucsLtfDisplayFormatControl = &H20 * 16
51+
ucsLtfNoFontFallback = &H400 * 16
52+
ucsLtfMeasureTrailingSpaces = &H800& * 16
53+
ucsLtfNoWrap = &H1000& * 16
54+
ucsLtfLineLimit = &H2000& * 16
55+
ucsLtfNoClip = &H4000& * 16
5656
End Enum
5757

5858
'=========================================================================
@@ -79,8 +79,10 @@ Private Const AC_SRC_ALPHA As Long = 1
7979
Private Const UnitPoint As Long = 3
8080
'--- for GdipSetTextRenderingHint
8181
Private Const TextRenderingHintAntiAlias As Long = 4
82+
Private Const TextRenderingHintClearTypeGridFit As Long = 5
8283
'--- for GdipSetSmoothingMode
8384
Private Const SmoothingModeAntiAlias As Long = 4
85+
Private Const DT_CALCRECT As Long = &H400
8486

8587
Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (lpDst As Any, lpSrc As Any, ByVal ByteLength As Long)
8688
Private Declare Function CreateCompatibleDC Lib "gdi32" (ByVal hDC As Long) As Long
@@ -93,6 +95,7 @@ Private Declare Function GetModuleHandle Lib "kernel32" Alias "GetModuleHandleA"
9395
Private Declare Function OleTranslateColor Lib "oleaut32" (ByVal lOleColor As Long, ByVal lHPalette As Long, ByVal lColorRef As Long) As Long
9496
Private Declare Function GetDC Lib "user32" (ByVal hWnd As Long) As Long
9597
Private Declare Function ReleaseDC Lib "user32" (ByVal hWnd As Long, ByVal hDC As Long) As Long
98+
Private Declare Function DrawText Lib "user32" Alias "DrawTextA" (ByVal hDC As Long, ByVal lpStr As String, ByVal nCount As Long, lpRect As Any, ByVal wFormat As Long) As Long
9699
'--- GDI+
97100
Private Declare Function GdiplusStartup Lib "gdiplus" (hToken As Long, pInputBuf As Any, Optional ByVal pOutputBuf As Long = 0) As Long
98101
Private Declare Function GdipCreateFontFamilyFromName Lib "gdiplus" (ByVal lNamePtr As Long, ByVal hFontCollection As Long, hFontFamily As Long) As Long
@@ -175,7 +178,7 @@ Private Const DEF_SHADOWOFFSETX As Single = 1
175178
Private Const DEF_SHADOWOFFSETY As Single = 1
176179
Private Const DEF_SHADOWCOLOR As Long = vbBlack
177180
Private Const DEF_SHADOWOPACITY As Single = 0
178-
Private Const DEF_TEXTALIGN As Long = ucsBflCenter
181+
Private Const DEF_TEXTALIGN As Long = ucsLtaCenter
179182
Private Const DEF_TEXTFLAGS As Long = 0
180183

181184
Private m_bAutoRedraw As Boolean
@@ -193,8 +196,8 @@ Private m_sngShadowOffsetX As Single
193196
Private m_sngShadowOffsetY As Single
194197
Private m_clrShadow As OLE_COLOR
195198
Private m_sngShadowOpacity As Single
196-
Private m_eTextAlign As UcsTextAlignEnum
197-
Private m_eTextFlags As UcsTextFlagsEnum
199+
Private m_eTextAlign As UcsLabelTextAlignEnum
200+
Private m_eTextFlags As UcsLabelTextFlagsEnum
198201
'--- run-time
199202
Private m_bShown As Boolean
200203
Private m_eContainerScaleMode As ScaleModeConstants
@@ -404,38 +407,123 @@ Property Let ShadowOpacity(ByVal sngValue As Single)
404407
End If
405408
End Property
406409

407-
Property Get TextAlign() As UcsTextAlignEnum
410+
Property Get TextAlign() As UcsLabelTextAlignEnum
408411
TextAlign = m_eTextAlign
409412
End Property
410413

411-
Property Let TextAlign(ByVal eValue As UcsTextAlignEnum)
414+
Property Let TextAlign(ByVal eValue As UcsLabelTextAlignEnum)
412415
If m_eTextAlign <> eValue Then
413416
m_eTextAlign = eValue
414417
pvRefresh
415418
PropertyChanged
416419
End If
417420
End Property
418421

419-
Property Get TextFlags() As UcsTextFlagsEnum
422+
Property Get TextFlags() As UcsLabelTextFlagsEnum
420423
TextFlags = m_eTextFlags
421424
End Property
422425

423-
Property Let TextFlags(ByVal eValue As UcsTextFlagsEnum)
426+
Property Let TextFlags(ByVal eValue As UcsLabelTextFlagsEnum)
424427
If m_eTextFlags <> eValue Then
425428
m_eTextFlags = eValue
429+
If m_bAutoSize And TypeOf Extender Is VBControlExtender Then
430+
pvSizeExtender Extender
431+
End If
426432
pvRefresh
427433
PropertyChanged
428434
End If
429435
End Property
430436

437+
Property Get WordWrap() As Boolean
438+
WordWrap = (m_eTextFlags And ucsLtfNoWrap) = 0
439+
End Property
440+
441+
Property Let WordWrap(ByVal bValue As Boolean)
442+
If bValue Then
443+
TextFlags = m_eTextFlags And Not ucsLtfNoWrap
444+
Else
445+
TextFlags = m_eTextFlags Or ucsLtfNoWrap
446+
End If
447+
End Property
448+
431449
Property Get LastError() As String
432450
LastError = m_sLastError
433451
End Property
434452

435453
'=========================================================================
436-
' Method
454+
' Methods
437455
'=========================================================================
438456

457+
Public Function MeasureString(sCaption As String, sngWidth As Single, sngHeight As Single) As Boolean
458+
Dim hDC As Long
459+
Dim hGraphics As Long
460+
Dim uRect As RECTF
461+
Dim uBounds As RECTF
462+
Dim rcRect(0 To 3) As Long
463+
Dim pFont As IFont
464+
Dim hPrevFont As Long
465+
Dim hStringFormat As Long
466+
467+
hDC = GetDC(ContainerHwnd)
468+
If hDC = 0 Then
469+
GoTo QH
470+
End If
471+
If m_hFont <> 0 Then
472+
If GdipCreateFromHDC(hDC, hGraphics) <> 0 Then
473+
GoTo QH
474+
End If
475+
If GdipSetSmoothingMode(hGraphics, SmoothingModeAntiAlias) <> 0 Then
476+
GoTo QH
477+
End If
478+
If GdipSetTextRenderingHint(hGraphics, IIf(m_bAutoRedraw, TextRenderingHintAntiAlias, TextRenderingHintClearTypeGridFit)) <> 0 Then
479+
GoTo QH
480+
End If
481+
If Not pvPrepareStringFormat(m_eTextAlign Or m_eTextFlags, hStringFormat) Then
482+
GoTo QH
483+
End If
484+
uRect.Right = ScaleX(sngWidth, m_eContainerScaleMode, vbPixels)
485+
uRect.Bottom = ScaleY(sngHeight, m_eContainerScaleMode, vbPixels)
486+
If GdipMeasureString(hGraphics, StrPtr(sCaption), Len(sCaption), m_hFont, uRect, hStringFormat, uBounds, 0, 0) <> 0 Then
487+
GoTo QH
488+
End If
489+
'--- ceil
490+
sngWidth = -Int(-uBounds.Right)
491+
sngHeight = -Int(-uBounds.Bottom)
492+
Else
493+
Set pFont = m_oFont
494+
hPrevFont = SelectObject(hDC, pFont.hFont)
495+
rcRect(2) = ScaleX(sngWidth, m_eContainerScaleMode, vbPixels)
496+
rcRect(3) = ScaleY(sngHeight, m_eContainerScaleMode, vbPixels)
497+
Call DrawText(hDC, sCaption, Len(sCaption), rcRect(0), DT_CALCRECT)
498+
Call SelectObject(hDC, hPrevFont)
499+
sngWidth = rcRect(2)
500+
sngHeight = rcRect(3)
501+
End If
502+
sngWidth = ScaleY(sngWidth, vbPixels, m_eContainerScaleMode)
503+
sngHeight = ScaleY(sngHeight, vbPixels, m_eContainerScaleMode)
504+
'--- success
505+
MeasureString = True
506+
QH:
507+
If hStringFormat <> 0 Then
508+
Call GdipDeleteStringFormat(hStringFormat)
509+
hStringFormat = 0
510+
End If
511+
If hGraphics <> 0 Then
512+
Call GdipDeleteGraphics(hGraphics)
513+
hGraphics = 0
514+
End If
515+
If hDC <> 0 Then
516+
Call ReleaseDC(ContainerHwnd, hDC)
517+
hDC = 0
518+
End If
519+
End Function
520+
521+
Public Sub Refresh()
522+
UserControl.Refresh
523+
End Sub
524+
525+
'= private ===============================================================
526+
439527
Private Function pvPaintControl(ByVal hDC As Long) As Boolean
440528
Const FUNC_NAME As String = "pvPaintControl"
441529
Dim hGraphics As Long
@@ -448,14 +536,29 @@ Private Function pvPaintControl(ByVal hDC As Long) As Boolean
448536
Dim sngTop As Single
449537
Dim sngWidth As Single
450538
Dim sngHeight As Single
539+
Dim rcRect(0 To 3) As Long
540+
Dim pFont As IFont
541+
Dim hPrevFont As Long
451542

452543
On Error GoTo EH
544+
If GetModuleHandle("gdiplus") = 0 Then
545+
rcRect(2) = ScaleX(ScaleWidth, ScaleMode, vbPixels)
546+
rcRect(3) = ScaleY(ScaleHeight, ScaleMode, vbPixels)
547+
Set pFont = m_oFont
548+
hPrevFont = SelectObject(hDC, pFont.hFont)
549+
Call DrawText(hDC, m_sCaption, -1, rcRect(0), 0)
550+
Call SelectObject(hDC, hPrevFont)
551+
GoTo QH
552+
End If
453553
If GdipCreateFromHDC(hDC, hGraphics) <> 0 Then
454554
GoTo QH
455555
End If
456556
If GdipSetSmoothingMode(hGraphics, SmoothingModeAntiAlias) <> 0 Then
457557
GoTo QH
458558
End If
559+
If GdipSetTextRenderingHint(hGraphics, IIf(m_bAutoRedraw, TextRenderingHintAntiAlias, TextRenderingHintClearTypeGridFit)) <> 0 Then
560+
GoTo QH
561+
End If
459562
hFont = m_hFont
460563
sCaption = m_sCaption
461564
sngWidth = ScaleWidth
@@ -479,9 +582,6 @@ Private Function pvPaintControl(ByVal hDC As Long) As Boolean
479582
If GdipSetSolidFillColor(hBrush, pvTranslateColor(m_clrShadow, m_sngShadowOpacity)) <> 0 Then
480583
GoTo QH
481584
End If
482-
If GdipSetTextRenderingHint(hGraphics, TextRenderingHintAntiAlias) <> 0 Then
483-
GoTo QH
484-
End If
485585
uRect.Left = uRect.Left + m_sngShadowOffsetX
486586
uRect.Top = uRect.Top + m_sngShadowOffsetY
487587
If GdipDrawString(hGraphics, StrPtr(sCaption), -1, hFont, uRect, hStringFormat, hBrush) <> 0 Then
@@ -530,6 +630,9 @@ Private Function pvPrepareFont(oFont As StdFont, hFont As Long) As Boolean
530630
Dim eStyle As FontStyle
531631

532632
On Error GoTo EH
633+
If GetModuleHandle("gdiplus") = 0 Then
634+
GoTo QH
635+
End If
533636
If oFont Is Nothing Then
534637
GoTo QH
535638
End If
@@ -642,38 +745,17 @@ Private Sub pvHandleMouseDown(Button As Integer, Shift As Integer, X As Single,
642745
End Sub
643746

644747
Private Sub pvSizeExtender(oExt As VBControlExtender)
645-
Dim hDC As Long
646-
Dim hGraphics As Long
647748
Dim sngWidth As Single
648749
Dim sngHeight As Single
649-
Dim uBounds As RECTF
650750

651-
If m_hFont = 0 Then
652-
GoTo QH
751+
If WordWrap Then
752+
sngWidth = oExt.Width
653753
End If
654-
hDC = GetDC(ContainerHwnd)
655-
If hDC = 0 Then
656-
GoTo QH
657-
End If
658-
If GdipCreateFromHDC(hDC, hGraphics) <> 0 Then
659-
GoTo QH
660-
End If
661-
If GdipMeasureString(hGraphics, StrPtr(m_sCaption), -1, m_hFont, uBounds, 0, uBounds, 0, 0) <> 0 Then
662-
GoTo QH
663-
End If
664-
'--- ceil
665-
sngWidth = -Int(-uBounds.Right)
666-
sngHeight = -Int(-uBounds.Bottom)
667-
oExt.Width = ScaleX(sngWidth, vbPixels, m_eContainerScaleMode)
668-
oExt.Height = ScaleY(sngHeight, vbPixels, m_eContainerScaleMode)
669-
QH:
670-
If hGraphics <> 0 Then
671-
Call GdipDeleteGraphics(hGraphics)
672-
hGraphics = 0
673-
End If
674-
If hDC <> 0 Then
675-
Call ReleaseDC(ContainerHwnd, hDC)
676-
hDC = 0
754+
If MeasureString(m_sCaption, sngWidth, sngHeight) Then
755+
If Not WordWrap Then
756+
oExt.Width = sngWidth
757+
End If
758+
oExt.Height = sngHeight
677759
End If
678760
End Sub
679761

@@ -892,9 +974,6 @@ Private Sub UserControl_ReadProperties(PropBag As PropertyBag)
892974
m_eTextFlags = .ReadProperty("TextFlags", DEF_TEXTFLAGS)
893975
End With
894976
pvPrepareFont m_oFont, m_hFont
895-
If m_bAutoSize And TypeOf Extender Is VBControlExtender Then
896-
pvSizeExtender Extender
897-
End If
898977
QH:
899978
Exit Sub
900979
EH:
@@ -931,11 +1010,11 @@ EH:
9311010
Resume QH
9321011
End Sub
9331012

934-
Private Sub UserControl_AmbientChanged(PropertyName As String)
935-
If PropertyName = "ScaleUnits" Then
936-
m_eContainerScaleMode = ToScaleMode(Ambient.ScaleUnits)
937-
End If
938-
End Sub
1013+
'Private Sub UserControl_AmbientChanged(PropertyName As String)
1014+
' If PropertyName = "ScaleUnits" Then
1015+
' m_eContainerScaleMode = ToScaleMode(Ambient.ScaleUnits)
1016+
' End If
1017+
'End Sub
9391018

9401019
'=========================================================================
9411020
' Base class events
@@ -946,7 +1025,9 @@ Private Sub UserControl_Initialize()
9461025

9471026
If GetModuleHandle("gdiplus") = 0 Then
9481027
aInput(0) = 1
1028+
On Error Resume Next
9491029
Call GdiplusStartup(0, aInput(0))
1030+
On Error GoTo 0
9501031
End If
9511032
m_eContainerScaleMode = vbTwips
9521033
End Sub

contrib/AlphaBlendTabStrip.ctl

+5
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ Begin VB.UserControl AlphaBlendTabStrip
3030
Strikethrough = 0 'False
3131
EndProperty
3232
ForeOpacity = 0.75
33+
TextFlags = 65536
3334
End
3435
Begin Project1.AlphaBlendLabel labBackgr
3536
Height = 390
@@ -80,6 +81,7 @@ Event BeforeClick(TabIndex As Long, Cancel As Boolean)
8081

8182
Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (lpDst As Any, lpSrc As Any, ByVal ByteLength As Long)
8283
Private Declare Function OleTranslateColor Lib "oleaut32" (ByVal lOleColor As Long, ByVal lHPalette As Long, ByVal lColorRef As Long) As Long
84+
Private Declare Function GetModuleHandle Lib "kernel32" Alias "GetModuleHandleA" (ByVal lpModuleName As String) As Long
8385
'--- GDI+
8486
Private Declare Function GdipCreateSolidFill Lib "gdiplus" (ByVal argb As Long, hBrush As Long) As Long
8587
Private Declare Function GdipSetSolidFillColor Lib "gdiplus" (ByVal hBrush As Long, ByVal argb As Long) As Long
@@ -329,6 +331,9 @@ Private Function pvDrawRect(ByVal hGraphics As Long, _
329331
Dim sngPixel As Single
330332

331333
On Error GoTo EH
334+
If GetModuleHandle("gdiplus") = 0 Then
335+
GoTo QH
336+
End If
332337
sngPixel = IconScale(16!) / 16!
333338
If GdipCreateSolidFill(clrLeft, hBrush) <> 0 Then
334339
GoTo QH

test/tabstrip/Form1.frm

+7-6
Original file line numberDiff line numberDiff line change
@@ -37,12 +37,13 @@ Begin VB.Form Form1
3737
Layout = "Printers|Configuration|Logs"
3838
End
3939
Begin Project1.AlphaBlendLabel AlphaBlendLabel1
40-
Height = 1608
41-
Left = 336
42-
Top = 252
43-
Width = 4464
44-
_ExtentX = 7874
45-
_ExtentY = 2836
40+
Height = 2112
41+
Left = 1344
42+
Top = 336
43+
Width = 3180
44+
_ExtentX = 5609
45+
_ExtentY = 3725
46+
AutoSize = -1 'True
4647
Caption = "This is a test of the wrap mode This is a test of the wrap mode"
4748
BeginProperty Font {0BE35203-8F91-11CE-9DE3-00AA004BB851}
4849
Name = "PT Sans Narrow"

0 commit comments

Comments
 (0)