Jaafar Tribak

Well-known Member
Joined
Dec 5, 2002
Messages
9,806
Office Version
  1. 2016
Platform
  1. Windows
Hi all,

I already wrote some code before for customizing the titlebar of userforms HERE and HERE.

Unfortunately, both codes relied on subclassing the userform which poses problems of its own. Problems such as risks of crashing excel during IDE testings or during unhandled errors... Also, subclassing works only with vbModal forms. Attempting to subclass a Modeless userform is a recipe for disaster.

Here, I have taken a different approach which doesn't use subclassing\hooking at all. The code doesn't override or interfere with the current Windows theme either and works with Modal as well as with Modeless userforms.

The code allows for the following:
A: Change the caption color (Gradient Fill Optional).
B: Change the Font and its attributes.
C; Adds an X Button and a context menu for closing the userform + (Alt+F4).
D: Adds a shadow to the userform.
E: Adds an Optional Icon.
F: Allows for disabling the caption when the userform is Deactivated (vbModeless only).
G: Choice between left aligned caption text or Centered text.
H: Optional fine Frame drawn around the userform.

Workbook Example








1- CTitleBar (Class Code)
VBA Code:
Option Explicit

Private WithEvents oFrame As MSForms.Frame
Private WithEvents objForm As MSForms.UserForm

Private Type CaptionData
    tSize As Long
    CaptionColor As Variant
    FontName As String * 256
    FontSize As Long
    FontColor As Long
    FontBold As Boolean
    FontItalic As Boolean
    DrawFrame As Boolean
    CenterText As Boolean
    GradientColor As Boolean
'//Applies to vbModeless UserForms only. //
    DisableWhenInActive As Boolean         '//
'//                            '//                                  //
    IconFile As String * 256
End Type

Private Type POINTAPI
    X As Long
    Y As Long
End Type

Private Type RECT
    Left As Long
    Top As Long
    Right As Long
    Bottom As Long
End Type

Private Type NCL_METRICS
    CaptionHeight As Single
    FrameWidth As Single
    FrameHeight As Single
End Type

Private Type uPicDesc
    Size As Long
    Type As Long
    #If Win64 Then
        hPic As LongLong
        hPal As LongLong
    #Else
        hPic As Long
        hPal As Long
    #End If
End Type

Private Type GUID
    Data1 As Long
    Data2 As Integer
    Data3 As Integer
    Data4(0 To 7) As Byte
End Type

Private Type TRIVERTEX
    X As Long
    Y As Long
    Red As Integer
    Green As Integer
    Blue As Integer
    alpha As Integer
End Type

Private Type GRADIENT_RECT
    UpperLeft As Long
    LowerRight As Long
End Type

Private Type MYFONT
    FontName As String
    FontSize As Long
    FontBold As Boolean
    FontItalic As Boolean
End Type

'// GDIPlus TYPES
    Private Type COLORMATRIX
        M(0 To 4, 0 To 4)   As Single
    End Type
  
    Private Type GDIPlusStartupInput
        GdiPlusVersion   As Long
        DebugEventCallback   As Long
        SuppressBackgroundThread   As Long
        SuppressExternalCodecs  As Long
    End Type
 '//

