Option Explicit
#If Win64 Then
Dim hwnd As LongPtr, hDc As LongPtr
Dim hFillBrush() As LongPtr, hFrameBrush() As LongPtr
#Else
Dim hwnd As Long, hDc As Long
Dim hFillBrush() As Long, hFrameBrush() As Long
#End If
#If Win64 Then
Private Declare PtrSafe Function IUnknown_GetWindow Lib "shlwapi" Alias "#172" (ByVal pIUnk As IUnknown, ByVal hwnd As LongPtr) As Long
Private Declare PtrSafe Function CreateSolidBrush Lib "gdi32" (ByVal crColor As Long) As LongPtr
Private Declare PtrSafe Function DeleteObject Lib "gdi32" (ByVal hObject As LongPtr) As LongPtr
Private Declare PtrSafe Function CreatePolygonRgn Lib "gdi32" (lpPoint As Any, ByVal nCount As Long, ByVal nPolyFillMode As Long) As Long
Private Declare PtrSafe Function Polygon Lib "gdi32" (ByVal lShapeDC As LongPtr, lpPoint As Any, ByVal nCount As Long) As Long
Private Declare PtrSafe Function CreateRectRgn Lib "gdi32" (ByVal x1 As Long, ByVal y1 As Long, ByVal x2 As Long, ByVal y2 As Long) As LongPtr
Private Declare PtrSafe Function CreateEllipticRgn Lib "gdi32" (ByVal x1 As Long, ByVal y1 As Long, ByVal x2 As Long, ByVal y2 As Long) As LongPtr
Private Declare PtrSafe Function FillRgn Lib "gdi32" (ByVal lShapeDC As LongPtr, ByVal hRgn As LongPtr, ByVal hFrameBrush As LongPtr) As Long
Private Declare PtrSafe Function FrameRgn Lib "gdi32" (ByVal lShapeDC As LongPtr, ByVal hRgn As LongPtr, ByVal hFrameBrush As LongPtr, ByVal nWidth As Long, ByVal nHeight As Long) As Long
Private Declare PtrSafe Function GetDC Lib "user32.dll" (ByVal hwnd As LongPtr) As LongPtr
Private Declare PtrSafe Function ReleaseDC Lib "user32" (ByVal hwnd As LongPtr, ByVal hdc1 As LongPtr) As Long
'Private Declare PtrSafe Function SendMessage Lib "user32.dll" Alias "SendMessageA" (ByVal hwnd As LongPtr, ByVal wMsg As Long, ByVal wParam As LongPtr, ByRef lParam As Any) As LongPtr
Private Declare PtrSafe Function SendMessage Lib "user32.dll" Alias "SendMessageA" (ByVal hwnd As LongPtr, ByVal wMsg As Long, ByVal wParam As Long, lParam As Any) As LongPtr ' if error, try wParam As LongPtr
#Else
Private Declare Function IUnknown_GetWindow Lib "shlwapi" Alias "#172" (ByVal pIUnk As IUnknown, ByVal hwnd As Long) As Long
Private Declare Function FindWindow Lib "user32.dll" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As Long
Private Declare Function CreateSolidBrush Lib "gdi32" (ByVal crColor As Long) As Long
Private Declare Function DeleteObject Lib "gdi32" (ByVal hObject As Long) As Long
Private Declare Function CreatePolygonRgn Lib "gdi32" (lpPoint As Any, ByVal nCount As Long, ByVal nPolyFillMode As Long) As Long
Private Declare Function Polygon Lib "gdi32" (ByVal lShapeDC As Long, lpPoint As Any, ByVal nCount As Long) As Long
Private Declare Function CreateRectRgn Lib "gdi32" (ByVal x1 As Long, ByVal y1 As Long, ByVal x2 As Long, ByVal y2 As Long) As Long
Private Declare Function CreateEllipticRgn Lib "gdi32" (ByVal x1 As Long, ByVal y1 As Long, ByVal x2 As Long, ByVal y2 As Long) As Long
Private Declare Function FillRgn Lib "gdi32" (ByVal lShapeDC As Long, ByVal hRgn As Long, ByVal hFrameBrush As Long) As Long
Private Declare Function FrameRgn Lib "gdi32" (ByVal lShapeDC As Long, ByVal hRgn As Long, ByVal hFrameBrush As Long, ByVal nWidth As Long, ByVal nHeight As Long) As Long
Private Declare Function GetDC Lib "user32.dll" (ByVal hwnd As Long) As Long
Private Declare Function ReleaseDC Lib "user32" (ByVal hwnd As Long, ByVal hdc1 As Long) As Long
' Private Declare Function SendMessage Lib "user32.dll" Alias "SendMessageA" (ByVal hWnd As Long, ByVal wMsg As Long, ByVal wParam As Long, ByRef lParam As Any) As Long
Private Declare Function SendMessage Lib "user32.dll" Alias "SendMessageA" (ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, ByRef lParam As Long) As Long
#End If
''!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
'Property Let ScreenUpdating(ByVal vNewValue As Boolean)
' Const WM_SETREDRAW = &HB
' '#If Win64 Then
' ' Dim Hwnd As LongPtr
' '#Else
' ' Dim Hwnd As Long
' '#End If
' 'Call IUnknown_GetWindow(Me, VarPtr(Hwnd))
' Call SendMessage(hwnd, ByVal WM_SETREDRAW, ByVal CLng(vNewValue), 0)
'End Property
'
'Private Sub NotRefresh()
' On Error GoTo errHandler
' Me.ScreenUpdating = False
' 'With Me.Controls.Add("Forms.TextBox.1", "TextBox1", False)
' ' .Top = 20
' ' .Left = 20
' ' .Visible = True
' 'End With
' Me.Hide
' Me.Show
'errHandler:
' Call cmdRefresher_Click 'Me.ScreenUpdating = True ' this line gives me bug on Office 2019 x32
'End Sub
'Private Sub cmdRefresher_Click()
''Stop
' Me.ScreenUpdating = True
'End Sub
''Private Sub Refresher()
'' Me.ScreenUpdating = True
''End Sub
''!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
Private Sub cmdExit_Click()
Unload Me
End Sub
Private Sub UserForm_Initialize()
'If IsMissing(Fill) Then Fill = vbWhite
ReDim hFillBrush(0 To 56)
ReDim hFrameBrush(0 To 56)
Dim lgColor As Long
Dim strColor As String
For lgColor = LBound(hFillBrush) To UBound(hFillBrush)
ActiveCell.Interior.ColorIndex = lgColor
'strColor = VBA.Hex(ActiveCell.Interior.Color)
'strColor = VBA.Right("000000" & strColor, 6)
'Excel shows nibbles in reverse order so make it as RGB
strColor = VBA.Right(strColor, 2) & VBA.Mid(strColor, 3, 2) & VBA.Left(strColor, 2)
'to get each byte component from the RGB value: VBA.cDec("&H" & --)
hFillBrush(lgColor) = CreateSolidBrush(ActiveCell.Interior.Color)
hFrameBrush(lgColor) = CreateSolidBrush(ActiveCell.Interior.Color)
Next lgColor
'Call NotRefresh
Call IUnknown_GetWindow(Me, VarPtr(hwnd))
hDc = GetDC(hwnd)
End Sub
Private Sub UserForm_Activate()
Dim cnt As Long
Dim startTime As Date
Dim lgColor As Long
startTime = Timer
For cnt = 1 To 1
lgColor = VBA.CInt(VBA.Rnd() * 16)
Call AddShape(hDc, triangle, 100, 0, 200, 200, hFillBrush(lgColor), hFrameBrush(lgColor))
lgColor = VBA.CInt(VBA.Rnd() * 16)
Call AddShape(hDc, Ellipse, 200, 50, 150, 100, hFillBrush(lgColor), hFrameBrush(lgColor))
lgColor = VBA.CInt(VBA.Rnd() * 16)
Call AddShape(hDc, Ellipse, 200, 150, 250, 250, hFillBrush(lgColor), hFrameBrush(lgColor))
DoEvents
Next cnt
MsgBox "Test completed: " & VBA.Format((Timer - startTime) / 86400, "hh:mm:ss")
End Sub
Private Sub UserForm_Terminate()
Dim lgColor As Long
Call ReleaseDC(hwnd, hDc)
For lgColor = LBound(hFillBrush) To UBound(hFillBrush)
Call DeleteObject(hFillBrush(lgColor))
Call DeleteObject(hFrameBrush(lgColor))
Next lgColor
Erase hFillBrush()
Erase hFrameBrush()
End Sub
#If Win64 Then
Private Sub AddShape(hDc As LongPtr, _
eShape As Shp, _
Left As Long, _
Top As Long, _
Width As Long, _
Height As Long, _
Optional hFillBrush As LongPtr, _
Optional hFrameBrush As LongPtr)
Dim hRgn As LongPtr ' still to be analized...
#Else
Private Sub AddShape(hDc As Long, _
eShape As Shp, _
Left As Long, _
Top As Long, _
Width As Long, _
Height As Long, _
Optional hFillBrush As Long, _
Optional hFrameBrush As Long)
Dim hRgn As Long ' still to be analized...
#End If
Const lFrameWidth As Long = 1
Const lFrameHeight As Long = 1
Select Case eShape
Case Is = triangle
Dim poly() As POINTAPI
ReDim poly(1 To 3)
poly(1).X = Left + Width / 2
poly(1).Y = Top
poly(2).X = Left + Width
poly(2).Y = Top + Height
poly(3).X = Left
poly(3).Y = Top + Height
Polygon hDc, poly(1), 3
hRgn = CreatePolygonRgn(poly(1), 3, 1)
Call FillRgn(hDc, hRgn, hFillBrush)
Call FrameRgn(hDc, hRgn, hFrameBrush, lFrameWidth, lFrameHeight)
Case Is = Ellipse
hRgn = CreateEllipticRgn(Left, Top, Width, Height)
Call FillRgn(hDc, hRgn, hFillBrush)
Call FrameRgn(hDc, hRgn, hFrameBrush, lFrameWidth, lFrameHeight)
Case Is = Rectangle
hRgn = CreateRectRgn(Left, Top, Width, Height)
Call FillRgn(hDc, hRgn, hFillBrush)
Call FrameRgn(hDc, hRgn, hFrameBrush, lFrameWidth, lFrameHeight)
End Select
Call DeleteObject(hRgn)
End Sub