Introduction
The "traditional" way of moving a borderless VB form is to move the form when the mouse button is clicked down and the mouse moves. However, this flickers and is not as intuitive as it could be because "normal" windows only move when you drag the caption. The solution is to have your form borderless and have the caption bar appear when the mouse moves to the top part of the form and disappear again when the mouse moves of the caption bar...thus:
Option Explicit
Public Enum enSetWindowPos
SWP_FRAMECHANGED = &H20
SWP_HIDEWINDOW = &H80
SWP_NOACTIVATE = &H10
SWP_NOCOPYBITS = &H100
SWP_NOMOVE = &H2
SWP_NOOWNERZORDER = &H200
SWP_NOREDRAW = &H8
SWP_NOSIZE = &H1
SWP_NOZORDER = &H4
SWP_SHOWWINDOW = &H40
End Enum
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
Public Enum enGetWindowLong
GWL_EXSTYLE = (-20)
GWL_HINSTANCE = (-6)
GWL_HWNDPARENT = (-8)
GWL_ID = (-12)
GWL_STYLE = (-16)
GWL_USERDATA = (-21)
GWL_WNDPROC = (-4)
End Enum
Private Declare Function GetWindowLong Lib "user32" _
Alias "GetWindowLongA" (ByVal hwnd As Long, _
ByVal nIndex 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
Public Enum enWindowStyles
WS_BORDER = &H800000
WS_CAPTION = &HC00000
WS_CHILD = &H40000000
WS_CLIPCHILDREN = &H2000000
WS_CLIPSIBLINGS = &H4000000
WS_DISABLED = &H8000000
WS_DLGFRAME = &H400000
WS_EX_ACCEPTFILES = &H10&
WS_EX_DLGMODALFRAME = &H1&
WS_EX_NOPARENTNOTIFY = &H4&
WS_EX_TOPMOST = &H8&
WS_EX_TRANSPARENT = &H20&
WS_EX_TOOLWINDOW = &H80&
WS_GROUP = &H20000
WS_HSCROLL = &H100000
WS_MAXIMIZE = &H1000000
WS_MAXIMIZEBOX = &H10000
WS_MINIMIZE = &H20000000
WS_MINIMIZEBOX = &H20000
WS_OVERLAPPED = &H0&
WS_POPUP = &H80000000
WS_SYSMENU = &H80000
WS_TABSTOP = &H10000
WS_THICKFRAME = &H40000
WS_VISIBLE = &H10000000
WS_VSCROLL = &H200000
WS_EX_MDICHILD = &H40
WS_EX_WINDOWEDGE = &H100
WS_EX_CLIENTEDGE = &H200
WS_EX_CONTEXTHELP = &H400
WS_EX_RIGHT = &H1000
WS_EX_LEFT = &H0
WS_EX_RTLREADING = &H2000
WS_EX_LTRREADING = &H0
WS_EX_LEFTSCROLLBAR = &H4000
WS_EX_RIGHTSCROLLBAR = &H0
WS_EX_CONTROLPARENT = &H10000
WS_EX_STATICEDGE = &H20000
WS_EX_APPWINDOW = &H40000
WS_EX_OVERLAPPEDWINDOW = (WS_EX_WINDOWEDGE Or WS_EX_CLIENTEDGE)
WS_EX_PALETTEWINDOW = (WS_EX_WINDOWEDGE Or _
WS_EX_TOOLWINDOW Or WS_EX_TOPMOST)
End Enum
Dim oldVal As FormBorderStyleConstants
Dim lCaptionHeight As Long
Public Enum SystemMetricsIndexes
SM_CXSCREEN = 0
SM_CYSCREEN = 1
SM_CXVSCROLL = 2
SM_CYHSCROLL = 3
SM_CYCAPTION = 4
SM_CXBORDER = 5
SM_CYBORDER = 6
SM_CXDLGFRAME = 7
SM_CYDLGFRAME = 8
SM_CYVTHUMB = 9
SM_CXHTHUMB = 10
SM_CXICON = 11
SM_CYICON = 12
SM_CXCURSOR = 13
SM_CYCURSOR = 14
SM_CYMENU = 15
SM_CXFULLSCREEN = 16
SM_CYFULLSCREEN = 17
SM_CYKANJIWINDOW = 18
SM_MOUSEPRESENT = 19
SM_CYVSCROLL = 20
SM_CXHSCROLL = 21
SM_DEBUG = 22
SM_SWAPBUTTON = 23
SM_RESERVED1 = 24
SM_RESERVED2 = 25
SM_RESERVED3 = 26
SM_RESERVED4 = 27
SM_CXMIN = 28
SM_CYMIN = 29
SM_CXSIZE = 30
SM_CYSIZE = 31
SM_CXFRAME = 32
SM_CYFRAME = 33
SM_CXMINTRACK = 34
SM_CYMINTRACK = 35
SM_CXDOUBLECLK = 36
SM_CYDOUBLECLK = 37
SM_CXICONSPACING = 38
SM_CYICONSPACING = 39
SM_MENUDROPALIGNMENT = 40
SM_PENWINDOWS = 41
SM_DBCSENABLED = 42
SM_CMOUSEBUTTONS = 43
SM_SECURE = 44
SM_CXEDGE = 45
SM_CYEDGE = 46
SM_CXMINSPACING = 47
SM_CYMINSPACING = 48
SM_CXSMICON = 49
SM_CYSMICON = 50
SM_CYSMCAPTION = 51
SM_CXSMSIZE = 52
SM_CYSMSIZE = 53
SM_CXMENUSIZE = 54
SM_CYMENUSIZE = 55
SM_ARRANGE = 56
SM_CXMINIMIZED = 57
SM_CYMINIMIZED = 58
SM_CXMAXTRACK = 59
SM_CYMAXTRACK = 60
SM_CXMAXIMIZED = 61
SM_CYMAXIMIZED = 62
SM_NETWORK = 63
SM_CLEANBOOT = 67
SM_CXDRAG = 68
SM_CYDRAG = 69
SM_SHOWSOUNDS = 70
SM_CXMENUCHECK = 71
SM_CYMENUCHECK = 72
SM_SLOWMACHINE = 73
SM_MIDEASTENABLED = 74
SM_MOUSEWHEELPRESENT = 75
SM_XVIRTUALSCREEN = 76
SM_YVIRTUALSCREEN = 77
SM_CXVIRTUALSCREEN = 78
SM_CYVIRTUALSCREEN = 79
SM_CMONITORS = 80
SM_SAMEDISPLAYFORMAT = 81
End Enum
Private Declare Function GetSystemMetrics Lib _
"user32" (ByVal nIndex As SystemMetricsIndexes) As Long
Public Property Get RuntimeFormBorderStyle() As FormBorderStyleConstants
RuntimeFormBorderStyle = oldVal
End Property
Public Property Let RuntimeFormBorderStyle(ByVal newVal_
As FormBorderStyleConstants)
If newVal <> oldVal Then
Select Case newVal
Case vbBSNone
WindowStyle(WS_BORDER) = False
WindowStyle(WS_CAPTION) = False
WindowStyle(WS_DLGFRAME) = False
WindowStyle(WS_EX_DLGMODALFRAME) = False
WindowStyle(WS_EX_TOOLWINDOW) = False
WindowStyle(WS_MAXIMIZEBOX) = Me.MaxButton
WindowStyle(WS_MINIMIZEBOX) = Me.MinButton
WindowStyle(WS_SYSMENU) = Me.ControlBox
WindowStyle(WS_THICKFRAME) = False
WindowStyle(WS_VSCROLL) = False
WindowStyle(WS_EX_WINDOWEDGE) = False
WindowStyle(WS_EX_CLIENTEDGE) = False
WindowStyle(WS_EX_CONTROLPARENT) = False
WindowStyle(WS_EX_STATICEDGE) = False
WindowStyle(WS_EX_APPWINDOW) = False
Case vbFixedDialog
WindowStyle(WS_BORDER) = True
WindowStyle(WS_CAPTION) = True
WindowStyle(WS_DLGFRAME) = True
WindowStyle(WS_EX_DLGMODALFRAME) = True
WindowStyle(WS_EX_TOOLWINDOW) = False
WindowStyle(WS_MAXIMIZEBOX) = Me.MaxButton
WindowStyle(WS_MINIMIZEBOX) = Me.MinButton
WindowStyle(WS_SYSMENU) = Me.ControlBox
WindowStyle(WS_THICKFRAME) = False
WindowStyle(WS_EX_WINDOWEDGE) = True
WindowStyle(WS_EX_CLIENTEDGE) = False
WindowStyle(WS_EX_STATICEDGE) = False
WindowStyle(WS_EX_APPWINDOW) = Me.ShowInTaskbar
Case vbFixedSingle
WindowStyle(WS_BORDER) = True
WindowStyle(WS_CAPTION) = True
WindowStyle(WS_DLGFRAME) = True
WindowStyle(WS_EX_DLGMODALFRAME) = False
WindowStyle(WS_EX_TOOLWINDOW) = False
WindowStyle(WS_MAXIMIZEBOX) = Me.MaxButton
WindowStyle(WS_MINIMIZEBOX) = Me.MinButton
WindowStyle(WS_SYSMENU) = Me.ControlBox
WindowStyle(WS_THICKFRAME) = True
WindowStyle(WS_EX_WINDOWEDGE) = True
WindowStyle(WS_EX_CLIENTEDGE) = False
WindowStyle(WS_EX_STATICEDGE) = False
WindowStyle(WS_EX_APPWINDOW) = Me.ShowInTaskbar
Case vbFixedToolWindow
WindowStyle(WS_BORDER) = True
WindowStyle(WS_CAPTION) = True
WindowStyle(WS_DLGFRAME) = True
WindowStyle(WS_EX_DLGMODALFRAME) = False
WindowStyle(WS_EX_TOOLWINDOW) = True
WindowStyle(WS_MAXIMIZEBOX) = Me.MaxButton
WindowStyle(WS_MINIMIZEBOX) = Me.MinButton
WindowStyle(WS_SYSMENU) = Me.ControlBox
WindowStyle(WS_THICKFRAME) = False
WindowStyle(WS_EX_WINDOWEDGE) = True
WindowStyle(WS_EX_CLIENTEDGE) = False
WindowStyle(WS_EX_STATICEDGE) = False
WindowStyle(WS_EX_APPWINDOW) = Me.ShowInTaskbar
Case vbSizable
WindowStyle(WS_BORDER) = True
WindowStyle(WS_CAPTION) = True
WindowStyle(WS_DLGFRAME) = True
WindowStyle(WS_EX_DLGMODALFRAME) = False
WindowStyle(WS_EX_TOOLWINDOW) = False
WindowStyle(WS_MAXIMIZEBOX) = Me.MaxButton
WindowStyle(WS_MINIMIZEBOX) = Me.MinButton
WindowStyle(WS_SYSMENU) = Me.ControlBox
WindowStyle(WS_THICKFRAME) = True
WindowStyle(WS_EX_WINDOWEDGE) = True
WindowStyle(WS_EX_CLIENTEDGE) = False
WindowStyle(WS_EX_APPWINDOW) = Me.ShowInTaskbar
Case vbSizableToolWindow
WindowStyle(WS_BORDER) = True
WindowStyle(WS_CAPTION) = True
WindowStyle(WS_DLGFRAME) = True
WindowStyle(WS_EX_DLGMODALFRAME) = False
WindowStyle(WS_EX_TOOLWINDOW) = True
WindowStyle(WS_MAXIMIZEBOX) = Me.MaxButton
WindowStyle(WS_MINIMIZEBOX) = Me.MinButton
WindowStyle(WS_SYSMENU) = Me.ControlBox
WindowStyle(WS_THICKFRAME) = False
WindowStyle(WS_EX_WINDOWEDGE) = True
WindowStyle(WS_EX_CLIENTEDGE) = False
WindowStyle(WS_EX_STATICEDGE) = False
WindowStyle(WS_EX_APPWINDOW) = Me.ShowInTaskbar
End Select
Call SetWindowPos(Me.hwnd, 0, 0, 0, 0, 0, _
SWP_NOMOVE + SWP_NOSIZE + SWP_FRAMECHANGED)
Me.Refresh
oldVal = newVal
End If
End Property
Public Property Let WindowStyle(ByVal Index _
As enWindowStyles, ByVal newVal As Boolean)
Dim gwIndex As enGetWindowLong
Dim lCurStyle As Long
If Index = WS_EX_ACCEPTFILES Or Index = WS_EX_APPWINDOW _
Or Index = WS_EX_CLIENTEDGE Or Index = WS_EX_CONTEXTHELP _
Or Index = WS_EX_CONTROLPARENT Or Index = WS_EX_DLGMODALFRAME _
Or Index = WS_EX_LEFT Or Index = WS_EX_LEFTSCROLLBAR _
Or Index = WS_EX_LTRREADING Or Index = WS_EX_MDICHILD _
Or Index = WS_EX_NOPARENTNOTIFY Or Index = WS_EX_OVERLAPPEDWINDOW _
Or Index = WS_EX_PALETTEWINDOW Or Index = WS_EX_RIGHT _
Or Index = WS_EX_RIGHTSCROLLBAR Or Index = WS_EX_RTLREADING _
Or Index = WS_EX_STATICEDGE Or Index = WS_EX_TOOLWINDOW _
Or Index = WS_EX_TOPMOST Or Index = WS_EX_TRANSPARENT _
Or Index = WS_EX_WINDOWEDGE Then
gwIndex = GWL_EXSTYLE
Else
gwIndex = GWL_STYLE
End If
lCurStyle = GetWindowLong(Me.hwnd, gwIndex)
If newVal Then
lCurStyle = lCurStyle Or Index
Else
lCurStyle = lCurStyle And (Not Index)
End If
Call SetWindowLong(Me.hwnd, gwIndex, lCurStyle)
End Property
Public Property Get WindowStyle(ByVal _
Index As enWindowStyles) As Boolean
Dim gwIndex As enGetWindowLong
Dim lCurStyle As Long
If Index = WS_EX_ACCEPTFILES Or Index = WS_EX_APPWINDOW _
Or Index = WS_EX_CLIENTEDGE Or Index = WS_EX_CONTEXTHELP _
Or Index = WS_EX_CONTROLPARENT Or Index = WS_EX_DLGMODALFRAME _
Or Index = WS_EX_LEFT Or Index = WS_EX_LEFTSCROLLBAR _
Or Index = WS_EX_LTRREADING Or Index = WS_EX_MDICHILD _
Or Index = WS_EX_NOPARENTNOTIFY Or Index = WS_EX_OVERLAPPEDWINDOW _
Or Index = WS_EX_PALETTEWINDOW Or Index = WS_EX_RIGHT _
Or Index = WS_EX_RIGHTSCROLLBAR Or Index = WS_EX_RTLREADING _
Or Index = WS_EX_STATICEDGE Or Index = WS_EX_TOOLWINDOW _
Or Index = WS_EX_TOPMOST Or Index = WS_EX_TRANSPARENT _
Or Index = WS_EX_WINDOWEDGE Then
gwIndex = GWL_EXSTYLE
Else
gwIndex = GWL_STYLE
End If
lCurStyle = GetWindowLong(Me.hwnd, gwIndex)
WindowStyle = (lCurStyle Or Index) = lCurStyle
End Property
Private Sub Form_Load()
lCaptionHeight = (GetSystemMetrics(SM_CYCAPTION) _
+ GetSystemMetrics(SM_CYBORDER))
oldVal = Me.BorderStyle
RuntimeFormBorderStyle = vbBSNone
End Sub
Private Sub Form_MouseMove(Button As Integer, _
Shift As Integer, x As Single, y As Single)
If y < lCaptionHeight And Me.RuntimeFormBorderStyle = vbBSNone Then
Me.RuntimeFormBorderStyle = vbSizable
Else
Me.RuntimeFormBorderStyle = vbBSNone
End If
End Sub
Although this seems like a lot of code, it does make a more intuitive interface when it comes to borderless forms that can be moved and resized.