Skip to content

Commit b3d2406

Browse files
committed
Allow HighDPI sub-pixel drawing of frames
1 parent 10cb9f9 commit b3d2406

File tree

2 files changed

+89
-42
lines changed

2 files changed

+89
-42
lines changed

contrib/AlphaBlendLabel.ctl

+27-17
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ Attribute VB_Exposed = False
2626
'=========================================================================
2727
Option Explicit
2828
DefObj A-Z
29-
Private Const STR_MODULE_NAME As String = "AlphaBlendLabel"
29+
Private Const MODULE_NAME As String = "AlphaBlendLabel"
3030

3131
'=========================================================================
3232
' Public enums
@@ -60,7 +60,7 @@ End Enum
6060
'=========================================================================
6161

6262
Event Click()
63-
Event OwnerDraw(ByVal hGraphics As Long, ByVal hFont As Long, sCaption As String, lLeft As Long, lTop As Long, lWidth As Long, lHeight As Long)
63+
Event OwnerDraw(ByVal hGraphics As Long, ByVal hFont As Long, sCaption As String, sngLeft As Single, sngTop As Single, sngWidth As Single, sngHeight As Single)
6464
Event DblClick()
6565
Event ContextMenu()
6666
Event MouseDown(Button As Integer, Shift As Integer, X As Single, Y As Single)
@@ -79,6 +79,8 @@ 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+
'--- for GdipSetSmoothingMode
83+
Private Const SmoothingModeAntiAlias As Long = 4
8284

