Moving a captionless form

Merrion

Well-known member
Joined
Sep 29, 2001
Messages
265
Location
Dublin, Ireland
User Rank
*Experts*
Often, especially where a customised or skinned look is desired, the form is created with the FormBorderStyle set to FixedSingle.
However if you still want to move that skinned form you have a bit of a problem. Fortunately it is possible to handle the WM_NCHITTEST window message to make windows think the mouse is over the caption even where a form doesnt have one.

1. Defining a rectangle that emulates the form caption
In the form:
Code:
Public Class Form1
    Inherits System.Windows.Forms.Form

#Region "Private memeber variables"
    Dim rcCaption As Rectangle
#End Region

    Public Sub New()
        MyBase.New()

        This call is required by the Windows Form Designer.
        InitializeComponent()

        \\ Make the fake caption rectangle
        rcCaption = New Rectangle(0, 0, Me.Width, 29)

    End Sub

    Private Sub Form1_Paint(ByVal sender As Object, ByVal e As System.Windows.Forms.PaintEventArgs) Handles MyBase.Paint

        e.Graphics.FillRectangle(New SolidBrush(Color.Blue), rcCaption)

    End Sub

    Protected Overrides Sub WndProc(ByRef m As System.Windows.Forms.Message)
        \\ We want to pretend that the rectangle rcCaption, is the caption bar so we can drag the form by it...
        If m.Msg = WM_NCHITTEST Then
            Call FakeCaptionForCaptionlessWindow(Me, m, rcCaption)
        Else
            MyBase.WndProc(m)
        End If
    End Sub

End Class

2. The WM_NCHITTEST handler
This is kept in a seperate module for reusability...
Code:
Imports System.Windows.Forms

\\ --[ApiHitTestHandling]-------------------------------------
\\ Used to handle the WM_HITTEST message, to allow dragging of 
\\ captionless windows...
\\ -----------------------------------------------------------
Module ApiHitTestHandling

    Public Const WM_NCHITTEST = &H84

    Public Enum HitTestResult
        HTBORDER = 18
        HTBOTTOM = 15
        HTBOTTOMLEFT = 16
        HTBOTTOMRIGHT = 17
        HTCAPTION = 2
        HTCLIENT = 1
        HTERROR = (-2)
        HTGROWBOX = 4
        HTHSCROLL = 6
        HTLEFT = 10
        HTMAXBUTTON = 9
        HTMENU = 5
        HTMINBUTTON = 8
        HTNOWHERE = 0
        HTRIGHT = 11
        HTSYSMENU = 3
        HTTOP = 12
        HTTOPLEFT = 13
        HTTOPRIGHT = 14
        HTVSCROLL = 7
        HTTRANSPARENT = (-1)
        HTOBJECT = 19
        HTCLOSE = 20
        HTHELP = 21
    End Enum

    Public Sub FakeCaptionForCaptionlessWindow(ByVal fParent As Form, ByRef m As Message, ByVal CaptionRectangle As Rectangle)

        If m.Msg = WM_NCHITTEST Then
            \\ If the mouse is in the rectangle that is considered to be the caption set the return value to HTCAPTION
            Dim ptClickLocation As New Point(m.LParam.ToInt32)
            ptClickLocation = fParent.PointToClient(ptClickLocation)

            If CaptionRectangle.Contains(ptClickLocation) Then
                m.Result = New IntPtr(HitTestResult.HTCAPTION)
            Else
                m.Result = New IntPtr(HitTestResult.HTCLIENT)
            End If
        End If
    End Sub

End Module
 
Back
Top