Jaafar Tribak

Well-known Member
Joined
Dec 5, 2002
Messages
9,806
Office Version
  1. 2016
Platform
  1. Windows
This little project took me hours and hours to complete but I think was worthy if only for the learning experience.

The project as such won't be of much use to most excel users but its shows that vba can do all kinds of neat things when combined with the win32 API.

This is what the code does:

* Allows moving and\or copying userform controls at runtime.
* The semi-transparent control that follows the mouse pointer during a dragging operation is actually a win32 static control (This static control, not being a child window of the userform, was the most tricky part to make it a layered window and to keep it confined within the bounderies of the parent form.)
* A colored dashed frame is drawn around the static control.
* The cursor changes dynamically depending on moving the controls , copying them (Holding CTRL key down) or when -the image is being moved outside the parent form. (custom cursor not showing on the Gif below but works as expected in the file demo below)
* Right-click context menu for deleting the controls.
* A label control can optionally be integrated into the class for displaying the current user activity.

This is the signature of only Class Method that hooks the UserForm controls:

Public Sub HookControl( _
ByVal ThisClassInstance As cls_DraggableControl, _
ByVal Ctrl As Control, _
Optional ByVal UILabel As Control _
)

Note: The transparency of the static control won't work unless the Desktop Window Manager (DWM) is enabled in the machine running the code.

Workbook Demo










1- Class code (Cls_DraggableControl):
VBA Code:
Option Explicit

Private Enum eCursor
    Drag_Cursor = 0
    Copy_Cursor = 1
    No_Cursor = 2
End Enum

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 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 LOGPEN
    lopnStyle As Long
    lopnWidth As POINTAPI
    lopnColor As Long
End Type

Private Type LOGBRUSH
    lbStyle As Long
    lbColor As Long
     #If Win64 Then
        lbHatch As LongLong
    #Else
        lbHatch As Long
    #End If
End Type

Private Type GdiplusStartupInput
   GdiplusVersion As Long
  #If Win64 Then
        DebugEventCallback As LongLong
        SuppressBackgroundThread As LongLong
  #Else
        DebugEventCallback As Long
        SuppressBackgroundThread As Long
  #End If
   SuppressExternalCodecs As Long
End Type