8385
Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (lpDst As Any, lpSrc As Any, ByVal ByteLength As Long)
8486
Private Declare Function CreateCompatibleDC Lib "gdi32" (ByVal hDC As Long) As Long
@@ -111,7 +113,8 @@ Private Declare Function GdipDeleteGraphics Lib "gdiplus" (ByVal hGraphics As Lo
111113
Private Declare Function GdipSetStringFormatFlags Lib "gdiplus" (ByVal hStringFormat As Long, ByVal lFlags As Long) As Long
112114
Private Declare Function GdipSetStringFormatAlign Lib "gdiplus" (ByVal hStringFormat As Long, ByVal eAlign As StringAlignment) As Long
113115
Private Declare Function GdipSetStringFormatLineAlign Lib "gdiplus" (ByVal hStringFormat As Long, ByVal eAlign As StringAlignment) As Long
114-
Private Declare Function GdipFillRectangleI Lib "gdiplus" (ByVal hGraphics As Long, ByVal hBrush As Long, ByVal lX As Long, ByVal lY As Long, ByVal lWidth As Long, ByVal lHeight As Long) As Long
116+
Private Declare Function GdipFillRectangle Lib "gdiplus" (ByVal hGraphics As Long, ByVal hBrush As Long, ByVal sngX As Single, ByVal sngY As Single, ByVal sngWidth As Single, ByVal sngHeight As Single) As Long
117+
Private Declare Function GdipSetSmoothingMode Lib "gdiplus" (ByVal hGraphics As Long, ByVal lSmoothingMd As Long) As Long
115118

116119
Private Type BITMAPINFOHEADER
117120
biSize As Long
@@ -209,7 +212,11 @@ Private m_sLastError As String
209212

210213
Private Function PrintError(sFunction As String) As VbMsgBoxResult
211214
m_sLastError = Err.Description
212-
Debug.Print "Critical error: " & Err.Description & " [" & STR_MODULE_NAME & "." & sFunction & "]", Timer
215+
#If USE_DEBUG_LOG <> 0 Then
216+
DebugLog MODULE_NAME, sFunction & "(" & Erl & ")", Err.Description & " &H" & Hex$(Err.Number), vbLogEventTypeError
217+
#Else
218+
Debug.Print "Critical error: " & Err.Description & " [" & MODULE_NAME & "." & sFunction & "]"
219+
#End If
213220
End Function
214221

215222
'=========================================================================
@@ -437,34 +444,37 @@ Private Function pvPaintControl(ByVal hDC As Long) As Boolean
437444
Dim hStringFormat As Long
438445
Dim hBrush As Long
439446
Dim uRect As RECTF
440-
Dim lLeft As Long
441-
Dim lTop As Long
442-
Dim lWidth As Long
443-
Dim lHeight As Long
447+
Dim sngLeft As Single
448+
Dim sngTop As Single
449+
Dim sngWidth As Single
450+
Dim sngHeight As Single
444451

445452
On Error GoTo EH
446453
If GdipCreateFromHDC(hDC, hGraphics) <> 0 Then
447454
GoTo QH
448455
End If
456+
If GdipSetSmoothingMode(hGraphics, SmoothingModeAntiAlias) <> 0 Then
457+
GoTo QH
458+
End If
449459
hFont = m_hFont
450460
sCaption = m_sCaption
451-
lWidth = ScaleWidth
452-
lHeight = ScaleHeight
453-
RaiseEvent OwnerDraw(hGraphics, hFont, sCaption, lLeft, lTop, lWidth, lHeight)
454-
If lWidth > 0 Then
461+
sngWidth = ScaleWidth
462+
sngHeight = ScaleHeight
463+
RaiseEvent OwnerDraw(hGraphics, hFont, sCaption, sngLeft, sngTop, sngWidth, sngHeight)
464+
If sngWidth > 0 Then
455465
If GdipCreateSolidFill(pvTranslateColor(m_clrBack, m_sngBackOpacity), hBrush) <> 0 Then
456466
GoTo QH
457467
End If
458-
If GdipFillRectangleI(hGraphics, hBrush, lLeft, lTop, lWidth, lHeight) <> 0 Then
468+
If GdipFillRectangle(hGraphics, hBrush, sngLeft + 0.5, sngTop + 0.5, sngWidth - 1, sngHeight - 1) <> 0 Then
459469
GoTo QH
460470
End If
461471
If Not pvPrepareStringFormat(m_eTextAlign Or m_eTextFlags, hStringFormat) Then
462472
GoTo QH
463473
End If
464-
uRect.Left = lLeft + m_sngTextOffsetX
465-
uRect.Top = lTop + m_sngTextOffsetY
466-
uRect.Right = lLeft + lWidth
467-
uRect.Bottom = lTop + lHeight
474+
uRect.Left = sngLeft + m_sngTextOffsetX
475+
uRect.Top = sngTop + m_sngTextOffsetY
476+
uRect.Right = sngLeft + sngWidth
477+
uRect.Bottom = sngTop + sngHeight
468478
If m_sngShadowOpacity <> 0 Then
469479
If GdipSetSolidFillColor(hBrush, pvTranslateColor(m_clrShadow, m_sngShadowOpacity)) <> 0 Then
470480
GoTo QH

contrib/AlphaBlendTabStrip.ctl

+62-25
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ Attribute VB_Exposed = False
6565
'=========================================================================
6666
Option Explicit
6767
DefObj A-Z
68-
Private Const STR_MODULE_NAME As String = "AlphaBlendTabStrip"
68+
Private Const MODULE_NAME As String = "AlphaBlendTabStrip"
6969

7070
'=========================================================================
7171
' Events
@@ -83,7 +83,7 @@ Private Declare Function OleTranslateColor Lib "oleaut32" (ByVal lOleColor As Lo
8383
'--- GDI+
8484
Private Declare Function GdipCreateSolidFill Lib "gdiplus" (ByVal argb As Long, hBrush As Long) As Long
8585
Private Declare Function GdipSetSolidFillColor Lib "gdiplus" (ByVal hBrush As Long, ByVal argb As Long) As Long
86-
Private Declare Function GdipFillRectangleI Lib "gdiplus" (ByVal hGraphics As Long, ByVal hBrush As Long, ByVal lX As Long, ByVal lY As Long, ByVal lWidth As Long, ByVal lHeight As Long) As Long
86+
Private Declare Function GdipFillRectangle Lib "gdiplus" (ByVal hGraphics As Long, ByVal hBrush As Long, ByVal sngX As Single, ByVal sngY As Single, ByVal sngWidth As Single, ByVal sngHeight As Single) As Long
8787
Private Declare Function GdipDeleteBrush Lib "gdiplus" (ByVal hBrush As Long) As Long
8888

8989
'=========================================================================
@@ -107,7 +107,11 @@ End Type
107107
'=========================================================================
108108

109109
Private Function PrintError(sFunction As String) As VbMsgBoxResult
110-
Debug.Print "Critical error: " & Err.Description & " [" & STR_MODULE_NAME & "." & sFunction & "]", Timer
110+
#If USE_DEBUG_LOG <> 0 Then
111+
DebugLog MODULE_NAME, sFunction & "(" & Erl & ")", Err.Description & " &H" & Hex$(Err.Number), vbLogEventTypeError
112+
#Else
113+
Debug.Print "Critical error: " & Err.Description & " [" & MODULE_NAME & "." & sFunction & "]"
114+
#End If
111115
End Function
112116

113117
'=========================================================================
@@ -166,6 +170,10 @@ Property Let TabCaption(ByVal Index As Long, sValue As String)
166170
pvResizeTabs
167171
End Property
168172

173+
Property Get TabCount() As Long
174+
TabCount = UBound(m_aTabCaptions) + 1
175+
End Property
176+
169177
'=========================================================================
170178
' Methods
171179
'=========================================================================
@@ -177,14 +185,17 @@ Private Sub pvLoadTabs()
177185
On Error GoTo EH
178186
For lIdx = 0 To UBound(m_aTabCaptions)
179187
If labTab.UBound < lIdx + 1 Then
188+
On Error GoTo QH
180189
Load labTab(lIdx + 1)
190+
On Error GoTo EH
181191
labTab(lIdx + 1).ZOrder vbBringToFront
182192
labTab(lIdx + 1).BackColor = vbButtonFace
183193
End If
184194
Next
185195
For lIdx = lIdx + 1 To labTab.UBound
186196
Unload labTab(lIdx)
187197
Next
198+
QH:
188199
Exit Sub
189200
EH:
190201
PrintError FUNC_NAME
@@ -199,9 +210,9 @@ Private Sub pvResizeTabs()
199210

200211
On Error GoTo EH
201212
labBackgr.Move 0, 0, ScaleWidth, ScaleHeight
202-
lTop = labBackgr.Top + 30
203-
lLeft = labBackgr.Left + 90
204-
lHeight = labBackgr.Height - 30
213+
lTop = labBackgr.Top + IconScale(3) * ScreenTwipsPerPixelY
214+
lLeft = labBackgr.Left + IconScale(6) * ScreenTwipsPerPixelX
215+
lHeight = labBackgr.Height - IconScale(3) * ScreenTwipsPerPixelY
205216
For lIdx = 0 To labTab.UBound - 1
206217
With labTab(lIdx + 1)
207218
.Visible = False
@@ -269,72 +280,78 @@ EH:
269280
PrintError FUNC_NAME
270281
End Sub
271282

272-
Private Sub labTab_OwnerDraw(Index As Integer, ByVal hGraphics As Long, ByVal hFont As Long, sCaption As String, lLeft As Long, lTop As Long, lWidth As Long, lHeight As Long)
283+
Private Sub labTab_OwnerDraw(Index As Integer, ByVal hGraphics As Long, ByVal hFont As Long, sCaption As String, sngLeft As Single, sngTop As Single, sngWidth As Single, sngHeight As Single)
273284
Const FUNC_NAME As String = "labTab_OwnerDraw"
274285
Dim clrLight As Long
286+
Dim sngPixel As Single
275287

276288
On Error GoTo EH
289+
sngPixel = IconScale(16!) / 16!
277290
If Index - 1 = m_lCurrentTab Then
278291
clrLight = pvTranslateColor(vbWindowBackground)
279-
pvDrawRect hGraphics, 0, 0, lWidth, lHeight - 1, clrLight, clrLight, pvTranslateColor(vbWindowText), pvTranslateColor(vbButtonFace)
280-
lLeft = lLeft + 1
281-
lWidth = lWidth - 2
292+
pvDrawRect hGraphics, 0, 0, sngWidth, sngHeight, clrLight, clrLight, pvTranslateColor(vbWindowText), pvTranslateColor(vbButtonFace)
293+
sngLeft = sngLeft + sngPixel
294+
sngWidth = sngWidth - 2 * sngPixel
282295
ElseIf Index <> m_lCurrentTab Then
283-
pvDrawRect hGraphics, 0, 3, lWidth, lHeight - 8, 0, 0, pvTranslateColor(vbWindowText, 0.5), 0
284-
lWidth = lWidth - 1
296+
pvDrawRect hGraphics, 0, 3 * sngPixel, sngWidth, sngHeight - 6 * sngPixel, 0, 0, pvTranslateColor(vbWindowText, 0.5), 0
297+
sngWidth = sngWidth - sngPixel
285298
End If
286-
lTop = lTop + 1
287-
lHeight = lHeight - 2
299+
sngTop = sngTop + sngPixel
300+
sngHeight = sngHeight - 2 * sngPixel
288301
Exit Sub
289302
EH:
290303
PrintError FUNC_NAME
291304
End Sub
292305

293-
Private Sub labBackgr_OwnerDraw(ByVal hGraphics As Long, ByVal hFont As Long, sCaption As String, lLeft As Long, lTop As Long, lWidth As Long, lHeight As Long)
306+
Private Sub labBackgr_OwnerDraw(ByVal hGraphics As Long, ByVal hFont As Long, sCaption As String, sngLeft As Single, sngTop As Single, sngWidth As Single, sngHeight As Single)
294307
Const FUNC_NAME As String = "labBackgr_OwnerDraw"
295308
Dim clrDark As Long
309+
Dim sngPixel As Single
296310

297311
On Error GoTo EH
312+
sngPixel = IconScale(16!) / 16!
298313
clrDark = pvTranslateColor(vbWindowText, 0.25)
299-
pvDrawRect hGraphics, 0, 0, lWidth, lHeight, clrDark, clrDark, clrDark, pvTranslateColor(vbWindowBackground)
300-
lLeft = lLeft + 1
301-
lTop = lTop + 1
302-
lWidth = lWidth - 2
303-
lHeight = lHeight - 1
314+
pvDrawRect hGraphics, 0, 0, sngWidth, sngHeight, clrDark, clrDark, clrDark, pvTranslateColor(vbWindowBackground)
315+
sngLeft = sngLeft + sngPixel
316+
sngTop = sngTop + sngPixel
317+
sngWidth = sngWidth - 2 * sngPixel
318+
sngHeight = sngHeight - sngPixel
304319
Exit Sub
305320
EH:
306321
PrintError FUNC_NAME
307322
End Sub
308323

309324
Private Function pvDrawRect(ByVal hGraphics As Long, _
310-
ByVal lLeft As Long, ByVal lTop As Long, ByVal lWidth As Long, ByVal lHeight As Long, _
325+
ByVal sngLeft As Single, ByVal sngTop As Single, ByVal sngWidth As Single, ByVal sngHeight As Single, _
311326
ByVal clrLeft As Long, ByVal clrTop As Long, ByVal clrRight As Long, ByVal clrBottom As Long) As Boolean
312327
Const FUNC_NAME As String = "pvDrawRect"
313328
Dim hBrush As Long
329+
Dim sngPixel As Single
314330

315331
On Error GoTo EH
332+
sngPixel = IconScale(16!) / 16!
316333
If GdipCreateSolidFill(clrLeft, hBrush) <> 0 Then
317334
GoTo QH
318335
End If
319-
If GdipFillRectangleI(hGraphics, hBrush, lLeft, lTop, 1, lHeight) <> 0 Then
336+
If GdipFillRectangle(hGraphics, hBrush, sngLeft + 0.5, sngTop + 0.5, sngPixel, sngHeight) <> 0 Then
320337
GoTo QH
321338
End If
322339
If GdipSetSolidFillColor(hBrush, clrTop) <> 0 Then
323340
GoTo QH
324341
End If
325-
If GdipFillRectangleI(hGraphics, hBrush, lLeft + 1, lTop, lWidth, 1) <> 0 Then
342+
If GdipFillRectangle(hGraphics, hBrush, sngLeft + 0.5 + sngPixel, sngTop + 0.5, sngWidth, sngPixel) <> 0 Then
326343
GoTo QH
327344
End If
328345
If GdipSetSolidFillColor(hBrush, clrRight) <> 0 Then
329346
GoTo QH
330347
End If
331-
If GdipFillRectangleI(hGraphics, hBrush, lLeft + lWidth - 1, lTop + 1, 1, lHeight) <> 0 Then
348+
If GdipFillRectangle(hGraphics, hBrush, sngLeft + sngWidth - 0.5 - sngPixel, sngTop + 0.5 + sngPixel, sngPixel, sngHeight - sngPixel) <> 0 Then
332349
GoTo QH
333350
End If
334351
If GdipSetSolidFillColor(hBrush, clrBottom) <> 0 Then
335352
GoTo QH
336353
End If
337-
If GdipFillRectangleI(hGraphics, hBrush, lLeft + 1, lTop + lHeight, lWidth - 1, 1) <> 0 Then
354+
If GdipFillRectangle(hGraphics, hBrush, sngLeft + 0.5 + sngPixel, sngTop + sngHeight - 0.5 - sngPixel, sngWidth - 2 * sngPixel - 1, sngPixel) <> 0 Then
338355
GoTo QH
339356
End If
340357
pvDrawRect = True
@@ -349,6 +366,26 @@ EH:
349366
Resume QH
350367
End Function
351368

369+
Private Property Get ScreenTwipsPerPixelX() As Single
370+
ScreenTwipsPerPixelX = Screen.TwipsPerPixelX
371+
End Property
372+
373+
Private Property Get ScreenTwipsPerPixelY() As Single
374+
ScreenTwipsPerPixelY = Screen.TwipsPerPixelY
375+
End Property
376+
377+
Private Function IconScale(ByVal sngSize As Single) As Long
378+
If ScreenTwipsPerPixelX < 6.5 Then
379+
IconScale = Int(sngSize * 3)
380+
ElseIf ScreenTwipsPerPixelX < 9.5 Then
381+
IconScale = Int(sngSize * 2)
382+
ElseIf ScreenTwipsPerPixelX < 11.5 Then
383+
IconScale = Int(sngSize * 3 \ 2)
384+
Else
385+
IconScale = Int(sngSize * 1)
386+
End If
387+
End Function
388+
352389
'=========================================================================
353390
' Base class events
354391
'=========================================================================

0 commit comments

Comments
 (0)