#If VBA7 Then
#If Win64 Then
Private Declare PtrSafe Function SetWindowLong Lib "user32.dll" Alias "SetWindowLongPtrA" (ByVal hWnd As LongPtr, ByVal nIndex As Long, ByVal dwNewLong As LongPtr) As Long
Private Declare PtrSafe Function GetWindowLong Lib "user32.dll" Alias "GetWindowLongPtrA" (ByVal hWnd As LongPtr, ByVal nIndex As Long) As Long
#Else
Private Declare PtrSafe Function SetWindowLong Lib "user32.dll" Alias "SetWindowLongA" (ByVal hWnd As LongPtr, ByVal nIndex As Long, ByVal dwNewLong As Long) As Long
Private Declare PtrSafe Function GetWindowLong Lib "user32.dll" Alias "GetWindowLongA" (ByVal hWnd As LongPtr, ByVal nIndex As Long) As Long
#End If
Private Declare PtrSafe Function ColorAdjustLuma Lib "SHLWAPI.DLL" (ByVal clrRGB As Long, ByVal n As Long, ByVal fScale As Long) As Long
Private Declare PtrSafe Function DrawMenuBar Lib "user32.dll" (ByVal hWnd As LongPtr) As Long
Private Declare PtrSafe Function GetClassLong Lib "user32.dll" Alias "GetClassLongA" (ByVal hWnd As LongPtr, ByVal nIndex As Long) As Long
Private Declare PtrSafe Function IUnknown_GetWindow Lib "shlwapi" Alias "#172" (ByVal pIUnk As IUnknown, ByVal hUf As LongPtr) As Long
Private Declare PtrSafe Function OleTranslateColor Lib "oleAut32.dll" (ByVal clr As OLE_COLOR, ByVal palet As LongPtr, col As Long) As Long
Private Declare PtrSafe Function PostMessage Lib "user32" Alias "PostMessageA" (ByVal hWnd As LongPtr, ByVal wMsg As Long, ByVal wParam As LongPtr, ByVal lParam As LongPtr) As Long
Private Declare PtrSafe Function ReleaseCapture Lib "user32.dll" () As Long
Private Declare PtrSafe Function SendMessage Lib "user32.dll" Alias "SendMessageA" (ByVal hWnd As LongPtr, ByVal wMsg As Long, ByVal wParam As LongPtr, lParam As Any) As Long
Private Declare PtrSafe Function SetClassLong Lib "user32.dll" Alias "SetClassLongA" (ByVal hWnd As LongPtr, ByVal nIndex As Long, ByVal dwNewLong As Long) As Long
Private hWnd As LongPtr
Private WindowStyle As LongPtr
#Else
Private Declare Function SetWindowLong Lib "user32" Alias "SetWindowLongA " (ByVal hwnd As Long , ByVal nIndex As Long, ByVal dwNewLong As Long ) As Long
Private Declare Function GetWindowLong Lib "user32" Alias "GetWindowLongA" (ByVal hwnd As Long, ByVal nIndex As Long) As Long
Private Declare Function ColorAdjustLuma Lib "SHLWAPI.DLL" (ByVal clrRGB As Long, ByVal n As Long, ByVal fScale As Long) As Long
Private Declare Function DrawMenuBar Lib "user32.dll" (ByVal hWnd As Long) As Long
Private Declare Function GetClassLong Lib "user32.dll" Alias "GetClassLongA" (ByVal hWnd As Long, ByVal nIndex As Long) As Long
Private Declare Function IUnknown_GetWindow Lib "shlwapi" Alias "#172" (ByVal pIUnk As IUnknown, ByVal hUf As Long) As Long
Private Declare Function OleTranslateColor Lib "oleAut32.dll" (ByVal clr As OLE_COLOR, ByVal palet As Long, col As Long) As Long
Private Declare Function PostMessage Lib "user32" Alias "PostMessageA" (ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, lParam As Any) As Long
Private Declare Function ReleaseCapture Lib "user32.dll" () As Long
Private Declare Function SendMessage Lib "user32.dll" Alias "SendMessageA" (ByVal hWnd As Long, ByVal wMsg As Long, ByVal wParam As Long, lParam As Any) As Long
Private Declare Function SetClassLong Lib "user32.dll" Alias "SetClassLongA" (ByVal hWnd As Long, ByVal nIndex As Long, ByVal dwNewLong As Long) As Long
Private hWnd As Long
Private WindowStyle As Long
#End If
Private Const CS_DROPSHADOW As Long = &H20000
Private Const GCL_STYLE As Long = (-26)
Private Const GWL_STYLE As Long = (-16)
Private Const GWL_EXSTYLE As Long = (-20)
Private Const HTCAPTION As Long = 2
Private Const WM_NCLBUTTONDOWN As Long = &HA1
Private Const WS_CAPTION As Long = &HC00000
Private Const WS_EX_DLGMODALFRAME As Long = &H1
Private WithEvents CancelBUtton As MSForms.CommandButton
Private WithEvents cForm As MSForms.UserForm
Private WithEvents NewTitleBar As MSForms.Label
Private WithEvents NewTitleBarCaption As MSForms.Label
Private WithEvents NewCloseButton As MSForms.Label
Event CancelBUtton(ByRef Handled As Boolean)
Private cDisplayCloseButton As Boolean
Private cCaption As String
Private cCaptionColor As Long
Private cCaptionHoverColor As Long
Private cDropShadow As Boolean
Private cFocusOnForm As Boolean
Private cFormSet As Boolean
Private cHoverColor As Long
Private cHoverColorSetByUser As Long
Private cTitleBarColor As Long
Private cTitleBarColorSetByUser As Long
' Class Events
Private Sub Class_Initialize()
cTitleBarColorSetByUser = -1
cHoverColorSetByUser = -1
cDisplayCloseButton = True
cCaption = "Default"
End Sub
Private Sub Class_Terminate()
Set cForm = Nothing
End Sub
' Properties
Public Property Get TitleBarColor() As Long
TitleBarColor = cTitleBarColor
End Property
Public Property Let TitleBarColor(uColor As Long)
cTitleBarColorSetByUser = uColor
cCaptionColor = BlackOrWhite(cTitleBarColorSetByUser)
If cFormSet = True Then Apply
End Property
Public Property Get HoverColor() As Long
HoverColor = cHoverColor
End Property
Public Property Let HoverColor(uColor As Long)
cHoverColorSetByUser = uColor
cCaptionHoverColor = BlackOrWhite(cHoverColorSetByUser)
If cFormSet = True Then Apply
End Property
Public Property Get DisplayCloseButton() As Boolean
DisplayCloseButton = cDisplayCloseButton
End Property
Public Property Let DisplayCloseButton(uDisplayCloseButton As Boolean)
cDisplayCloseButton = uDisplayCloseButton
If cFormSet = True Then Apply
End Property
Public Property Set Form(uForm As Object)
Set cForm = uForm
cCaption = IIf(cCaption = "Default", uForm.Caption, cCaption)
Call IUnknown_GetWindow(cForm, VarPtr(hWnd))
Apply
' Applies dropshadow to userform to counter the removal of normal
' shadow resulting from style changes
Call SetClassLong(hWnd, GCL_STYLE, GetClassLong(hWnd, GCL_STYLE) Or CS_DROPSHADOW)
cFormSet = True
End Property
' Prepares userform / applies colors to controls
Public Sub Apply()
HideTitleBorder
Dim cFormBackColor As Long
cFormBackColor = cForm.BackColor
cTitleBarColor = IIf(cTitleBarColorSetByUser >= 0, cTitleBarColorSetByUser, cFormBackColor)
cHoverColor = IIf(cHoverColorSetByUser >= 0, cHoverColorSetByUser, IIf(cTitleBarColorSetByUser >= 0, cTitleBarColorSetByUser, TintAndShade(cFormBackColor, -40)))
cCaptionColor = BlackOrWhite(cTitleBarColor)
cCaptionHoverColor = BlackOrWhite(cHoverColor)
If NewTitleBar Is Nothing Then
CreatePseudoTitleBar
Else
NewTitleBar.BackColor = cTitleBarColor
NewTitleBarCaption.ForeColor = cCaptionColor
NewCloseButton.BackColor = cTitleBarColor
End If
End Sub
' Creates the pseudo titlebar
Private Sub CreatePseudoTitleBar()
Set NewTitleBar = cForm.Controls.Add("Forms.Label.1", "lbTitleBar")
With NewTitleBar
.BackColor = cTitleBarColor
.BackStyle = fmBackStyleOpaque
.Left = 0
.Top = 0
.Height = 20
.Width = cForm.InsideWidth
End With
Set NewTitleBarCaption = cForm.Controls.Add("Forms.Label.1", "lbTitleBarCaption")
With NewTitleBarCaption
.BackStyle = fmBackStyleTransparent
.Caption = cCaption
.Font.Name = "Segoe UI"
.Font.Size = 9
.ForeColor = cCaptionColor
.Left = 6
.Top = 4
.Height = 20
.Width = cForm.InsideWidth
.AutoSize = True
End With
Set NewCloseButton = cForm.Controls.Add("Forms.Label.1", "lbCloseButton")
With NewCloseButton
.BackColor = cTitleBarColor
.BackStyle = fmBackStyleOpaque
.Height = 20
.Width = 24
.Left = cForm.InsideWidth - 24
.Top = 0
.PicturePosition = fmPicturePositionCenter
.Picture = Application.CommandBars.GetImageMso("WindowClose", 16, 16)
End With
Set CancelBUtton = cForm.Controls.Add("Forms.CommandButton.1", "btnDefaultCancel")
With CancelBUtton
.TabStop = False
.Cancel = True
.Top = -40
End With
If cDisplayCloseButton = False Then NewCloseButton.Visible = False
End Sub
' Events for dynamically created controls / pseudo titlebar
Private Sub cForm_MouseMove(ByVal Button As Integer, ByVal Shift As Integer, ByVal X As Single, ByVal Y As Single)
If cFocusOnForm = False Then
NewCloseButton.BackColor = cTitleBarColor
NewTitleBar.BackColor = cTitleBarColor
NewTitleBarCaption.ForeColor = cCaptionColor
cFocusOnForm = True
End If
End Sub
' Close routine for the pseudo closebutton
Private Sub NewCloseButton_Click()
Unload cForm
End Sub
Private Sub NewCloseButton_MouseMove(ByVal Button As Integer, ByVal Shift As Integer, ByVal X As Single, ByVal Y As Single)
NewCloseButton.BackColor = vbRed
cFocusOnCloseButton = True
End Sub
Private Sub NewTitleBarCaption_MouseMove(ByVal Button As Integer, ByVal Shift As Integer, ByVal X As Single, ByVal Y As Single)
Debug.Print "Caption"
If cFocusOnForm = True Then
NewTitleBar.BackColor = cHoverColor
NewCloseButton.BackColor = cHoverColor
NewTitleBarCaption.ForeColor = cCaptionHoverColor
cFocusOnForm = False
cFocusOnCloseButton = False
End If
If Button Then
MoveUserForm
End If
End Sub
Private Sub NewTitleBar_MouseMove(ByVal Button As Integer, ByVal Shift As Integer, ByVal X As Single, ByVal Y As Single)
Debug.Print "Titlebar"
If cFocusOnForm = True Then
NewTitleBar.BackColor = cHoverColor
NewCloseButton.BackColor = cHoverColor
NewTitleBarCaption.ForeColor = cCaptionHoverColor
cFocusOnForm = False
cFocusOnCloseButton = False
End If
If Button Then
MoveUserForm
End If
End Sub
' Click event for the hidden command button that is dynamically-created
' with cancel property set to allow for easy use of escape key.
Private Sub CancelButton_Click()
Dim Handled As Boolean
RaiseEvent CancelBUtton(Handled)
If Handled = False Then
Unload cForm
End If
End Sub
' Misc / Helper routines
Private Sub HideTitleBorder()
WindowStyle = GetWindowLong(hWnd, GWL_STYLE)
WindowStyle = WindowStyle And (Not WS_CAPTION)
SetWindowLong hWnd, GWL_STYLE, WindowStyle
WindowStyle = GetWindowLong(hWnd, GWL_EXSTYLE)
WindowStyle = WindowStyle And Not WS_EX_DLGMODALFRAME
SetWindowLong hWnd, GWL_EXSTYLE, WindowStyle
DrawMenuBar hWnd
End Sub
Private Sub MoveUserForm()
ReleaseCapture
SendMessage hWnd, WM_NCLBUTTONDOWN, HTCAPTION, ByVal 0&
End Sub
Private Function TintAndShade(ByVal ColRef As Long, Optional ByVal Luminance As Long = 0) As Long
' Orignally sourced code written by Jaafar Tribak from https://www.mrexcel.com/board/threads/applying-tintandshade-to-a-userform-label.1189219/
'(Luminance must be between -100 and +100)
OleTranslateColor ColRef, 0, ColRef
TintAndShade = ColorAdjustLuma(ColRef, Luminance * 10, True)
End Function
Private Function BlackOrWhite(Color As Long) As Long
Dim cRed As Long, cGreen As Long, cBlue As Long
cRed = Color And 255
cGreen = (Color \ 256) And 255
cBlue = (Color \ 65536) And 255
If cRed * 0.3 + cGreen * 0.59 + cBlue * 0.11 < 128 Then BlackOrWhite = vbWhite
End Function