#If VBA7 Then
    #If Win64 Then
        Private Declare PtrSafe Function SetWindowLong Lib "user32" Alias "SetWindowLongPtrA" (ByVal hwnd As LongPtr, ByVal nIndex As Long, ByVal dwNewLong As LongPtr) As LongPtr
        Private Declare PtrSafe Function GetWindowLong Lib "user32" Alias "GetWindowLongPtrA" (ByVal hwnd As LongPtr, ByVal nIndex As Long) As LongPtr
        Private Declare PtrSafe Function GetClassLong Lib "user32" Alias "GetClassLongPtrA" (ByVal hwnd As LongPtr, ByVal nIndex As Long) As LongPtr
        Private Declare PtrSafe Function SetClassLong Lib "user32" Alias "SetClassLongPtrA" (ByVal hwnd As LongPtr, ByVal nIndex As Long, ByVal dwNewLong As LongPtr) As LongPtr
        Private Declare PtrSafe Function PtInRect Lib "user32" (lpRect As RECT, ByVal arg2 As LongPtr) As Long
        Private Declare PtrSafe Function WindowFromPoint Lib "user32" (ByVal Point As LongPtr) As LongPtr
    #Else
        Private Declare PtrSafe Function SetWindowLong Lib "user32" Alias "SetWindowLongA" (ByVal hwnd As Long, ByVal nIndex As Long, ByVal dwNewLong As Long) As Long
        Private Declare PtrSafe Function GetWindowLong Lib "user32" Alias "GetWindowLongA" (ByVal hwnd As Long, ByVal nIndex As Long) As Long
        Private Declare PtrSafe Function GetClassLong Lib "user32" Alias "GetClassLongA" (ByVal hwnd As Long, ByVal nIndex As Long) As Long
        Private Declare PtrSafe Function SetClassLong Lib "user32" Alias "SetClassLongA" (ByVal hwnd As Long, ByVal nIndex As Long, ByVal dwNewLong As Long) As Long
        Private Declare PtrSafe Function PtInRect Lib "user32" (lpRect As RECT, ByVal arg1 As Long, ByVal arg2 As Long) As Long
        Private Declare PtrSafe Function WindowFromPoint Lib "user32" (ByVal xPoint As Long, ByVal yPoint As Long) As Long
    #End If
        Private Declare PtrSafe Function IUnknown_GetWindow Lib "shlwapi" Alias "#172" (ByVal pIUnk As IUnknown, ByVal hUf As LongPtr) As Long
        Private Declare PtrSafe Function SetWindowPos Lib "user32" (ByVal hwnd As LongPtr, ByVal hWndInsertAfter As LongPtr, ByVal X As Long, ByVal Y As Long, ByVal cx As Long, ByVal cy As Long, ByVal wFlags As Long) As Long
        Private Declare PtrSafe Function DrawMenuBar Lib "user32" (ByVal hwnd As LongPtr) As Long
        Private Declare PtrSafe Function GetClientRect Lib "user32" (ByVal hwnd As LongPtr, lpRect As RECT) As Long
        Private Declare PtrSafe Function GetWindowRect Lib "user32" (ByVal hwnd As LongPtr, lpRect As RECT) As Long
        Private Declare PtrSafe Function ReleaseCapture Lib "user32" () 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 GetSystemMetrics Lib "user32" (ByVal nIndex As Long) As Long
        Private Declare PtrSafe Function DrawFrameControl Lib "user32" (ByVal hDC As LongPtr, lpRect As RECT, ByVal un1 As Long, ByVal un2 As Long) As Long
        Private Declare PtrSafe Function GetDC Lib "user32" (ByVal hwnd As LongPtr) As LongPtr
        Private Declare PtrSafe Function ReleaseDC Lib "user32" (ByVal hwnd As LongPtr, ByVal hDC As LongPtr) As Long
        Private Declare PtrSafe Function CreateCompatibleDC Lib "gdi32" (ByVal hDC As LongPtr) As LongPtr
        Private Declare PtrSafe Function CreateCompatibleBitmap Lib "gdi32" (ByVal hDC As LongPtr, ByVal nWidth As Long, ByVal nHeight As Long) As LongPtr
        Private Declare PtrSafe Function SelectObject Lib "gdi32" (ByVal hDC As LongPtr, ByVal hObject As LongPtr) As LongPtr
        Private Declare PtrSafe Function SetBkMode Lib "gdi32" (ByVal hDC As LongPtr, ByVal nBkMode As Long) As Long
        Private Declare PtrSafe Function OleCreatePictureIndirect Lib "oleAut32.dll" (PicDesc As uPicDesc, RefIID As Any, ByVal fPictureOwnsHandle As Long, IPic As IPicture) As Long
        Private Declare PtrSafe Function DeleteDC Lib "gdi32" (ByVal hDC As LongPtr) As Long
        Private Declare PtrSafe Function DeleteObject Lib "gdi32" (ByVal hObject As LongPtr) As Long
        Private Declare PtrSafe Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal Length As LongPtr)
        Private Declare PtrSafe Function DrawText Lib "user32" Alias "DrawTextA" (ByVal hDC As LongPtr, ByVal lpStr As String, ByVal nCount As Long, lpRect As RECT, ByVal wFormat As Long) As Long
        Private Declare PtrSafe Function GradientFillRect Lib "msimg32" Alias "GradientFill" (ByVal hDC As LongPtr, pVertex As TRIVERTEX, ByVal dwNumVertex As Long, pMesh As GRADIENT_RECT, ByVal dwNumMesh As Long, ByVal dwMode As Long) As Long
        Private Declare PtrSafe Function CreateSolidBrush Lib "gdi32" (ByVal crColor As Long) As LongPtr
        Private Declare PtrSafe Function FillRect Lib "user32" (ByVal hDC As LongPtr, lpRect As RECT, ByVal hBrush As LongPtr) As Long
        Private Declare PtrSafe Function SetTextColor Lib "gdi32" (ByVal hDC As LongPtr, ByVal crColor As Long) As Long
        Private Declare PtrSafe Function GetCursorPos Lib "user32" (lpPoint As POINTAPI) As Long
        Private Declare PtrSafe Function ClientToScreen Lib "user32" (ByVal hwnd As LongPtr, lpPoint As POINTAPI) As Long
        Private Declare PtrSafe Function LoadImage Lib "user32" Alias "LoadImageA" (ByVal hInst As LongPtr, ByVal lpsz As String, ByVal un1 As Long, ByVal n1 As Long, ByVal n2 As Long, ByVal un2 As Long) As LongPtr
        Private Declare PtrSafe Function DestroyIcon Lib "user32" (ByVal hIcon As LongPtr) As Long
        Private Declare PtrSafe Function DrawIcon Lib "user32" (ByVal hDC As LongPtr, ByVal X As Long, ByVal Y As Long, ByVal hIcon As LongPtr) As Long
        Private Declare PtrSafe Function TranslateColor Lib "oleAut32.dll" Alias "OleTranslateColor" (ByVal clr As OLE_COLOR, ByVal palet As LongPtr, Col As Long) As Long
        Private Declare PtrSafe Function CreatePen Lib "gdi32" (ByVal nPenStyle As Long, ByVal nWidth As Long, ByVal crColor As Long) As LongPtr
        Private Declare PtrSafe Function CreatePopupMenu Lib "user32" () As LongPtr
        Private Declare PtrSafe Function DestroyMenu Lib "user32" (ByVal hMenu As LongPtr) As Long
        Private Declare PtrSafe Function SetMenuItemBitmaps Lib "user32" (ByVal hMenu As LongPtr, ByVal nPosition As Long, ByVal wFlags As Long, ByVal hBitmapUnchecked As LongPtr, ByVal hBitmapChecked As LongPtr) As Long
        Private Declare PtrSafe Function AppendMenu Lib "user32" Alias "AppendMenuA" (ByVal hMenu As LongPtr, ByVal wFlags As Long, ByVal wIDNewItem As LongPtr, ByVal lpNewItem As Any) As Long
        Private Declare PtrSafe Function TrackPopupMenuEx Lib "user32" (ByVal hMenu As LongPtr, ByVal un As Long, ByVal n1 As Long, ByVal n2 As Long, ByVal hwnd As LongPtr, ByVal lpTPMParams As Long) As Long
        Private Declare PtrSafe Function CopyImage Lib "user32" (ByVal handle As LongPtr, ByVal un1 As Long, ByVal n1 As Long, ByVal n2 As Long, ByVal un2 As Long) As LongPtr
        Private Declare PtrSafe Function OpenClipboard Lib "user32" (ByVal hwnd As LongPtr) As Long
        Private Declare PtrSafe Function CloseClipboard Lib "user32" () As Long
        Private Declare PtrSafe Function EmptyClipboard Lib "user32" () As Long
        Private Declare PtrSafe Function GetClipboardData Lib "user32" (ByVal wFormat As Long) As LongPtr
        Private Declare PtrSafe Function CreateWindowEx Lib "user32" Alias "CreateWindowExA" (ByVal dwExStyle As Long, ByVal lpClassName As String, ByVal lpWindowName As String, ByVal dwStyle As Long, ByVal X As Long, ByVal Y As Long, ByVal nWidth As Long, ByVal nHeight As Long, ByVal hWndParent As LongPtr, ByVal hMenu As LongPtr, ByVal hInstance As LongPtr, lpParam As Any) As LongPtr
        Private Declare PtrSafe Function DestroyWindow Lib "user32" (ByVal hwnd As LongPtr) As Long
        Private Declare PtrSafe Function IsWindow Lib "user32" (ByVal hwnd As LongPtr) As Long
        Private Declare PtrSafe Function GetModuleHandle Lib "kernel32" Alias "GetModuleHandleA" (ByVal lpModuleName As String) As LongPtr
        Private Declare PtrSafe Function GetSysColorBrush Lib "user32" (ByVal nIndex As Long) As LongPtr
        Private Declare PtrSafe Function GetSysColor Lib "user32" (ByVal nIndex As Long) As Long
        Private Declare PtrSafe Function BitBlt Lib "gdi32" (ByVal hDestDC As LongPtr, ByVal X As Long, ByVal Y As Long, ByVal nWidth As Long, ByVal nHeight As Long, ByVal hSrcDC As LongPtr, ByVal xSrc As Long, ByVal ySrc As Long, ByVal dwRop As Long) As Long
        Private Declare PtrSafe Function GetAsyncKeyState Lib "user32" (ByVal vKey As Long) As Integer
        Private Declare PtrSafe Function SelectClipRgn Lib "gdi32" (ByVal hDC As LongPtr, ByVal hRgn As LongPtr) 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 CombineRgn Lib "gdi32" (ByVal hDestRgn As LongPtr, ByVal hSrcRgn1 As LongPtr, ByVal hSrcRgn2 As LongPtr, ByVal nCombineMode As Long) As Long
        Private Declare PtrSafe Function SetWindowRgn Lib "user32" (ByVal hwnd As LongPtr, ByVal hRgn As LongPtr, ByVal bRedraw As Long) As Long
        Private Declare PtrSafe Function SetRect Lib "user32" (lpRect As RECT, ByVal X1 As Long, ByVal Y1 As Long, ByVal X2 As Long, ByVal Y2 As Long) As Long
        Private Declare PtrSafe Function GetDeviceCaps Lib "gdi32" (ByVal hDC As LongPtr, ByVal nIndex As Long) As Long
        Private Declare PtrSafe Function MoveToEx Lib "gdi32" (ByVal hDC As LongPtr, ByVal X As Long, ByVal Y As Long, ByVal lpPoint As Long) As Long
        Private Declare PtrSafe Function LineTo Lib "gdi32" (ByVal hDC As LongPtr, ByVal X As Long, ByVal Y As Long) As Long
        Private Declare PtrSafe Function GetActiveWindow Lib "user32" () As LongPtr
        Private Declare PtrSafe Function IsWindowEnabled Lib "user32" (ByVal hwnd As LongPtr) As Long
        Private Declare PtrSafe Function ShowWindow Lib "user32.dll" (ByVal hwnd As LongPtr, ByVal nCmdShow As Long) As Long
        Private Declare PtrSafe Function IsWindowVisible Lib "user32" (ByVal hwnd As LongPtr) As Long
        Private Declare PtrSafe Function SetActiveWindow Lib "user32" (ByVal hwnd As LongPtr) As LongPtr

        'GDIPlus declares
        Private Declare PtrSafe Function GdiplusStartup Lib "gdiplus" (token As Long, inputbuf As GDIPlusStartupInput, Optional ByVal outputbuf As Long = 0) As Long
        Private Declare PtrSafe Function GdiplusShutdown Lib "gdiplus" (ByVal token As Long) As Long
        Private Declare PtrSafe Function GdipCreateBitmapFromHBITMAP Lib "gdiplus" (ByVal hbm As LongPtr, ByVal hPal As LongPtr, BITMAP As LongPtr) As Long
        Private Declare PtrSafe Function GdipGetImageThumbnail Lib "gdiplus" (ByVal Image As LongPtr, ByVal thumbWidth As Long, ByVal thumbHeight As Long, thumbImage As LongPtr, ByVal Callback As LongPtr, ByVal callbackData As LongPtr) As Long
        Private Declare PtrSafe Function GdipCreateFromHDC Lib "gdiplus" (ByVal hDC As LongPtr, hGraphics As LongPtr) As Long
        Private Declare PtrSafe Function GdipSetImageAttributesColorMatrix Lib "gdiplus" (ByVal imageattr As LongPtr, ByVal ColorAdjust As Long, ByVal EnableFlag As Boolean, ByRef MatrixColor As COLORMATRIX, ByRef MatrixGray As COLORMATRIX, ByVal flags As Long) As Long
        Private Declare PtrSafe Function GdipCreateImageAttributes Lib "gdiplus" (ByRef imageattr As LongPtr) As Long
        Private Declare PtrSafe Function GdipSetSmoothingMode Lib "gdiplus" (ByVal graphics As LongPtr, ByVal SmoothingMd As Long) As Long
        Private Declare PtrSafe Function GdipGetImageHeight Lib "GdiPlus.dll" (ByVal mImage As LongPtr, ByRef mHeight As Long) As Long
        Private Declare PtrSafe Function GdipGetImageWidth Lib "GdiPlus.dll" (ByVal mImage As LongPtr, ByRef mWidth As Long) As Long
        Private Declare PtrSafe Function GdipDisposeImage Lib "gdiplus" (ByVal Image As LongPtr) As LongPtr
        Private Declare PtrSafe Function GdipDrawImageRectRectI Lib "gdiplus" (ByVal hGraphics As LongPtr, ByVal hImage As LongPtr, ByVal DstX As Long, ByVal DstY As Long, ByVal DstWidth As Long, ByVal DstHeight As Long, ByVal SrcX As Long, ByVal SrcY As Long, ByVal SrcWidth As Long, ByVal SrcHeight As Long, ByVal srcUnit As Long, Optional ByVal imageAttributes As LongPtr = 0, Optional ByVal Callback As Long = 0, Optional ByVal callbackData As Long = 0) As Long
        Private Declare PtrSafe Function GdipDeleteGraphics Lib "GdiPlus.dll" (ByVal mGraphics As LongPtr) As Long
        Private Declare PtrSafe Function GdipDisposeImageAttributes Lib "gdiplus" (ByVal imageattr As LongPtr) As Long
  
        Private hwnd As LongPtr, hIcon As LongPtr, hShadow 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 GetClassLong Lib "user32" Alias "GetClassLongA" (ByVal hwnd As Long, ByVal nIndex As Long) As Long
    Private Declare Function SetClassLong Lib "user32" Alias "SetClassLongA" (ByVal hwnd As Long, ByVal nIndex As Long, ByVal dwNewLong As Long) As Long
    Private Declare Function PtInRect Lib "user32" (lpRect As RECT, ByVal arg1 As Long, ByVal arg2 As Long) As Long
    Private Declare Function WindowFromPoint Lib "user32" (ByVal xPoint As Long, ByVal yPoint 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 SetWindowPos Lib "user32" (ByVal hwnd As Long, ByVal hWndInsertAfter As Long, ByVal X As Long, ByVal Y As Long, ByVal cx As Long, ByVal cy As Long, ByVal wFlags As Long) As Long
    Private Declare Function DrawMenuBar Lib "user32" (ByVal hwnd As Long) As Long
    Private Declare Function GetClientRect Lib "user32" (ByVal hwnd As Long, lpRect As RECT) As Long
    Private Declare Function GetWindowRect Lib "user32" (ByVal hwnd As Long, lpRect As RECT) As Long
    Private Declare Function ReleaseCapture Lib "user32" () As Long
    Private Declare Function PostMessage Lib "user32" Alias "PostMessageA" (ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
    Private Declare Function GetSystemMetrics Lib "user32" (ByVal nIndex As Long) As Long
    Private Declare Function DrawFrameControl Lib "user32" (ByVal hDC As Long, lpRect As RECT, ByVal un1 As Long, ByVal un2 As Long) As Long
    Private Declare Function GetDC Lib "user32" (ByVal hwnd As Long) As Long
    Private Declare Function ReleaseDC Lib "user32" (ByVal hwnd As Long, ByVal hDC As Long) As Long
    Private Declare Function CreateCompatibleDC Lib "gdi32" (ByVal hDC As Long) As Long
    Private Declare Function CreateCompatibleBitmap Lib "gdi32" (ByVal hDC As Long, ByVal nWidth As Long, ByVal nHeight As Long) As Long
    Private Declare Function SelectObject Lib "gdi32" (ByVal hDC As Long, ByVal hObject As Long) As Long
    Private Declare Function SetBkMode Lib "gdi32" (ByVal hDC As Long, ByVal nBkMode As Long) As Long
    Private Declare Function OleCreatePictureIndirect Lib "oleAut32.dll" (PicDesc As uPicDesc, RefIID As Any, ByVal fPictureOwnsHandle As Long, IPic As IPicture) As Long
    Private Declare Function DeleteDC Lib "gdi32" (ByVal hDC As Long) As Long
    Private Declare Function DeleteObject Lib "gdi32" (ByVal hObject As Long) As Long
    Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal Length As Long)
    Private Declare Function DrawText Lib "user32" Alias "DrawTextA" (ByVal hDC As Long, ByVal lpStr As String, ByVal nCount As Long, lpRect As RECT, ByVal wFormat As Long) As Long
    Private Declare Function GradientFillRect Lib "msimg32" Alias "GradientFill" (ByVal hDC As Long, pVertex As TRIVERTEX, ByVal dwNumVertex As Long, pMesh As GRADIENT_RECT, ByVal dwNumMesh As Long, ByVal dwMode As Long) As Long
    Private Declare Function CreateSolidBrush Lib "gdi32" (ByVal crColor As Long) As Long
    Private Declare Function FillRect Lib "user32" (ByVal hDC As Long, lpRect As RECT, ByVal hBrush As Long) As Long
    Private Declare Function SetTextColor Lib "gdi32" (ByVal hDC As Long, ByVal crColor As Long) As Long
    Private Declare Function GetCursorPos Lib "user32" (lpPoint As POINTAPI) As Long
    Private Declare Function ClientToScreen Lib "user32" (ByVal hwnd As Long, lpPoint As POINTAPI) As Long
    Private Declare Function LoadImage Lib "user32" Alias "LoadImageA" (ByVal hInst As Long, ByVal lpsz As String, ByVal un1 As Long, ByVal n1 As Long, ByVal n2 As Long, ByVal un2 As Long) As Long
    Private Declare Function DestroyIcon Lib "user32" (ByVal hIcon As Long) As Long
    Private Declare Function DrawIcon Lib "user32" (ByVal hDC As Long, ByVal X As Long, ByVal Y As Long, ByVal hIcon As Long) As Long
    Private Declare Function TranslateColor Lib "oleAut32.dll" Alias "OleTranslateColor" (ByVal clr As OLE_COLOR, ByVal palet As Long, Col As Long) As Long
    Private Declare Function CreatePen Lib "gdi32" (ByVal nPenStyle As Long, ByVal nWidth As Long, ByVal crColor As Long) As Long
    Private Declare Function CreatePopupMenu Lib "user32" () As Long
    Private Declare Function DestroyMenu Lib "user32" (ByVal hMenu As Long) As Long
    Private Declare Function SetMenuItemBitmaps Lib "user32" (ByVal hMenu As Long, ByVal nPosition As Long, ByVal wFlags As Long, ByVal hBitmapUnchecked As Long, ByVal hBitmapChecked As Long) As Long
    Private Declare Function AppendMenu Lib "user32" Alias "AppendMenuA" (ByVal hMenu As Long, ByVal wFlags As Long, ByVal wIDNewItem As Long, ByVal lpNewItem As Any) As Long
    Private Declare Function TrackPopupMenuEx Lib "user32" (ByVal hMenu As Long, ByVal un As Long, ByVal n1 As Long, ByVal n2 As Long, ByVal hwnd As Long, ByVal lpTPMParams As Long) As Long
    Private Declare Function CopyImage Lib "user32" (ByVal handle As Long, ByVal un1 As Long, ByVal n1 As Long, ByVal n2 As Long, ByVal un2 As Long) As Long
    Private Declare Function OpenClipboard Lib "user32" (ByVal hwnd As Long) As Long
    Private Declare Function CloseClipboard Lib "user32" () As Long
    Private Declare Function EmptyClipboard Lib "user32" () As Long
    Private Declare Function GetClipboardData Lib "user32" (ByVal wFormat As Long) As Long
    Private Declare Function CreateWindowEx Lib "user32" Alias "CreateWindowExA" (ByVal dwExStyle As Long, ByVal lpClassName As String, ByVal lpWindowName As String, ByVal dwStyle As Long, ByVal X As Long, ByVal Y As Long, ByVal nWidth As Long, ByVal nHeight As Long, ByVal hWndParent As Long, ByVal hMenu As Long, ByVal hInstance As Long, lpParam As Any) As Long
    Private Declare Function DestroyWindow Lib "user32" (ByVal hwnd As Long) As Long
    Private Declare Function IsWindow Lib "user32" (ByVal hwnd As Long) As Long
    Private Declare Function GetModuleHandle Lib "kernel32" Alias "GetModuleHandleA" (ByVal lpModuleName As String) As Long
    Private Declare Function GetSysColorBrush Lib "user32" (ByVal nIndex As Long) As Long
    Private Declare Function GetSysColor Lib "user32" (ByVal nIndex As Long) As Long
    Private Declare Function BitBlt Lib "gdi32" (ByVal hDestDC As Long, ByVal X As Long, ByVal Y As Long, ByVal nWidth As Long, ByVal nHeight As Long, ByVal hSrcDC As Long, ByVal xSrc As Long, ByVal ySrc As Long, ByVal dwRop As Long) As Long
    Private Declare Function GetAsyncKeyState Lib "user32" (ByVal vKey As Long) As Integer
    Private Declare Function SelectClipRgn Lib "gdi32" (ByVal hDC As Long, ByVal hRgn 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 CombineRgn Lib "gdi32" (ByVal hDestRgn As Long, ByVal hSrcRgn1 As Long, ByVal hSrcRgn2 As Long, ByVal nCombineMode As Long) As Long
    Private Declare Function SetWindowRgn Lib "user32" (ByVal hwnd As Long, ByVal hRgn As Long, ByVal bRedraw As Long) As Long
    Private Declare Function SetRect Lib "user32" (lpRect As RECT, ByVal X1 As Long, ByVal Y1 As Long, ByVal X2 As Long, ByVal Y2 As Long) As Long
    Private Declare Function GetDeviceCaps Lib "gdi32" (ByVal hDC As Long, ByVal nIndex As Long) As Long
    Private Declare Function MoveToEx Lib "gdi32" (ByVal hDC As Long, ByVal X As Long, ByVal Y As Long, ByVal lpPoint As Long) As Long
    Private Declare Function LineTo Lib "gdi32" (ByVal hDC As Long, ByVal X As Long, ByVal Y As Long) As Long
    Private Declare Function GetActiveWindow Lib "user32" () As Long
    Private Declare Function IsWindowEnabled Lib "user32" (ByVal hwnd As Long) As Long
    Private Declare Function ShowWindow Lib "user32.dll" (ByVal hwnd As Long, ByVal nCmdShow As Long) As Long
    Private Declare Function IsWindowVisible Lib "user32" (ByVal hwnd As Long) As Long
    Private Declare Function SetActiveWindow Lib "user32" (ByVal hwnd As Long) As Long
  
    'GDIPlus declares
    Private Declare Function GdiplusStartup Lib "gdiplus" (token As Long, inputbuf As GDIPlusStartupInput, Optional ByVal outputbuf As Long = 0) As Long
    Private Declare Function GdiplusShutdown Lib "gdiplus" (ByVal token As Long) As Long
    Private Declare Function GdipCreateBitmapFromHBITMAP Lib "gdiplus" (ByVal hbm As Long, ByVal hPal As Long, BITMAP As Long) As Long
    Private Declare Function GdipGetImageThumbnail Lib "gdiplus" (ByVal Image As Long, ByVal thumbWidth As Long, ByVal thumbHeight As Long, thumbImage As Long, ByVal Callback As Long, ByVal callbackData As Long) As Long
    Private Declare Function GdipCreateFromHDC Lib "gdiplus" (ByVal hDC As Long, hGraphics As Long) As Long
    Private Declare Function GdipSetImageAttributesColorMatrix Lib "gdiplus" (ByVal imageattr As Long, ByVal ColorAdjust As Long, ByVal EnableFlag As Boolean, ByRef MatrixColor As COLORMATRIX, ByRef MatrixGray As COLORMATRIX, ByVal flags As Long) As Long
    Private Declare Function GdipCreateImageAttributes Lib "gdiplus" (ByRef imageattr As Long) As Long
    Private Declare Function GdipSetSmoothingMode Lib "gdiplus" (ByVal graphics As Long, ByVal SmoothingMd As Long) As Long
    Private Declare Function GdipGetImageHeight Lib "GdiPlus.dll" (ByVal mImage As Long, ByRef mHeight As Long) As Long
    Private Declare Function GdipGetImageWidth Lib "GdiPlus.dll" (ByVal mImage As Long, ByRef mWidth As Long) As Long
    Private Declare Function GdipDisposeImage Lib "gdiplus" (ByVal Image As Long) As Long
    Private Declare Function GdipDrawImageRectRectI Lib "gdiplus" (ByVal hGraphics As Long, ByVal hImage As Long, ByVal DstX As Long, ByVal DstY As Long, ByVal DstWidth As Long, ByVal DstHeight As Long, ByVal SrcX As Long, ByVal SrcY As Long, ByVal SrcWidth As Long, ByVal SrcHeight As Long, ByVal srcUnit As Long, Optional ByVal imageAttributes As Long = 0, Optional ByVal Callback As Long = 0, Optional ByVal callbackData As Long = 0) As Long
    Private Declare Function GdipDeleteGraphics Lib "GdiPlus.dll" (ByVal mGraphics As Long) As Long
    Private Declare Function GdipDisposeImageAttributes Lib "gdiplus" (ByVal imageattr As Long) As Long

    Private hwnd As Long, hIcon As Long, hShadow As Long

#End If

Private BMPsCol As Collection
Private FramePicsCollection As Collection
Private CaptionPicsCollection As Collection
Private tMt As NCL_METRICS
Private tFont As MYFONT

Private lBackColor As Long
Private sFontName As String
Private sIconFile As String
Private sFormCaption As String
Private lFontColor As Long
Private bGradientColor As Boolean
Private bCenterText As Boolean
Private bDisableWhenInActive As Boolean
Private bDrawFrame As Boolean


  
#If Win64 Then
    Public Sub Attach(ByVal oForm As Object, ByVal pCD As LongLong)
#Else
    Public Sub Attach(ByVal oForm As Object, ByVal pCD As Long)
#End If

    Const LR_LOADFROMFILE = &H10
    Const IMAGE_ICON = 1
    Const DFCS_HOT = &H1000
    Const DFCS_PUSHED = &H200
    Const DFCS_INACTIVE = 256
    Const COLOR_BTNHIGHLIGHT = 20
  
    Dim tCD As CaptionData

    Set objForm = oForm
    Call IUnknown_GetWindow(oForm, VarPtr(hwnd))
  
    Call CopyMemory(ByVal tCD, ByVal pCD, LenB(tCD))
    With tCD
        sFontName = Left(.FontName, InStr(1, .FontName, vbNullChar) - 1)
        tFont.FontName = IIf(Len(sFontName), sFontName, oForm.Font.Name)
        tFont.FontItalic = .FontItalic
        tFont.FontSize = IIf(.FontSize, .FontSize, oForm.Font.Size)
        lFontColor = .FontColor
        lBackColor = IIf(TypeName(.CaptionColor) = "Empty", GetSysColor(COLOR_BTNHIGHLIGHT), .CaptionColor)
        bDrawFrame = .DrawFrame
        bCenterText = .CenterText
        bGradientColor = .GradientColor
        bDisableWhenInActive = .DisableWhenInActive
        sIconFile = Left(.IconFile, InStr(1, .IconFile, vbNullChar) - 1)
    End With

   sFormCaption = oForm.Caption
  
    If Len(Dir(sIconFile)) Then
        hIcon = LoadImage(0, sIconFile, IMAGE_ICON, 0, 0, LR_LOADFROMFILE)
    End If
  
    tMt = GetWinMetrics()
    Call ChangeFormWinStyles(oForm)
    Call ShiftFormControls(ByVal oForm)
    Call AddCloseFrame(oForm)
    Call DrawActiveCaption(oForm)
    If bDisableWhenInActive Then
        Call DrawInActiveCaption(oForm)
    End If
    Call DrawCloseBtn(oFrame, 0)
    Call DrawCloseBtn(oFrame, DFCS_HOT)
    Call DrawCloseBtn(oFrame, DFCS_PUSHED)
    Call DrawCloseBtn(oFrame, DFCS_INACTIVE)

End Sub

Public Sub Enable(ByVal bEnable As Boolean)
  
    If bEnable Then
        If CaptionPicsCollection.Count Then
            Set objForm.Picture = CaptionPicsCollection("ActiveCaptionPic")
        End If
        If FramePicsCollection.Count Then
            Set oFrame.Picture = FramePicsCollection(1)
        End If
        Call CreateShadow
    Else
        If bDisableWhenInActive Then
            If CaptionPicsCollection.Count > 1 Then
                If IsWindowEnabled(Application.hwnd) Then
                    Set objForm.Picture = CaptionPicsCollection("InActiveCaptionPic")
                End If
            End If
        End If
        If FramePicsCollection.Count Then
            Set oFrame.Picture = FramePicsCollection(4)
        End If
        Call DestroyWindow(hShadow)
    End If

End Sub

Private Sub Class_Terminate()
    Call CleanUp
End Sub


Private Sub CleanUp()

    Dim i As Long
  
    Call DestroyWindow(hShadow)
    Call DestroyIcon(hIcon)

    If Not BMPsCol Is Nothing Then
        With BMPsCol
            For i = .Count To 1 Step -1
                Call DeleteObject(.Item(i))
                .Remove i
            Next i
        End With
    End If
  
    Set BMPsCol = Nothing
    Set FramePicsCollection = Nothing
    Set CaptionPicsCollection = Nothing
 
End Sub

Private Sub DrawActiveCaption(ByVal oForm As Object)

    Const SM_CXICON = 11
    Const SM_CXBORDER = 5
    Const SM_CXFRAME = 32
    Const DT_SINGLELINE = &H20
    Const DT_CALCRECT = &H400
    Const PS_SOLID = 1
    Const TRANSPARENT = 1
    Const GRADIENT_FILL_RECT_H = &H0
  
    #If Win64 Then
        Dim hDC As LongLong, hBrush As LongLong, hPrevFont As LongLong, hOldBrush As LongLong
        Dim hMemDC As LongLong, hMemBmp As LongLong, hOldBmp As LongLong, hPen As LongLong, hOldPen As LongLong
    #Else
         Dim hDC As Long, hBrush As Long, hPrevFont As Long, hOldBrush As Long
        Dim hMemDC As Long, hMemBmp As Long, hOldBmp As Long, hPen As Long, hOldPen As Long
    #End If
  
    Dim tTitleBarRect As RECT, tClientRect As RECT, tTextRect As RECT, tTextPosRect As RECT
    Dim vert(2) As TRIVERTEX, tPt As GRADIENT_RECT
    Dim IFont As stdole.IFont
    Dim lTextHeight As Long, lFrmColor As Long, lPenColor As Long
    Dim R As Byte, G As Byte, B As Byte
  
    On Error GoTo Xit
  
    hDC = GetDC(hwnd)
    Call GetClientRect(hwnd, tClientRect)
  
    hMemDC = CreateCompatibleDC(0)
    hMemBmp = CreateCompatibleBitmap(hDC, tClientRect.Right, tClientRect.Bottom)
    hOldBmp = SelectObject(hMemDC, hMemBmp)
  
    lFrmColor = oForm.BackColor
    Call TranslateColor(oForm.BackColor, 0, lFrmColor)
    hBrush = CreateSolidBrush(lFrmColor)
    hOldBrush = SelectObject(hMemDC, hBrush)
    Call FillRect(hMemDC, tClientRect, hBrush)
    Call SelectObject(hMemDC, hOldBrush)
    Call DeleteObject(hBrush)

    If bDrawFrame Then
        lPenColor = lBackColor
        If lBackColor = vbWhite Then lPenColor = 0
        hPen = CreatePen(PS_SOLID, 2, lPenColor)
        hOldPen = SelectObject(hMemDC, hPen)
        With tClientRect
            Call MoveToEx(hMemDC, .Left, .Top, ByVal 0)
            Call LineTo(hMemDC, .Right, .Top)
            Call LineTo(hMemDC, .Right, .Bottom)
            Call LineTo(hMemDC, .Left, .Bottom)
            Call LineTo(hMemDC, .Left, .Top)
        End With
        Call DeleteObject(hPen)
    End If
  
    With tClientRect
        Call SetRect(tTitleBarRect, 0, -tMt.FrameHeight, .Right, .Top + tMt.CaptionHeight + 1)
    End With

    Call ConvertLongToRGB(lBackColor, R, G, B)
    With vert(0)
        .X = 1
        .Y = 1
        .Red = TransfCol(R)
        .Green = TransfCol(G)
        .Blue = TransfCol(B)
        .alpha = TransfCol(0)
    End With
    With vert(1)
        .X = tTitleBarRect.Right - tTitleBarRect.Left - 1
        .Y = tTitleBarRect.Bottom - tTitleBarRect.Top - 1
        .Red = IIf(bGradientColor, 0, TransfCol(R))
        .Green = IIf(bGradientColor, 0, TransfCol(G))
        .Blue = IIf(bGradientColor, 0, TransfCol(B))
        .alpha = TransfCol(0)
    End With
    tPt.UpperLeft = 0: tPt.LowerRight = 1
    Call GradientFillRect(hMemDC, vert(0), 2, tPt, 1, GRADIENT_FILL_RECT_H)
  
    Call DrawIcon(hMemDC, 2, 1, hIcon)

    Set IFont = oForm.Font
    With tFont
        If Len(.FontName) Then
            IFont.Name = .FontName
            IFont.Size = .FontSize
            IFont.Bold = .FontBold
            IFont.Italic = .FontItalic
        End If
    End With
  
    hPrevFont = SelectObject(hMemDC, IFont.hFont)
    Call SetBkMode(hMemDC, TRANSPARENT)
    Call SetTextColor(hMemDC, lFontColor)
  
    lTextHeight = DrawText(hMemDC, sFormCaption, Len(sFormCaption), tTextRect, DT_CALCRECT)

    With tClientRect
        Call SetRect(tTitleBarRect, 0, 0, .Right, tMt.CaptionHeight + tMt.FrameHeight)
    End With
            
    With tTitleBarRect
        If bCenterText Then
            Call SetRect( _
                tTextPosRect, ((.Right) - (tTextRect.Right)) / 2, _
                ((tMt.CaptionHeight + tMt.FrameWidth + tMt.FrameHeight) - tTextRect.Bottom) / 2, _
                .Right, _
                .Bottom)
        Else
            Call SetRect( _
                tTextPosRect, _
                IIf(hIcon, GetSystemMetrics(SM_CXICON) + _
                GetSystemMetrics(SM_CXFRAME), _
                GetSystemMetrics(SM_CXFRAME) + _
                GetSystemMetrics(SM_CXBORDER)), _
                ((tMt.CaptionHeight + tMt.FrameWidth + tMt.FrameHeight) - tTextRect.Bottom) / 2, _
                .Right, _
                .Bottom)
        End If
    End With
              
    Call DrawText(hMemDC, sFormCaption, Len(sFormCaption), tTextPosRect, DT_SINGLELINE)
  
    If CaptionPicsCollection Is Nothing Then
        Set CaptionPicsCollection = New Collection
    End If
    CaptionPicsCollection.Add BmpToStdPic(hMemBmp), "ActiveCaptionPic"
  
    If BMPsCol Is Nothing Then
        Set BMPsCol = New Collection
    End If
    BMPsCol.Add hMemBmp

Xit:
    Call SelectObject(hMemDC, hOldBmp)
    Call DeleteObject(hOldBmp)
    Call SelectObject(hMemDC, hPrevFont)
    Call DeleteObject(hPrevFont)
    Call DeleteDC(hMemDC)
    Call ReleaseDC(hwnd, hDC)
  
    If Err.Number <> 0 Then Call DestroyWindow(hShadow)

End Sub

Private Sub DrawInActiveCaption(ByVal oForm As Object)

    Const SM_CXICON = 11
    Const SM_CXBORDER = 5
    Const SM_CXFRAME = 32
    Const COLOR_BTNFACE = 15
    Const COLOR_BTNHIGHLIGHT = 20
    Const COLOR_INACTIVECAPTION = 3
    Const SRCCOPY = &HCC0020
    Const DT_SINGLELINE = &H20
    Const DT_CALCRECT = &H400
    Const PS_SOLID = 1
    Const TRANSPARENT = 1
    Const RGN_DIFF = 4

    #If Win64 Then
        Dim hDC As LongLong, hBrush As LongLong, hPrevFont As LongLong, hOldBrush As LongLong
        Dim hMemDC As LongLong, hMemBmp As LongLong, hOldBmp As LongLong, hPen As LongLong, hOldPen As LongLong
        Dim hDisabledMemDc As LongLong, hDisabledMemBmp As LongLong, hDisabledOldMemBmp As LongLong
        Dim hRgn1 As LongLong, hRgn2 As LongLong
    #Else
        Dim hDC As Long, hBrush As Long, hPrevFont As Long, hOldBrush As Long
        Dim hMemDC As Long, hMemBmp As Long, hOldBmp As Long, hPen As Long, hOldPen As Long
        Dim hDisabledMemDc As Long, hDisabledMemBmp As Long, hDisabledOldMemBmp As Long
        Dim hRgn1 As Long, hRgn2 As Long
    #End If

    Dim tTitleBarRect As RECT, tClientRect As RECT, tTextRect As RECT, tTextPosRect As RECT
    Dim IFont As stdole.IFont
    Dim lTextHeight As Long, lRealColor As Long
  
    On Error GoTo Xit
 
    hDC = GetDC(hwnd)
    Call GetClientRect(hwnd, tClientRect)

    hMemDC = CreateCompatibleDC(0)
    hMemBmp = CreateCompatibleBitmap(hDC, tClientRect.Right, tClientRect.Bottom)
    hOldBmp = SelectObject(hMemDC, hMemBmp)

    Call TranslateColor(oForm.BackColor, 0, lRealColor)
    hBrush = CreateSolidBrush(lRealColor)
    hOldBrush = SelectObject(hMemDC, hBrush)
    Call FillRect(hMemDC, tClientRect, hBrush)
    Call SelectObject(hMemDC, hOldBrush)
    Call DeleteObject(hBrush)

    With tTitleBarRect
        .Left = tClientRect.Left
        .Top = tClientRect.Top
        .Right = tClientRect.Right
        .Bottom = tClientRect.Top + tMt.CaptionHeight + tMt.FrameHeight
    End With
      
    Call TranslateColor(oForm.BackColor, 0, lRealColor)
    If GetSysColor(COLOR_BTNFACE) = lRealColor Then
        hBrush = CreateSolidBrush(GetSysColor(COLOR_BTNHIGHLIGHT))
    Else
        hBrush = CreateSolidBrush(GetSysColor(COLOR_BTNFACE))
    End If
    Call FillRect(hMemDC, tTitleBarRect, hBrush)
    Call DeleteObject(hBrush)

    Call DrawIcon(hMemDC, 2, 1, hIcon)

    Set IFont = oForm.Font
    With tFont
        If Len(.FontName) Then
            IFont.Name = .FontName
            IFont.Size = .FontSize
            IFont.Bold = .FontBold
            IFont.Italic = .FontItalic
        End If
    End With
    hPrevFont = SelectObject(hMemDC, IFont.hFont)

    Call SetBkMode(hMemDC, TRANSPARENT)
    Call SetTextColor(hMemDC, &HAB40&)

    lTextHeight = DrawText(hMemDC, sFormCaption, Len(sFormCaption), tTextRect, DT_CALCRECT)

    With tClientRect
        Call SetRect(tTitleBarRect, 0, 0, .Right, tMt.CaptionHeight + tMt.FrameHeight)
    End With
            
    With tTitleBarRect
         If bCenterText Then
             Call SetRect( _
                 tTextPosRect, ((.Right) - (tTextRect.Right)) / 2, _
                 ((tMt.CaptionHeight + tMt.FrameWidth + tMt.FrameHeight) - tTextRect.Bottom) / 2, _
                 .Right, _
                 .Bottom)
         Else
            Call SetRect( _
                 tTextPosRect, _
                IIf(hIcon, GetSystemMetrics(SM_CXICON) + _
                     GetSystemMetrics(SM_CXFRAME), _
                      GetSystemMetrics(SM_CXFRAME) + _
                     GetSystemMetrics(SM_CXBORDER)), _
              ((tMt.CaptionHeight + tMt.FrameWidth + tMt.FrameHeight) - tTextRect.Bottom) / 2, _
                 .Right, _
                 .Bottom)
        End If
     End With

    Call DrawText(hMemDC, sFormCaption, Len(sFormCaption), tTextPosRect, DT_SINGLELINE)
                
    hDisabledMemDc = CreateCompatibleDC(0)
    hDisabledMemBmp = CreateCompatibleBitmap(hDC, tClientRect.Right, tClientRect.Bottom)
    hDisabledOldMemBmp = SelectObject(hDisabledMemDc, hDisabledMemBmp)

    With tClientRect
  
        Call BitBlt(hDisabledMemDc, 0, 0, .Right, .Bottom, hMemDC, 0, 0, SRCCOPY)
        hRgn1 = CreateRectRgn(0, 0, .Right, .Bottom)
        hRgn2 = CreateRectRgn(0, tMt.CaptionHeight + tMt.FrameHeight, .Right - 1, .Bottom - 1)
        Call CombineRgn(hRgn2, hRgn1, hRgn2, RGN_DIFF)
        Call SelectClipRgn(hDisabledMemDc, hRgn2)
        Call DrawDisabledBitmap(hDisabledMemDc, hDisabledMemBmp, 0, 0, .Right, .Bottom)
        Call SelectClipRgn(hDisabledMemDc, 0)

        Call TranslateColor(GetSysColor(COLOR_INACTIVECAPTION), 0, lRealColor)
        hPen = CreatePen(PS_SOLID, 2, lRealColor)
        hOldPen = SelectObject(hDisabledMemDc, hPen)
        With tClientRect
            Call MoveToEx(hDisabledMemDc, .Left, .Top, ByVal 0)
            Call LineTo(hDisabledMemDc, .Right, .Top)
            Call LineTo(hDisabledMemDc, .Right, .Bottom)
            Call LineTo(hDisabledMemDc, .Left, .Bottom)
            Call LineTo(hDisabledMemDc, .Left, .Top)
        End With
        Call DeleteObject(hPen)
      
    End With

    If CaptionPicsCollection Is Nothing Then
        Set CaptionPicsCollection = New Collection
    End If
    CaptionPicsCollection.Add BmpToStdPic(hDisabledMemBmp), "InActiveCaptionPic"

    If BMPsCol Is Nothing Then
        Set BMPsCol = New Collection
    End If
    BMPsCol.Add hDisabledMemBmp
  
Xit:
    Call SelectObject(hMemDC, hOldBmp)
    Call DeleteObject(hOldBmp)
    Call SelectObject(hMemDC, hPrevFont)
    Call DeleteObject(hPrevFont)
    Call DeleteDC(hMemDC)
    Call SelectObject(hDisabledMemDc, hDisabledOldMemBmp)
    Call DeleteObject(hDisabledOldMemBmp)
    Call DeleteDC(hDisabledMemDc)
    Call ReleaseDC(hwnd, hDC)
  
    If Err.Number <> 0 Then Call DestroyWindow(hShadow)
  
End Sub

#If Win64 Then
    Private Function DrawDisabledBitmap(ByVal hDC As LongLong, ByVal hBitmap As LongLong, ByVal Left As Long, ByVal Top As Long, Optional ByVal Width As Long = -1, Optional ByVal Height As Long = -1) As Boolean
        Dim hImage As LongLong, hGraphics As LongLong, hAttributes As LongLong
#Else
    Private Function DrawDisabledBitmap(ByVal hDC As Long, ByVal hBitmap As Long, ByVal Left As Long, ByVal Top As Long, Optional ByVal Width As Long = -1, Optional ByVal Height As Long = -1) As Boolean
        Dim hImage As Long, hGraphics As Long, hAttributes As Long
#End If

    'Credit for this function goes to LeandroA  at VBForums-- Thanks.
    'https://www.vbforums.com/showthread.php?894142-Embossed-Disabled-Bitmap&p=5543513&viewfull=1#post5543513

    Const SmoothingModeAntiAlias    As Long = 4

    Dim GdipStartupInput As GDIPlusStartupInput
    Dim GdipToken As Long
    Dim tMatrixColor As COLORMATRIX
    Dim tMatrixGray As COLORMATRIX
    Dim RealWidth As Long, RealHeight As Long
  
    With tMatrixColor
        .M(0, 0) = 0.299
        .M(1, 0) = 0.299
        .M(2, 0) = 0.299
        .M(0, 1) = 0.587
        .M(1, 1) = 0.587
        .M(2, 1) = 0.587
        .M(0, 2) = 0.114
        .M(1, 2) = 0.114
        .M(2, 2) = 0.114
        .M(3, 3) = 1
        .M(4, 4) = 1
    End With
  
    GdipStartupInput.GdiPlusVersion = 1&
    If GdiplusStartup(GdipToken, GdipStartupInput, ByVal 0) = 0& Then
        If GdipCreateFromHDC(hDC, hGraphics) = 0& Then
            Call GdipSetSmoothingMode(hGraphics, SmoothingModeAntiAlias)
            If GdipCreateBitmapFromHBITMAP(hBitmap, 0&, hImage) = 0& Then
                Call GdipGetImageWidth(hImage, RealWidth)
                Call GdipGetImageHeight(hImage, RealHeight)
                If Width = -1 Then Width = RealWidth
                If Height = -1 Then Height = RealHeight
                Call GdipCreateImageAttributes(hAttributes)
                Call GdipSetImageAttributesColorMatrix(hAttributes, &H0, True, tMatrixColor, tMatrixGray, &H0)
                DrawDisabledBitmap = GdipDrawImageRectRectI(hGraphics, hImage, Left, Top, Width, Height, 0, 0, RealWidth, RealHeight, &H2, hAttributes) = 0&
                Call GdipDisposeImage(hImage)
                Call GdipDisposeImageAttributes(hAttributes)
            End If
            Call GdipDeleteGraphics(hGraphics)
        End If
        Call GdiplusShutdown(GdipToken)
    End If
End Function


Private Sub ChangeFormWinStyles(ByVal oForm As Object)

    Const GWL_STYLE = (-16)
    Const GWL_EXSTYLE = (-20)
    Const GCL_STYLE = -26
    Const WS_BORDER = &H800000
    Const WS_THICKFRAME = &H40000
    Const WS_CAPTION = &HC00000
    Const WS_DLGFRAME = &H400000
    Const WS_EX_DLGMODALFRAME = &H1&
    Const WS_EX_WINDOWEDGE = &H100&
    Const WS_EX_STATICEDGE = &H20000
  
    Call SetWindowLong(hwnd, GWL_STYLE, _
            GetWindowLong(hwnd, GWL_STYLE) And Not (WS_BORDER Or WS_THICKFRAME _
            Or WS_CAPTION Or WS_DLGFRAME))
  
    Call SetWindowLong(hwnd, GWL_EXSTYLE, _
            GetWindowLong(hwnd, GWL_EXSTYLE) And Not (WS_EX_DLGMODALFRAME Or _
            WS_EX_WINDOWEDGE Or WS_EX_STATICEDGE))
  
    Call DrawMenuBar(hwnd)

End Sub

Private Function DrawCloseBtn(ByVal oFrame As Frame, ByVal FrameState As Long) As StdPicture

    Const DFCS_ADJUSTRECT = &H2000
    Const DFC_CAPTION = 1
    Const DFCS_CAPTIONCLOSE = &H0
  
    #If Win64 Then
        Dim hFrame As LongLong, hDC As LongLong, hMemDC As LongLong
        Dim hMemBmp As LongLong, hOldBmp As LongLong
    #Else
        Dim hFrame As Long, hDC As Long, hMemDC As Long
        Dim hMemBmp As Long, hOldBmp As Long
    #End If
      
    Dim tClientRect As RECT
    
    Call IUnknown_GetWindow(oFrame, VarPtr(hFrame))
    Call GetClientRect(hFrame, tClientRect)
    hDC = GetDC(0)
    hMemDC = CreateCompatibleDC(0)
    hMemBmp = CreateCompatibleBitmap(hDC, tClientRect.Right, tClientRect.Bottom)
    hOldBmp = SelectObject(hMemDC, hMemBmp)
    If hMemBmp Then
        Call DrawFrameControl(hMemDC, tClientRect, DFC_CAPTION, DFCS_CAPTIONCLOSE + DFCS_ADJUSTRECT + FrameState)
        Set oFrame.Picture = BmpToStdPic(hMemBmp)
        If BMPsCol Is Nothing Then
            Set BMPsCol = New Collection
        End If
        BMPsCol.Add hMemBmp
        If FramePicsCollection Is Nothing Then
            Set FramePicsCollection = New Collection
        End If
        FramePicsCollection.Add oFrame.Picture
    End If
  
    Call ReleaseDC(0, hDC)
    Call SelectObject(hMemDC, hOldBmp)
    Call DeleteObject(hOldBmp)
    Call DeleteDC(hMemDC)

End Function

Private Function GetWinMetrics() As NCL_METRICS

    Const SM_CYCAPTION = 4
    Const SM_CXBORDER = 5
    Const SM_CYBORDER = 6
    Const SM_CXEDGE = 45
    Const SM_CXFIXEDFRAME = 7
    Const SM_CYDLGFRAME = 8
    Const SM_CYEDGE = 46
    Const SM_CYFIXEDFRAME = 8
  
    With tMt
        .CaptionHeight = GetSystemMetrics(SM_CYCAPTION) + 1
        .FrameHeight = GetSystemMetrics(SM_CYEDGE) + _
                GetSystemMetrics(SM_CYFIXEDFRAME) + _
                GetSystemMetrics(SM_CYBORDER) + _
                GetSystemMetrics(SM_CYDLGFRAME)
        .FrameWidth = GetSystemMetrics(SM_CXEDGE) + _
                GetSystemMetrics(SM_CXFIXEDFRAME) + _
                GetSystemMetrics(SM_CXBORDER)
    End With

    GetWinMetrics = tMt

End Function

Private Sub AddCloseFrame(ByVal oForm As Object)

    Const SM_CXSMICON = 49
    Const SM_CXBORDER = 5
    Const SM_CXDLGFRAME = 7
    Const SM_CYDLGFRAME = 8
    Const SM_CYSMICON = 50
    Const SM_CYCAPTION = 4

    Dim lFrmColor As Long
  
    Set oFrame = oForm.Controls.Add("Forms.Frame.1", "CloseFrame")
  
    lFrmColor = oForm.BackColor
    Call TranslateColor(oForm.BackColor, 0, lFrmColor)
  
    With oFrame
        .Left = oForm.InsideWidth - _
        GetSystemMetrics(SM_CXSMICON) - _
        GetSystemMetrics(SM_CXDLGFRAME) - _
        GetSystemMetrics(SM_CXBORDER)
      
        .Top = ((GetSystemMetrics(SM_CYCAPTION) + _
        GetSystemMetrics(SM_CYDLGFRAME) - _
        GetSystemMetrics(SM_CYSMICON)) / 2) - 1
      
        .Width = GetSystemMetrics(SM_CXSMICON)
        .Height = GetSystemMetrics(SM_CYSMICON)
      
        .BackColor = lBackColor
        .BorderStyle = fmBorderStyleSingle
        .BorderColor = lFrmColor
        .TabStop = False
        .ZOrder 0
    End With

End Sub

Private Sub ShiftFormControls(ByVal oForm As Object)

    Const SM_CXDLGFRAME = 7
    Const SM_CXBORDER = 5
    Const SM_CXFIXEDFRAME = 7
    Const SM_CXEDGE = 45

    Dim Ctrl As Control
  
    For Each Ctrl In oForm.Controls
        If Ctrl.Parent Is oForm Then
            Ctrl.Top = Ctrl.Top + PXtoPT(tMt.CaptionHeight + tMt.FrameHeight, True)
            Ctrl.Left = Ctrl.Left + 1
        End If
    Next
  
   oForm.Width = oForm.Width - _
        PXtoPT(1 * GetSystemMetrics(SM_CXFIXEDFRAME) + _
        1 * GetSystemMetrics(SM_CXBORDER) + _
        0 * GetSystemMetrics(SM_CXEDGE), False)
    oForm.Height = oForm.Height + 2
  
End Sub

Private Sub CreateShadow()

    Const GWL_HWNDPARENT = (-8)
    Const WS_POPUP = &H80000000
    Const WS_VISIBLE = &H10000000
    Const WS_DISABLED = &H8000000
    Const SWP_NOSIZE = &H1
    Const SWP_NOACTIVATE = &H10
    Const SWP_DEFERERASE = &H2000
    Const SWP_NOREDRAW = &H8
    Const SWP_SHOWWINDOW = &H40
    Const WS_EX_NOACTIVATE = &H8000000
    Const WS_EX_TOOLWINDOW = &H80
    Const COLOR_BTNSHADOW = 16
    Const RGN_DIFF = 4

    #If Win64 Then
        Dim hRgn1 As LongLong, hRgn2 As LongLong, hDC As LongLong, hBrush As LongLong
    #Else
        Dim hRgn1 As Long, hRgn2 As Long, hDC As Long, hBrush As Long
    #End If

    Dim tFormRect As RECT, tRgnRect As RECT
    Dim lOffset As Long

    Call GetWindowRect(hwnd, tFormRect)
  
    lOffset = 2
    With tFormRect
        If IsWindow(hShadow) = 0 Then
            hShadow = CreateWindowEx(0 Or WS_EX_TOOLWINDOW Or WS_EX_NOACTIVATE, "BUTTON", vbNullString, _
                 WS_POPUP Or WS_DISABLED, 0, 0, .Right - .Left - (lOffset * 2), _
                .Bottom - .Top - (lOffset * 2), 0, 0, GetModuleHandle(vbNullString), 0)
            Call SetWindowLong(hShadow, GWL_HWNDPARENT, hwnd)
        End If
        Call SetRect(tRgnRect, 0, 0, .Right - .Left, .Bottom - .Top)
        hBrush = CreateSolidBrush(&H595959)
        hRgn1 = CreateRectRgn(0, 0, tRgnRect.Right, tRgnRect.Bottom)
        hRgn2 = CreateRectRgn(0, 0, tRgnRect.Right - (lOffset * 3), tRgnRect.Bottom - (lOffset * 3))
        Call CombineRgn(hRgn2, hRgn1, hRgn2, RGN_DIFF)
        hDC = GetDC(hShadow)
        Call SelectClipRgn(hDC, hRgn2)
        Call SetWindowRgn(hShadow, hRgn2, True)
    End With
  
    With tFormRect
        Call SetWindowPos(hShadow, hwnd, .Left + (lOffset * 3), .Top + (lOffset * 3), 0, 0, _
                SWP_NOACTIVATE Or SWP_DEFERERASE Or SWP_NOSIZE Or SWP_SHOWWINDOW)
        Call FillRect(hDC, tRgnRect, hBrush)
    End With
          
    Call DeleteObject(hBrush)
    Call DeleteObject(hRgn1)
    Call DeleteObject(hRgn2)
    Call ReleaseDC(hShadow, hDC)

End Sub

Private Sub oFrame_MouseDown(ByVal Button As Integer, ByVal Shift As Integer, ByVal X As Single, ByVal Y As Single)
    If Button = 1 Then
        Set oFrame.Picture = FramePicsCollection(3)
    End If
End Sub

Private Sub oFrame_MouseMove(ByVal Button As Integer, ByVal Shift As Integer, ByVal X As Single, ByVal Y As Single)
    If GetAsyncKeyState(VBA.vbKeyLButton) Then
        Set oFrame.Picture = FramePicsCollection(3)
    Else
        Set oFrame.Picture = FramePicsCollection(2)
    End If
End Sub

Private Sub oFrame_MouseUp(ByVal Button As Integer, ByVal Shift As Integer, ByVal X As Single, ByVal Y As Single)

    Const SW_HIDE = 0

    #If Win64 Then
        Dim hFrame As LongLong, Ptr As LongLong
    #Else
        Dim hFrame As Long
    #End If

    Dim tCurPos As POINTAPI

    If Button = 1 Then
        Call IUnknown_GetWindow(oFrame, VarPtr(hFrame))
        Call GetCursorPos(tCurPos)
        #If Win64 Then
            Call CopyMemory(Ptr, tCurPos, LenB(tCurPos))
            If WindowFromPoint(Ptr) = hFrame Then
        #Else
            If WindowFromPoint(tCurPos.X, tCurPos.Y) = hFrame Then
        #End If
                Call ShowWindow(hShadow, SW_HIDE)
                Call SetActiveWindow(hwnd)
                Unload objForm
            End If
    End If

End Sub

Private Sub objForm_MouseMove(ByVal Button As Integer, ByVal Shift As Integer, ByVal X As Single, ByVal Y As Single)

    Const WM_NCLBUTTONDOWN = &HA1
    Const HTCAPTION = 2
    Const SWP_NOSIZE = &H1
    Const SWP_NOACTIVATE = &H10
    Const SWP_DEFERERASE = &H2000
    Const SWP_NOREDRAW = &H8
    Const SWP_SHOWWINDOW = &H40
    Const SW_HIDE = 0
  
    Dim tFormRect  As RECT, lOffset As Long
  
    lOffset = 2
 
    If IsMouseOverTitleBar(objForm) Then
        If GetAsyncKeyState(VBA.vbKeyLButton) Then
            If IsWindowVisible(hShadow) Then
                If GetAsyncKeyState(VBA.vbKeyLButton) Then
                    Call ShowWindow(hShadow, SW_HIDE)
                End If
            End If
        Else
            If IsWindowVisible(hShadow) = 0 Then
                Call GetWindowRect(hwnd, tFormRect)
                With tFormRect
                    Call SetWindowPos(hShadow, hwnd, .Left + (lOffset * 3), .Top + (lOffset * 3), 0, 0, _
                            SWP_NOACTIVATE Or SWP_DEFERERASE Or SWP_NOSIZE Or SWP_SHOWWINDOW)
                End With
            End If
        End If
        If Button = 1 Then
            Call ReleaseCapture
            Call PostMessage(hwnd, WM_NCLBUTTONDOWN, HTCAPTION, 0)
        End If
    End If

    If GetActiveWindow = hwnd Then
        If FramePicsCollection.Count Then
            Set oFrame.Picture = FramePicsCollection(1)
        End If
    End If
  
End Sub

Private Sub objForm_MouseDown(ByVal Button As Integer, ByVal Shift As Integer, ByVal X As Single, ByVal Y As Single)
  
    Const MF_BYPOSITION = &H400
    Const MF_STRING = &H0&
    Const TPM_RETURNCMD = &H100&
    Const SW_HIDE = 0

    #If Win64 Then
        Dim hMenu As LongLong
    #Else
        Dim hMenu As Long
    #End If

    Dim oStdPic As StdPicture
    Dim tCursorPos As POINTAPI
    Dim lShowPopupMenu As Long

    If Button = 2 Then
        If IsMouseOverTitleBar(objForm) Then
            Set oStdPic = FaceIDToBMP(840)
            hMenu = CreatePopupMenu()
            Call AppendMenu(hMenu, MF_STRING, 1, "&Close   (Alt +F4)")
            If Not oStdPic Is Nothing Then
                Call SetMenuItemBitmaps(hMenu, 0, MF_BYPOSITION, oStdPic, oStdPic)
            End If
            Call GetCursorPos(tCursorPos)
            lShowPopupMenu = TrackPopupMenuEx(hMenu, TPM_RETURNCMD, tCursorPos.X, tCursorPos.Y, hwnd, ByVal 0&)
            Set oStdPic = Nothing
            Call DestroyMenu(hMenu)
            If lShowPopupMenu = 1 Then
                Call ShowWindow(hShadow, SW_HIDE)
                Call SetActiveWindow(hwnd)
                Unload objForm
            End If
        End If
    End If

End Sub

Private Function IsMouseOverTitleBar(ByVal oForm As Object) As Boolean

    Dim tMt As NCL_METRICS, tTitleBarRect As RECT
    Dim p1 As POINTAPI, p2 As POINTAPI, tCurPos As POINTAPI
    Dim lRet As Long
  
    tMt = GetWinMetrics
    Call GetClientRect(hwnd, tTitleBarRect)
    With tTitleBarRect
        p1.X = .Left
        p1.Y = .Top
        p2.X = .Right
        p2.Y = .Top + tMt.CaptionHeight + tMt.FrameHeight
        Call ClientToScreen(hwnd, p1)
        Call ClientToScreen(hwnd, p2)
        .Left = p1.X
        .Top = p1.Y
        .Right = p2.X
        .Bottom = p2.Y
    End With
  
    Call GetCursorPos(tCurPos)
  
    #If Win64 Then
        Dim lPtr As LongLong
        Call CopyMemory(lPtr, tCurPos, LenB(tCurPos))
        lRet = PtInRect(tTitleBarRect, lPtr)
    #Else
        lRet = PtInRect(tTitleBarRect, tCurPos.X, tCurPos.Y)
    #End If
  
    If lRet Then
        IsMouseOverTitleBar = True
    End If

End Function


Private Function FaceIDToBMP(ByVal FaceID As Long) As StdPicture

    #If Win64 Then
            Dim hBmpPtr As LongLong
    #Else
            Dim hBmpPtr As Long
    #End If

    Const IMAGE_BITMAP = 0
    Const LR_COPYDELETEORG = &H8
    Const PICTYPE_BITMAP = 1
    Const CF_BITMAP = 2
    Const S_OK = &H0&

    Dim IID_IDispatch As GUID, uPicInfo As uPicDesc
    Dim IPic As Object, lRet As Long
 
    On Error GoTo errHandler
 
    Application.CommandBars.FindControl(ID:=FaceID).CopyFace
    Call OpenClipboard(0)
    hBmpPtr = GetClipboardData(CF_BITMAP)
    Call DeleteObject(hBmpPtr)
    hBmpPtr = CopyImage(hBmpPtr, IMAGE_BITMAP, 0, 0, LR_COPYDELETEORG)
 
    If hBmpPtr Then
        With IID_IDispatch
            .Data1 = &H20400
            .Data4(0) = &HC0
            .Data4(7) = &H46
        End With
        With uPicInfo
            .Size = Len(uPicInfo)
            .Type = PICTYPE_BITMAP
            .hPic = hBmpPtr
            .hPal = 0
        End With
        lRet = OleCreatePictureIndirect(uPicInfo, IID_IDispatch, True, IPic)
        If lRet = S_OK Then
            Set FaceIDToBMP = IPic
        End If
    End If
 
errHandler:
    Call EmptyClipboard
    Call CloseClipboard
 
End Function

#If Win64 Then
    Private Function BmpToStdPic(ByVal Bmp As LongLong) As StdPicture
#Else
    Private Function BmpToStdPic(ByVal Bmp As Long) As StdPicture
#End If

    Const PICTYPE_BITMAP = 1
    Const S_OK = 0
  
    Dim IID_IDispatch As GUID, uPicInfo As uPicDesc, oStdPic As StdPicture, lRet As Long
  
    With IID_IDispatch
        .Data1 = &H20400
        .Data4(0) = &HC0
        .Data4(7) = &H46
    End With
    With uPicInfo
        .Size = Len(uPicInfo)
        .Type = PICTYPE_BITMAP
        .hPic = Bmp
        .hPal = 0
    End With
    lRet = OleCreatePictureIndirect(uPicInfo, IID_IDispatch, True, oStdPic)
    If lRet = S_OK Then Set BmpToStdPic = oStdPic
  
End Function


Private Function ScreenDPI(ByVal bVert As Boolean) As Long
    Const LOGPIXELSX As Long = 88
    Const LOGPIXELSY As Long = 90
    Static lDPI(1), hDC

    If lDPI(0) = 0 Then
        hDC = GetDC(0)
        lDPI(0) = GetDeviceCaps(hDC, LOGPIXELSX)
        lDPI(1) = GetDeviceCaps(hDC, LOGPIXELSY)
        hDC = ReleaseDC(0, hDC)
    End If
    ScreenDPI = lDPI(Abs(bVert))
End Function

Private Function PXtoPT(ByVal Pixels As Long, ByVal bVert As Boolean) As Single
    Const POINTSPERINCH As Long = 72
    PXtoPT = Pixels / (ScreenDPI(bVert) / POINTSPERINCH)
End Function

Private Sub ConvertLongToRGB(ByVal Value As Long, R As Byte, G As Byte, B As Byte)
    R = Value Mod 256
    G = Int(Value / 256) Mod 256
    B = Int(Value / 256 / 256) Mod 256
End Sub

Private Function TransfCol(ByVal Col As Long) As Double
    Dim a As Double
    If Col = 0 Then
        TransfCol = 0
    ElseIf Col > 127 Then
        a = 256 - Col
        TransfCol = -(256 * a)
    Else
        a = Col
        TransfCol = 256 * a
    End If
End Function



2- Code Usage Example in UserForm:
VBA Code:
Option Explicit

Private Type TITLE_BAR
    tSize As Long
    CaptionColor As Variant
    FontName As String * 256
    FontSize As Long
    FontColor As Long
    FontBold As Boolean
    FontItalic As Boolean
    DrawFrame As Boolean
    CenterText As Boolean
    GradientColor As Boolean
    DisableWhenInActive As Boolean
    IconFile As String * 256
End Type

Private oTitleBar As CTitleBar


Private Sub UserForm_Initialize()

    Dim uTitleBar As TITLE_BAR

    With uTitleBar
        .tSize = LenB(uTitleBar)
        .CaptionColor = vbRed
        .FontName = "Orbitron" & vbNullChar
        .FontSize = 24
        .FontColor = vbCyan
        .FontBold = True
        .DrawFrame = True
        .CenterText = True
        .DisableWhenInActive = True
        .GradientColor = True
        .IconFile = ThisWorkbook.Path & "\test.ico" & vbNullChar   '<==change icon path as needed.
    End With

    Set oTitleBar = New CTitleBar
    Call oTitleBar.Attach(Me, VarPtr(uTitleBar))

End Sub

Private Sub UserForm_Activate()
    oTitleBar.Enable True
End Sub

Private Sub UserForm_Deactivate()
    oTitleBar.Enable False
End Sub


Code tested on excel 2016 x64bit, Win 10 x64bit but hopefully should work on other platforms.
 
Last edited:

Excel Facts

What does custom number format of ;;; mean?
Three semi-colons will hide the value in the cell. Although most people use white font instead.
Office 365 64-bit, Windows 10 64-bit.
Moving by dragging title bar is unreliable and slow, sometimes you have to hold the mouse down for 5+ seconds before you can get it to move.
Why use an xls file?
 
Upvote 0
Office 365 64-bit, Windows 10 64-bit.
Moving by dragging title bar is unreliable and slow, sometimes you have to hold the mouse down for 5+ seconds before you can get it to move.

Thanks for testing and for the feedback.

I don't have office 365 64-bit so I can't give carry out a test ... Is that the only excel version you tested the code on ? If not, how did it go ?

I have personally tested the code on excel 2007,2010,2016 32bit and 64bit, Win7 and win10 32bit and 64bit and it worked fine in all of them.

Why use an xls file?
Just a habit really and since the workbook is just for a demo and won't need xlsm functionality , I thought an xls would be just fine, plus it would be smaller in size.

Would using an xlsm make any difference ?
 
Upvote 0
I've stopped worrying about Excel 2007 and 2010, other than sometimes to check my memory of how things used to be. If Microsoft no longer supports them, I don't feel that I have to. I wish more users and their employers would switch to O365, so I can use the great new features more widely.

I have not noticed much difference in the VBA performance of Office 365 compared to 2016 and earlier. Switching to 64-bit was more of a problem than version, and only with the conversion of Windows APIs. You do a lot more of that than I do, so your experience may well be different.

In general, xls files tend to be larger, often much larger than xlsm or xlsx files. Your xls is 258 kb and the xlsm file I saved it as is 101 kb. The zipped files are close, 88 kb for the xls and 99 kb for the xlsm.
 
Upvote 0
Just a little clarification for someone who isn't an expert in Windows APIs. Does your code draw a new rectangle over the UserForm's actual title bar, or does it actually change the title bar?

I do a trick with some UserForms where I use the APIs to shrink the regular title bar, and I use a formatted label along the top edge of the UserForm's working area as a substitute title bar. I move the form around using the label's mouse down and move events, and it's pretty slick. Maybe I should post a demo.
 
Upvote 0
I opened up a VM with Excel 2016, and the customized UserForms worked much better than in 365. The movement still wasn't as smooth as an unmodified UserForm, and sometimes a form would get stuck for several seconds.
 
Upvote 0
Does your code draw a new rectangle over the UserForm's actual title bar, or does it actually change the title bar?
It removes the userform title bar, increases the height of the userform to compensate for the missing title bar, pushes the controls down and finally draws a formatted rectangle across the top of the client area in order to fake a true caption.

I do a trick with some UserForms where I use the APIs to shrink the regular title bar, and I use a formatted label along the top edge of the UserForm's working area as a substitute title bar. I move the form around using the label's mouse down and move events, and it's pretty slick. Maybe I should post a demo.
I would be interested to see it.

Thanks for your interest.
 
Upvote 0
This is great!
How to make the X Button for closing the userform a bit smaller? it exceeds the title bar size by 1.5 mm
 
Upvote 0

Forum statistics

Threads
1,224,813
Messages
6,181,109
Members
453,021
Latest member
Justyna P

We've detected that you are using an adblocker.

We have a great community of people providing Excel help here, but the hosting costs are enormous. You can help keep this site running by allowing ads on MrExcel.com.
Allow Ads at MrExcel

Which adblocker are you using?

Disable AdBlock

Follow these easy steps to disable AdBlock

1)Click on the icon in the browser’s toolbar.
2)Click on the icon in the browser’s toolbar.
2)Click on the "Pause on this site" option.
Go back

Disable AdBlock Plus

Follow these easy steps to disable AdBlock Plus

1)Click on the icon in the browser’s toolbar.
2)Click on the toggle to disable it for "mrexcel.com".
Go back

Disable uBlock Origin

Follow these easy steps to disable uBlock Origin

1)Click on the icon in the browser’s toolbar.
2)Click on the "Power" button.
3)Click on the "Refresh" button.
Go back

Disable uBlock

Follow these easy steps to disable uBlock

1)Click on the icon in the browser’s toolbar.
2)Click on the "Power" button.
3)Click on the "Refresh" button.
Go back
Back
Top