#If VBA7 Then
    #If Win64 Then
        Private Declare PtrSafe Function WindowFromPoint Lib "user32" (ByVal Point As LongPtr) As LongLong
        Private Declare PtrSafe Function SetWindowLong Lib "user32" Alias "SetWindowLongPtrA" (ByVal hwnd As LongLong, ByVal nIndex As Long, ByVal dwNewLong As LongLong) As LongLong
    #Else
        Private Declare PtrSafe Function WindowFromPoint Lib "user32" (ByVal xPoint As Long, ByVal yPoint As Long) As LongPtr
        Private Declare PtrSafe Function SetWindowLong Lib "user32" Alias "SetWindowLongA" (ByVal hwnd As LongPtr, ByVal nIndex As Long, ByVal dwNewLong As Long) As LongPtr
    #End If
    
    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 GetModuleHandle Lib "kernel32" Alias "GetModuleHandleA" (ByVal lpModuleName As String) As LongPtr
    Private Declare PtrSafe Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal Length As Long)
    Private Declare PtrSafe Function SetLayeredWindowAttributes Lib "user32" (ByVal hwnd As LongPtr, ByVal crey As Long, ByVal bAlpha As Byte, ByVal dwFlags As Long) As LongPtr
    Private Declare PtrSafe Function GetCursorPos Lib "user32" (lpPoint As POINTAPI) 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 GetWindowRect Lib "user32" (ByVal hwnd As LongPtr, lpRect As RECT) As Long
    Private Declare PtrSafe Function ScreenToClient Lib "user32" (ByVal hwnd As LongPtr, lpPoint As POINTAPI) As Long
    Private Declare PtrSafe Function GetAsyncKeyState Lib "user32" (ByVal vKey As Long) As Integer
    Private Declare PtrSafe Function GetDeviceCaps Lib "gdi32" (ByVal hdc As LongPtr, ByVal nIndex 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 IUnknown_GetWindow Lib "shlwapi" Alias "#172" (ByVal pIUnk As IUnknown, ByVal hwnd As LongPtr) As Long
    Private Declare PtrSafe Function IsChild Lib "user32" (ByVal hWndParent As LongPtr, ByVal hwnd As LongPtr) As Long
    Private Declare PtrSafe Function SendMessage Lib "user32" Alias "SendMessageA" (ByVal hwnd As LongPtr, ByVal wMsg As Long, ByVal wParam As LongPtr, lParam As Any) As LongPtr
    Private Declare PtrSafe Function GetSystemMetrics Lib "user32" (ByVal nIndex As Long) As Long
    Private Declare PtrSafe Function DestroyIcon Lib "user32" (ByVal hIcon As LongPtr) As Long
    Private Declare PtrSafe Function CreateSolidBrush Lib "gdi32" (ByVal crColor 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 DeleteObject Lib "gdi32" (ByVal hObject As LongPtr) As Long
    Private Declare PtrSafe Function SetActiveWindow Lib "user32" (ByVal hwnd As LongPtr) As LongPtr
    Private Declare PtrSafe Function GetNextWindow Lib "user32" Alias "GetWindow" (ByVal hwnd As LongPtr, ByVal wFlag As Long) As LongPtr
    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 SetWindowRgn Lib "user32" (ByVal hwnd As LongPtr, ByVal hRgn As LongPtr, ByVal bRedraw As Long) 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 IntersectRect Lib "user32" (lpDestRect As RECT, lpSrc1Rect As RECT, lpSrc2Rect As RECT) As Long
    Private Declare PtrSafe Function IsRectEmpty Lib "user32" (lpRect As RECT) As Long
    Private Declare PtrSafe Function DwmGetWindowAttribute Lib "Dwmapi.dll" (ByVal hwnd As LongPtr, ByVal dwAttribute As Long, ByRef pvAttribute As Any, ByVal cbAttribute As Long) As Long
    Private Declare PtrSafe Function ExtCreatePen Lib "gdi32" (ByVal dwPenStyle As Long, ByVal dwWidth As Long, lplb As LOGBRUSH, ByVal dwStyleCount As Long, lpStyle As Long) As LongPtr
    Private Declare PtrSafe Function Rectangle Lib "gdi32" (ByVal hdc As LongPtr, ByVal X1 As Long, ByVal Y1 As Long, ByVal X2 As Long, ByVal Y2 As Long) As Long
    Private Declare PtrSafe Function GetStockObject Lib "gdi32" (ByVal nIndex As Long) As LongPtr
    Private Declare PtrSafe Function CreateIconFromResourceEx Lib "user32.dll" (ByRef presbits As Any, ByVal dwResSize As Long, ByVal fIcon As Long, ByVal dwVer As Long, ByVal cxDesired As Long, ByVal cyDesired As Long, ByVal Flags As Long) As LongPtr
    Private Declare PtrSafe Function SetCursorAPI Lib "user32" Alias "SetCursor" (ByVal hCursor As LongPtr) As LongPtr
    Private Declare PtrSafe Function LoadCursor Lib "user32" Alias "LoadCursorA" (ByVal hInstance As LongPtr, ByVal lpCursorName 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 CreatePopupMenu Lib "user32" () As LongPtr
    Private Declare PtrSafe Function DestroyMenu Lib "user32" (ByVal hMenu 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 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 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
    'GDI+
    Private Declare PtrSafe Function GdiplusStartup Lib "gdiplus" (token As LongPtr, inputbuf As GdiplusStartupInput, Optional ByVal outputbuf As Long = 0) As Long
    Private Declare PtrSafe Function GdiplusShutdown Lib "gdiplus" (ByVal token As LongPtr) 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 GdipDisposeImage Lib "gdiplus" (ByVal Image As LongPtr) As LongPtr
    Private Declare PtrSafe Function GdipCreateHBITMAPFromBitmap Lib "gdiplus" (ByVal BITMAP As LongPtr, hbmReturn As LongPtr, ByVal background As Long) 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 hBitmap As LongPtr, hCopy As LongPtr

#Else

    Private Declare Function WindowFromPoint Lib "user32" (ByVal xPoint As Long, ByVal yPoint As Long) As Long
    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 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 GetModuleHandle Lib "kernel32" Alias "GetModuleHandleA" (ByVal lpModuleName As String) As Long
    Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal Length As Long)
    Private Declare Function SetLayeredWindowAttributes Lib "user32" (ByVal hwnd As Long, ByVal crey As Long, ByVal bAlpha As Byte, ByVal dwFlags As Long) As Long
    Private Declare Function GetCursorPos Lib "user32" (lpPoint As POINTAPI) 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 GetWindowRect Lib "user32" (ByVal hwnd As Long, lpRect As RECT) As Long
    Private Declare Function ScreenToClient Lib "user32" (ByVal hwnd As Long, lpPoint As POINTAPI) As Long
    Private Declare Function GetAsyncKeyState Lib "user32" (ByVal vKey As Long) As Integer
    Private Declare Function GetDeviceCaps Lib "gdi32" (ByVal hdc As Long, ByVal nIndex 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 IUnknown_GetWindow Lib "shlwapi" Alias "#172" (ByVal pIUnk As IUnknown, ByVal hwnd As Long) As Long
    Private Declare Function IsChild Lib "user32" (ByVal hWndParent As Long, ByVal hwnd As Long) As Long
    Private Declare Function SendMessage Lib "user32" Alias "SendMessageA" (ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, lParam As Any) As Long
    Private Declare Function GetSystemMetrics Lib "user32" (ByVal nIndex As Long) As Long
    Private Declare Function DestroyIcon Lib "user32" (ByVal hIcon As Long) As Long
    Private Declare Function CreateSolidBrush Lib "gdi32" (ByVal crColor As Long) As Long
    Private Declare Function SelectObject Lib "gdi32" (ByVal hdc As Long, ByVal hObject As Long) As Long
    Private Declare Function DeleteObject Lib "gdi32" (ByVal hObject As Long) As Long
    Private Declare Function SetActiveWindow Lib "user32" (ByVal hwnd As Long) As Long
    Private Declare Function GetNextWindow Lib "user32" Alias "GetWindow" (ByVal hwnd As Long, ByVal wFlag 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 SetWindowRgn Lib "user32" (ByVal hwnd As Long, ByVal hRgn As Long, ByVal bRedraw 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 IntersectRect Lib "user32" (lpDestRect As RECT, lpSrc1Rect As RECT, lpSrc2Rect As RECT) As Long
    Private Declare Function IsRectEmpty Lib "user32" (lpRect As RECT) As Long
    Private Declare Function DwmGetWindowAttribute Lib "Dwmapi.dll" (ByVal hwnd As Long, ByVal dwAttribute As Long, ByRef pvAttribute As Any, ByVal cbAttribute As Long) As Long
    Private Declare Function ExtCreatePen Lib "gdi32" (ByVal dwPenStyle As Long, ByVal dwWidth As Long, lplb As LOGBRUSH, ByVal dwStyleCount As Long, lpStyle As Long) As Long
    Private Declare Function Rectangle Lib "gdi32" (ByVal hdc As Long, ByVal X1 As Long, ByVal Y1 As Long, ByVal X2 As Long, ByVal Y2 As Long) As Long
    Private Declare Function GetStockObject Lib "gdi32" (ByVal nIndex As Long) As Long
    Private Declare Function CreateIconFromResourceEx Lib "User32.dll" (ByRef presbits As Any, ByVal dwResSize As Long, ByVal fIcon As Long, ByVal dwVer As Long, ByVal cxDesired As Long, ByVal cyDesired As Long, ByVal Flags As Long) As Long
    Private Declare Function SetCursorAPI Lib "user32" Alias "SetCursor" (ByVal hCursor As Long) As Long
    Private Declare Function LoadCursor Lib "user32" Alias "LoadCursorA" (ByVal hInstance As Long, ByVal lpCursorName 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 CreatePopupMenu Lib "user32" () As Long
    Private Declare Function DestroyMenu Lib "user32" (ByVal hMenu 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 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 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
    'GDI+
    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 GdipDisposeImage Lib "gdiplus" (ByVal Image As Long) As Long
    Private Declare Function GdipCreateHBITMAPFromBitmap Lib "gdiplus" (ByVal BITMAP As Long, hbmReturn As Long, ByVal background 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 hBitmap As Long, hCopy As Long

#End If


Private bMouseDragging As Boolean
Private oNewClass As cls_DraggableControl
Private oThisInstance As cls_DraggableControl
Private oContainers As Collection
Private lCtrlWidth As Long, lCtrlHeight As Long
Private oUILabel As Control

Private WithEvents Cntrl As MSForms.Image



'___________________________________Class Public Method________________________________________________

Public Sub HookControl(ByVal ThisClassInstance As cls_DraggableControl, ByVal Ctrl As Control, Optional ByVal UILabel As Control)

    Const CHILDID_SELF = &H0&
    
    #If Win64 Then
        Dim hwnd As LongLong
    #Else
        Dim hwnd As Long
    #End If
    
    Dim oForm As Object
    Dim oCtrl As Control
    
    Set oThisInstance = ThisClassInstance
    
    Set oForm = GetUserFormObject(Ctrl)
    
    If oContainers Is Nothing Then
        Set oContainers = New Collection
        IUnknown_GetWindow oForm, VarPtr(hwnd)
        oContainers.Add oForm, CStr(GetNextWindow(hwnd, 5))
        For Each oCtrl In oForm.Controls
            If TypeOf oCtrl Is MSForms.Frame Then
                oContainers.Add oCtrl, CStr(oCtrl.[_GethWnd])
            End If
        Next oCtrl
    End If
    Set Cntrl = Ctrl
    
    If Not UILabel Is Nothing Then
        Set oUILabel = UILabel
    End If

End Sub



'___________________________________Class Private Routines________________________________________________


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

    If Button = 2 Then
        Call CreateAndShowContextMenu
    End If

End Sub

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

    If Button = 1 And bMouseDragging = False Then
        Call DragControl(CreateWindow(Cntrl), Cntrl, X, Y)
    End If

End Sub


#If Win64 Then
    Private Function CreateWindow( _
            ByVal Cntrl As Control _
            ) As LongLong

#Else
        Private Function CreateWindow( _
            ByVal Cntrl As Control _
            ) As Long
#End If

    Const WS_POPUP = &H80000000
    Const SS_BITMAP = &HE
    Const IMAGE_BITMAP = &H0
    Const STM_SETIMAGE = &H172
    Const WS_EX_TOPMOST = &H8
    Const WS_EX_LAYERED = &H80000
    Const WS_EX_NOACTIVATE = &H8000000
    Const GWL_HWNDPARENT = (-8)
    Const GW_CHILD = &H5
    Const LWA_ALPHA = &H2&    

    #If Win64 Then
        Dim hForm As LongPtr, hStatic As LongPtr
    #Else
        Dim hForm As Long, hStatic As Long
    #End If
    
    lCtrlWidth = PTtoPX(Cntrl.Width, False)
    lCtrlHeight = PTtoPX(Cntrl.Height, True)
    hStatic = CreateWindowEx(WS_EX_LAYERED + WS_EX_NOACTIVATE + WS_EX_TOPMOST, _
    "STATIC", "", WS_POPUP Or SS_BITMAP, 0, 0, _
    0, 0, 0, 0&, GetModuleHandle(vbNullString), 0&)
    Call SetLayeredWindowAttributes(hStatic, 0, 100, LWA_ALPHA)
    Call IUnknown_GetWindow(GetUserFormObject(Cntrl), VarPtr(hForm))
    Call SetWindowLong(hStatic, GWL_HWNDPARENT, hForm)
    hBitmap = CreateAndResizeBitmap(Cntrl.Picture, lCtrlWidth, lCtrlHeight)
    Call SendMessage(hStatic, STM_SETIMAGE, IMAGE_BITMAP, ByVal hBitmap)
    Call SetActiveWindow(hForm)
    
    CreateWindow = hStatic

End Function


#If Win64 Then
    Private Sub DragControl( _
        ByVal hStatic As LongLong, _
        ByVal Ctrl As Control, _
        ByVal X As Single, _
        ByVal Y As Single _
        )
        
        Dim hStaticRgn As LongLong, hStaticDC As LongLong, hContainer As LongLong
#Else
    Private Sub DragControl( _
        ByVal hStatic As Long, _
        ByVal Ctrl As Control, _
        ByVal X As Single, _
        ByVal Y As Single _
        )
        
        Dim hStaticRgn As Long, hStaticDC As Long, hContainer As Long
 #End If

    Const SWP_SHOWWINDOW = &H40
    Const SWP_NOACTIVATE = &H10
    Const CHILDID_SELF = &H0&
    
    Dim oContainer As Object, lIndex As Long
    Dim tDstRect As RECT, tPt1 As POINTAPI, tPt2 As POINTAPI
    Dim tFormRect As RECT, tStaticRect As RECT, tCursPos As POINTAPI

    Do While GetAsyncKeyState(vbKeyLButton)
    
        bMouseDragging = True
        
        tFormRect = Get_Form_Extended_Frame_Bounds_Rectangle(GetUserFormObject(Ctrl))
        Call GetWindowRect(hStatic, tStaticRect)
        
        Call IntersectRect(tDstRect, tFormRect, tStaticRect)
        
        With tDstRect
            tPt1.X = .Left
            tPt1.Y = .Top
            tPt2.X = .Right
            tPt2.Y = .Bottom
        End With
        
        Call ScreenToClient(hStatic, tPt1)
        Call ScreenToClient(hStatic, tPt2)
        
        hStaticRgn = CreateRectRgn(tPt1.X, tPt1.Y, tPt2.X, tPt2.Y)
        hStaticDC = GetDC(hStatic)
        Call MakeStaticBorder(hStaticDC)
        Call SetWindowRgn(hStatic, hStaticRgn, True)
        Call ReleaseDC(hStatic, hStaticDC)
        ' Call DeleteObject(hStaticRgn)  ' !!

        Call GetCursorPos(tCursPos)
        Call SetWindowPos( _
            hStatic, 0, tCursPos.X - PTtoPX(X, False), tCursPos.Y - PTtoPX(Y, True), _
            lCtrlWidth, lCtrlHeight, SWP_NOACTIVATE + SWP_SHOWWINDOW)

        #If Win64 Then
            Dim lPT As LongLong
            Call CopyMemory(lPT, tCursPos, LenB(lPT))
            hContainer = WindowFromPoint(lPT)
        #Else
            hContainer = WindowFromPoint(tCursPos.X, tCursPos.Y)
        #End If
                
        For lIndex = 1 To oContainers.Count
            On Error Resume Next
                Set oContainer = oContainers(CStr(hContainer))
            On Error GoTo 0
            If Not oContainer Is Nothing Then
                Exit For
            End If
        Next lIndex
    
        If IsRectEmpty(tDstRect) Then
                SetCursor = No_Cursor
                If Not oUILabel Is Nothing Then
                    oUILabel.Caption = "Outside UserForm."
                End If
        Else
            If GetAsyncKeyState(VBA.vbKeyControl) Then
                SetCursor = Copy_Cursor
                If Not oUILabel Is Nothing Then
                    oUILabel.Caption = "Copying Control."
                End If
            Else
                SetCursor = Drag_Cursor
                If Not oUILabel Is Nothing Then
                    oUILabel.Caption = "Moving Control."
                End If
            End If
        End If

        DoEvents
        
    Loop
    
    bMouseDragging = False
    
    Call DeleteObject(hCopy)
    Call DeleteObject(hBitmap)

    If IsRectEmpty(tDstRect) = 0 Then
        Call RelocateControl(Ctrl, hStatic, oContainer)
        Call DestroyWindow(hStatic)
    End If

End Sub


#If Win64 Then
    Private Sub RelocateControl( _
        ByVal Ctrl As Control, _
        ByVal StaticHwnd As LongLong, _
        ByVal Container As Object _
        )

        Dim hContainer As LongLong, hForm As LongLong
#Else

    Private Sub RelocateControl( _
        ByVal Ctrl As Control, _
        ByVal StaticHwnd As Long, _
        ByVal Container As Object _
       )
        
        Dim hContainer As Long, hForm As Long
#End If

    Const WM_SETREDRAW = &HB
    Const SM_CYCAPTION = 4
    Const SM_CYDLGFRAME = 8
    Const SM_CYBORDER = 6
    Const SM_CXEDGE = 45
    Const SM_CYEDGE = 46
    Const SM_CYFRAME = 33

    Dim oNewControl   As Control
    Dim lFrameHOffset As Long, lFrameVOffset As Long
    Dim tStaticRect As RECT, tCursPos As POINTAPI

    On Error GoTo xit
    
    Call IUnknown_GetWindow(Container, VarPtr(hContainer))
    Call IUnknown_GetWindow(GetUserFormObject(Ctrl), VarPtr(hForm))
    
    Call SendMessage(hContainer, ByVal WM_SETREDRAW, ByVal 0, 0)
    
    Select Case GetAsyncKeyState(VBA.vbKeyControl)
        Case 0  'moving.
            If Cntrl.Parent Is Container Then
                Set oNewControl = Cntrl
                If Not oUILabel Is Nothing Then
                    oUILabel.Caption = Ctrl.Name & " moved."
                End If
            Else
                Cntrl.Visible = False
                Set oNewControl = AddNewControl(Container)
                oNewControl.Name = Cntrl.Name
                If Not oUILabel Is Nothing Then
                   oUILabel.Caption = Ctrl.Name & " moved."
                End If
            End If
        Case Else 'copying.
            Set oNewControl = AddNewControl(Container)
            If Not oUILabel Is Nothing Then
                oUILabel.Caption = Ctrl.Name & " copied."
            End If
    End Select
    
    lFrameHOffset = GetSystemMetrics(SM_CXEDGE)
    lFrameVOffset = GetSystemMetrics(SM_CYEDGE) + _
    GetSystemMetrics(SM_CYFRAME) + GetSystemMetrics(SM_CYBORDER)
    Call GetWindowRect(StaticHwnd, tStaticRect)
    Call GetCursorPos(tCursPos)
    tCursPos.X = tStaticRect.Left: tCursPos.Y = tStaticRect.Top
    Call ScreenToClient(hContainer, tCursPos)
    
    With oNewControl
        .Left = PXtoPT(tCursPos.X - IIf(IsChild(hForm, hContainer), lFrameHOffset, 0), False)
        .Top = PXtoPT(tCursPos.Y - IIf(IsChild(hForm, hContainer), lFrameVOffset, 0), True)
        .Width = Cntrl.Width
        .Height = Cntrl.Height
        .PictureSizeMode = fmPictureSizeModeStretch
        .Picture = Cntrl.Picture
    End With
    
xit:
    Call SendMessage(hContainer, ByVal WM_SETREDRAW, ByVal 1, 0)
    Container.Repaint

End Sub


Private Function AddNewControl(ByVal Container As Object, Optional ByVal UILabel As Control) As Control

        Dim oNewCtrl As Control

        Set AddNewControl = Container.Controls.Add("Forms.Image.1")
        Set oNewClass = New cls_DraggableControl
        oNewClass.HookControl oNewClass, AddNewControl, oUILabel

End Function


#If Win64 Then
    Private Sub MakeStaticBorder( _
        ByVal hdc As LongLong _
    )
        Dim hPrevBrush As LongLong, hBrush As LongLong, hPrevPen As LongLong, hPen As LongLong
#Else
    Private Sub MakeStaticBorder( _
        ByVal hdc As Long _
    )
       Dim hPrevBrush As Long, hBrush As Long, hPrevPen As Long, hPen As Long
#End If

    Const DASH_LEN = 5
    Const SPACE_LEN = 10
    Const PEN_WIDTH = 4
    Const HOLLOW_BRUSH = 5
    Const PEN_COLOR = vbRed
    Const BS_SOLID = 0
    Const PS_GEOMETRIC = &H10000
    Const PS_USERSTYLE = 7&

    Dim LOGBRUSH As LOGBRUSH
    Dim lStyleArray(1) As Long
  
    With LOGBRUSH
        .lbStyle = BS_SOLID
        .lbColor = PEN_COLOR
    End With
    
    lStyleArray(0) = DASH_LEN
    lStyleArray(1) = SPACE_LEN
    hPen = ExtCreatePen(PS_GEOMETRIC Or PS_USERSTYLE, PEN_WIDTH, LOGBRUSH, 2, lStyleArray(0))
    hBrush = GetStockObject(HOLLOW_BRUSH)
    hPrevBrush = SelectObject(hdc, hBrush)
    hPrevPen = SelectObject(hdc, hPen)
    Call Rectangle(hdc, 0, 0, lCtrlWidth, lCtrlHeight)
    Call SelectObject(hdc, hPrevPen)
    Call SelectObject(hdc, hPrevBrush)
    Call DeleteObject(hPen)
    Call DeleteObject(hBrush)

End Sub


Private Sub CreateAndShowContextMenu()

    Const MF_STRING = &H0&
    Const MF_BYPOSITION = &H400
    Const TPM_RETURNCMD = &H100&
    
    #If Win64 Then
        Dim hMenu As LongLong, hwnd As LongLong
    #Else
        Dim hMenu As Long, hwnd As Long
    #End If
    
    Dim lShowPopupMenu As Long
    Dim oFaceIdPic As StdPicture, tCursPos As POINTAPI
    
    hMenu = CreatePopupMenu()
    
    If hMenu Then
        Call AppendMenu(hMenu, MF_STRING, 1, "&Remove")
        Set oFaceIdPic = PicFromFaceID(478)
        If Not oFaceIdPic Is Nothing Then
            Call SetMenuItemBitmaps(hMenu, 0, MF_BYPOSITION, oFaceIdPic, oFaceIdPic)
        End If
        Call IUnknown_GetWindow(GetUserFormObject(Cntrl), VarPtr(hwnd))
        Call GetCursorPos(tCursPos)
        lShowPopupMenu = TrackPopupMenuEx(hMenu, TPM_RETURNCMD, tCursPos.X, tCursPos.Y, hwnd, ByVal 0&)
        If lShowPopupMenu = 1 Then Cntrl.Visible = False
        Call DestroyMenu(hMenu)
        If Not oUILabel Is Nothing Then
            oUILabel.Caption = Cntrl.Name & " Deleted."
        End If
    End If

End Sub


Private Function ScreenDPI(ByVal bVert As Boolean) As Long

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

    Const LOGPIXELSX As Long = 88
    Const LOGPIXELSY As Long = 90
    Static lDPI(1) As Long

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

End Function


Private Function PTtoPX(ByVal Points As Single, ByVal bVert As Boolean) As Long
    Const POINTSPERINCH As Long = 72
    PTtoPX = Points * ScreenDPI(bVert) / POINTSPERINCH
End Function


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


Private Function GetUserFormObject(ByVal Ctrl As Control) As Object

    Dim oTemp As Object
    
    Set oTemp = Ctrl.Parent
    Do While TypeOf oTemp Is MSForms.Control
        Set oTemp = oTemp.Parent
        DoEvents
    Loop
    Set GetUserFormObject = oTemp
 
End Function


Private Function PicFromFaceID(ByVal FaceID As Long) As IPicture

    #If Win64 Then
        Dim hPtr As LongLong
    #Else
        Dim hPtr As Long
    #End If
    
    Const S_OK = &H0
    Const CF_BITMAP = 2
    Const IMAGE_BITMAP = 0
    Const LR_COPYRETURNORG = &H4
    Const PICTYPE_BITMAP = 1

    Dim iPic As IPicture
    Dim IID_IDispatch As GUID, uPicinfo As uPicDesc

    On Error GoTo errHandler
            
    Application.CommandBars.FindControl(id:=FaceID).CopyFace
    
    Call OpenClipboard(0)
    hPtr = GetClipboardData(CF_BITMAP)
  
    If hPtr Then
        hPtr = CopyImage(hPtr, IMAGE_BITMAP, 0, 0, LR_COPYRETURNORG)
        Call EmptyClipboard
        Call CloseClipboard
        
        With IID_IDispatch
            .Data1 = &H20400
            .Data4(0) = &HC0
            .Data4(7) = &H46
        End With
        With uPicinfo
            .Size = Len(uPicinfo)
            .Type = PICTYPE_BITMAP
            .hPic = hPtr
            .hPal = 0
        End With
        
        If OleCreatePictureIndirect(uPicinfo, IID_IDispatch, True, iPic) = S_OK Then
            Set PicFromFaceID = iPic
        End If
    End If
    
    Exit Function
    
errHandler:
    
    Call EmptyClipboard
    Call CloseClipboard
    
End Function


Private Function Get_Form_Extended_Frame_Bounds_Rectangle(ByVal Form As Object) As RECT

    Const SM_CYCAPTION = 4
    Const SM_CYDLGFRAME = 8
    Const SM_CYBORDER = 6
    Const SM_CXEDGE = 45
    Const SM_CYEDGE = 46
    Const SM_CYFRAME = 33
    Const DWMWA_EXTENDED_FRAME_BOUNDS = 9

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

    Dim tRect As RECT, tFormRect As RECT

    Call IUnknown_GetWindow(Form, VarPtr(hForm))
    Call DwmGetWindowAttribute(hForm, DWMWA_EXTENDED_FRAME_BOUNDS, tFormRect, LenB(tFormRect))
    Call GetWindowRect(hForm, tRect)
    
    If tFormRect.Right = 0 Then
        With tRect
            .Top = .Top + GetSystemMetrics(SM_CYCAPTION) + GetSystemMetrics(SM_CYDLGFRAME)
        End With
        tFormRect = tRect
    Else
        With tFormRect
            .Top = .Top + GetSystemMetrics(SM_CYCAPTION) + GetSystemMetrics(SM_CYDLGFRAME) _
            + GetSystemMetrics(SM_CYFRAME) + GetSystemMetrics(SM_CYBORDER)
        End With
    End If
    
    Get_Form_Extended_Frame_Bounds_Rectangle = tFormRect

End Function


#If Win64 Then
    Private Function BuildDrag_Cursor() As LongLong
#Else
    Private Function BuildDrag_Cursor() As Long
#End If

    ReDim longs(0 To 186) As Long

    longs(0) = 0: longs(1) = 40: longs(2) = 32: longs(3) = 64: longs(4) = 262145: longs(5) = 0: longs(6) = 640: longs(7) = 0: longs(8) = 0: longs(9) = 16: longs(10) = 0: longs(11) = 0: longs(12) = 8388608: longs(13) = 32768: longs(14) = 8421376: longs(15) = 128: longs(16) = 8388736: longs(17) = 32896: longs(18) = 12632256: longs(19) = 8421504: longs(20) = 16711680: longs(21) = 65280: longs(22) = 16776960: longs(23) = 255: longs(24) = 16711935: longs(25) = 65535: longs(26) = 16777215: longs(27) = 0: longs(28) = 0: longs(29) = 0
    longs(30) = 0: longs(31) = 0: longs(32) = 0: longs(33) = 0: longs(34) = 0: longs(35) = 0: longs(36) = 151587072: longs(37) = 151587081: longs(38) = 9: longs(39) = 0: longs(40) = -1869611008: longs(41) = -1869574000: longs(42) = 144: longs(43) = 0: longs(44) = 2304: longs(45) = 0: longs(46) = 9: longs(47) = 0: longs(48) = 9437184: longs(49) = 0: longs(50) = 144: longs(51) = 0: longs(52) = 2304: longs(53) = 0: longs(54) = 9: longs(55) = 0: longs(56) = 9437184: longs(57) = 0: longs(58) = 144: longs(59) = 0
    longs(60) = 2304: longs(61) = 0: longs(62) = 9: longs(63) = 0: longs(64) = 9437184: longs(65) = 0: longs(66) = 144: longs(67) = 0: longs(68) = 2304: longs(69) = 0: longs(70) = 9: longs(71) = 0: longs(72) = -1869611008: longs(73) = -1869574000: longs(74) = 144: longs(75) = 0: longs(76) = 151587072: longs(77) = 151587081: longs(78) = 9: longs(79) = 150994944: longs(80) = 144: longs(81) = 0: longs(82) = 0: longs(83) = -1728053248: longs(84) = 153: longs(85) = 0: longs(86) = 0: longs(87) = -1728053248: longs(88) = 153: longs(89) = 0
    longs(90) = 0: longs(91) = -1727463424: longs(92) = 144: longs(93) = 0: longs(94) = 0: longs(95) = -1727463280: longs(96) = 144: longs(97) = 0: longs(98) = 0: longs(99) = -1718026087: longs(100) = 0: longs(101) = 0: longs(102) = 0: longs(103) = -1717989223: longs(104) = 0: longs(105) = 0: longs(106) = 0: longs(107) = -1868981863: longs(108) = 0: longs(109) = 0: longs(110) = 0: longs(111) = -1717986919: longs(112) = 37017: longs(113) = 0: longs(114) = 0: longs(115) = -1717986919: longs(116) = 153: longs(117) = 0: longs(118) = 0: longs(119) = -1717986919
    longs(120) = 144: longs(121) = 0: longs(122) = 0: longs(123) = -1717986919: longs(124) = 0: longs(125) = 0: longs(126) = 0: longs(127) = -1868981863: longs(128) = 0: longs(129) = 0: longs(130) = 0: longs(131) = 10066329: longs(132) = 0: longs(133) = 0: longs(134) = 0: longs(135) = 9476505: longs(136) = 0: longs(137) = 0: longs(138) = 0: longs(139) = 39321: longs(140) = 0: longs(141) = 0: longs(142) = 0: longs(143) = 37017: longs(144) = 0: longs(145) = 0: longs(146) = 0: longs(147) = 153: longs(148) = 0: longs(149) = 0
    longs(150) = 0: longs(151) = 144: longs(152) = 0: longs(153) = 0: longs(154) = 0: longs(155) = -1: longs(156) = -1: longs(157) = -1079317761: longs(158) = 2136339967: longs(159) = -1073745921: longs(160) = 2147481599: longs(161) = -1073745921: longs(162) = 2147481599: longs(163) = -1073745921: longs(164) = 2147481599: longs(165) = -1073745921: longs(166) = 2136339967: longs(167) = -1079317761: longs(168) = -32770: longs(169) = -49156: longs(170) = -49156: longs(171) = -32776: longs(172) = -32904: longs(173) = -208: longs(174) = -240: longs(175) = -255: longs(176) = -57600: longs(177) = -49408: longs(178) = -33024: longs(179) = -256
    longs(180) = -255: longs(181) = -253: longs(182) = -249: longs(183) = -241: longs(184) = -225: longs(185) = -193: longs(186) = -129:

    BuildDrag_Cursor = CreateIconFromResourceEx(longs(0), UBound(longs) * 4 + 4, 0&, &H30000, 0, 0, 0&)

End Function


#If Win64 Then
    Private Function BuildCopy_Cursor() As LongLong
#Else
    Private Function BuildCopy_Cursor() As Long
#End If

    ReDim longs(0 To 186) As Long
    
    longs(1) = 40: longs(2) = 32: longs(3) = 64: longs(4) = 262145: longs(6) = 640: longs(9) = 16: longs(10) = 16: longs(12) = 8388608: longs(13) = 32768: longs(14) = 8421376: longs(15) = 128: longs(16) = 8388736: longs(17) = 32896: longs(18) = 8421504: longs(19) = 12632256: longs(20) = 16711680: longs(21) = 65280: longs(22) = 16776960: longs(23) = 255: longs(24) = 16711935: longs(25) = 65535: longs(26) = 16777215:
    longs(36) = 151587072: longs(37) = 151587081: longs(38) = 9: longs(40) = -1869611008: longs(41) = -1869574000: longs(42) = 144: longs(44) = 2304: longs(46) = 9: longs(48) = 9437184: longs(50) = 144: longs(52) = 2304: longs(54) = 9: longs(56) = 9437184: longs(58) = 144:
    longs(60) = 2304: longs(62) = 9: longs(64) = 9437184: longs(66) = 144: longs(68) = 2304: longs(70) = 9: longs(72) = -1869611008: longs(73) = -1869574000: longs(74) = 144: longs(76) = 151587072: longs(77) = 151587081: longs(78) = 9: longs(79) = 150994944: longs(80) = 144: longs(83) = -1728053248: longs(84) = 153: longs(87) = -1728053248: longs(88) = 153: longs(89) = 37017
    longs(91) = -1727463424: longs(92) = 144: longs(93) = 37017: longs(95) = -1727463280: longs(96) = 144: longs(97) = 37017: longs(99) = -1718026087: longs(100) = -1861681152: longs(101) = 10064281: longs(103) = -1717989223: longs(104) = -1727463424: longs(105) = 10066329: longs(107) = -1868981863: longs(108) = -1727463424: longs(109) = 10066321: longs(111) = -1717986919: longs(112) = 37017: longs(113) = 37017: longs(115) = -1717986919: longs(116) = 153: longs(117) = 37017: longs(119) = -1717986919
    longs(120) = 144: longs(121) = 37017: longs(123) = -1717986919: longs(127) = -1868981863: longs(131) = 10066329: longs(135) = 9476505: longs(139) = 39321: longs(143) = 37017: longs(147) = 153:
    longs(151) = 144: longs(155) = -1: longs(156) = -1: longs(157) = -1079317761: longs(158) = 2136339967: longs(159) = -1073745921: longs(160) = 2147481599: longs(161) = -1073745921: longs(162) = 2147481599: longs(163) = -1073745921: longs(164) = 2147481599: longs(165) = -1073745921: longs(166) = 2136339967: longs(167) = -1079317761: longs(168) = -32770: longs(169) = -49156: longs(170) = -14729220: longs(171) = -14712840: longs(172) = -14712968: longs(173) = -16517072: longs(174) = -16517104: longs(175) = -16517119: longs(176) = -14737664: longs(177) = -14729472: longs(178) = -14713088: longs(179) = -256
    longs(180) = -255: longs(181) = -253: longs(182) = -249: longs(183) = -241: longs(184) = -225: longs(185) = -193: longs(186) = -129:
    
    BuildCopy_Cursor = CreateIconFromResourceEx(longs(0), UBound(longs) * 4 + 4, 0&, &H30000, 0, 0, 0&)

End Function


Private Property Let SetCursor(Cur As eCursor)

    Const IDC_NO = 32648&
    
    #If Win64 Then
        Dim hCursor As LongLong
    #Else
        Dim hCursor As Long
    #End If
    
    Select Case Cur
        Case Drag_Cursor
            hCursor = BuildDrag_Cursor
        Case Copy_Cursor
            hCursor = BuildCopy_Cursor
        Case No_Cursor
            hCursor = LoadCursor(0, IDC_NO)
    End Select
    
    Call SetCursorAPI(hCursor)
    Call DestroyIcon(hCursor)

End Property

#If Win64 Then
    Private Function CreateAndResizeBitmap( _
    ByVal Image As StdPicture, _
    ByVal Width As Long, _
    ByVal Height As Long _
    ) As LongLong

    Dim lGDIP As LongLong, lBitmap As LongLong, lThumb As LongLong, hBitmap As LongLong
    
#Else
    Private Function CreateAndResizeBitmap( _
    ByVal Image As StdPicture, _
    ByVal Width As Long, _
    ByVal Height As Long _
    ) As Long

    Dim lGDIP As Long, lBitmap As Long, lThumb As Long, hBitmap As Long
    
  #End If
 
    Const S_OK = 0&
    
    Dim CreatheThumbnail As StdPicture
    Dim tSI As GdiplusStartupInput
    Dim lRes As Long
    
    tSI.GdiplusVersion = 1
    lRes = GdiplusStartup(lGDIP, tSI)

   If lRes = S_OK Then
      lRes = GdipCreateBitmapFromHBITMAP(Image.handle, 0, lBitmap)
      If lRes = S_OK Then
         lRes = GdipGetImageThumbnail(lBitmap, Width, Height, lThumb, 0, 0)
         If lRes = S_OK Then
            lRes = GdipCreateHBITMAPFromBitmap(lThumb, hBitmap, 0)
             CreateAndResizeBitmap = hBitmap
            GdipDisposeImage lThumb
         End If
         GdipDisposeImage lBitmap
      End If
      GdiplusShutdown lGDIP
   End If

   If lRes Then Err.Raise 5, , "Cannot load file."

End Function




2- Code Usage example (Standard Module )
VBA Code:
Option Explicit

Sub ShowUserForm()

    Dim oCtrl As MSForms.Control
    Dim oClass As cls_DraggableControl
    Dim oUserForm As Object
    
    Set oUserForm = UserForm1
    
    For Each oCtrl In oUserForm.Controls
        If TypeOf oCtrl Is MSForms.Image Then
            Set oClass = New cls_DraggableControl
            oClass.HookControl ThisClassInstance:=oClass, Ctrl:=oCtrl, UILabel:=oUserForm.Label1
        End If
    Next

    oUserForm.Show
    
End Sub
 

Excel Facts

VLOOKUP to Left?
Use =VLOOKUP(A2,CHOOSE({1,2},$Z$1:$Z$99,$Y$1:$Y$99),2,False) to lookup Y values to left of Z values.

Forum statistics

Threads
1,224,816
Messages
6,181,139
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