Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Moving a borderless window - an alternate way

0.00/5 (No votes)
9 Feb 2004 1  
How to move a borderless form by adding or removing the border part.

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 ' The frame changed: send WM_NCCALCSIZE

    SWP_HIDEWINDOW = &H80
    SWP_NOACTIVATE = &H10
    SWP_NOCOPYBITS = &H100
    SWP_NOMOVE = &H2
    SWP_NOOWNERZORDER = &H200 ' Don't do owner Z ordering

    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
'\\ Get Window Long Indexes...

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

'\\ Window Style

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
    '\\ New from 95/NT4 onwards

    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 '/* Use instead of GetMenuCheckMarkDimensions()! */

    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
    '\\ Refresh the window

    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
    '\\ Extended window style

    gwIndex = GWL_EXSTYLE
Else
    '\\ Standard window style

    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
    '\\ Extended window style

    gwIndex = GWL_EXSTYLE
Else
    '\\ Standard window style

    gwIndex = GWL_STYLE
End If

lCurStyle = GetWindowLong(Me.hwnd, gwIndex)

WindowStyle = (lCurStyle Or Index) = lCurStyle

End Property
Private Sub Form_Load()

'\\ calculate the height of a caption bar

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.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here