locked
How to remove the white space at top of form RRS feed

  • Question

  • Hi everybody,

    I have problem with winform application and need to help.

    I create a new form, i want hide the title bar but the form can be resize and move. I try set some below attributes but when run it, it always have a whitespace at top of the form

    - formborderstyle = sizable

    - control box = false

    - me.text = ""

    How can I remove it?

    Please help me, thank you very much!


    Thursday, September 3, 2020 3:38 PM

All replies

  • Hi everybody,

    I have problem with winform application and need to help.

    I create a new form, i want hide the title bar but the form can be resize and move. I try set some below attributes but when run it, it always have a whitespace at top of the form

    - formborderstyle = sizable

    - control box = false

    - me.text = ""

    How can I remove it?

    Please help me, thank you very much!


    Hi

    - formborderstyle = none


    Regards Les, Livingston, Scotland

    Thursday, September 3, 2020 3:59 PM
  • Thank you Les,

    I tried it before.

    But I cannot resize the form by hold on the edge and move mouse when set it.

    Thursday, September 3, 2020 4:35 PM
  • Hi

    That is correct. You need to take account of that if you use the Borders = None.

    You would need to work to build your own resize and relocate for the Form.

    It is much easier to live with the Form Title text and what you call white space. BTW why do you want to not have the title bar at the top of the Form?


    Regards Les, Livingston, Scotland

    Thursday, September 3, 2020 4:39 PM

  • I create a new form, i want hide the title bar but the form can be resize and move. 

    It is now done with DWM , mainly DwmExtendFrameIntoClientArea

    Friday, September 4, 2020 6:45 AM
  • It look great! Could you share me more about how Can I do it? Ex: code example
    Friday, September 4, 2020 9:41 AM
  • I adapted the MSDN C++ code from Custom Window Frame Using DWM  :

    Imports System.Runtime.InteropServices
    
    ' Reference : https://docs.microsoft.com/en-us/windows/win32/dwm/customframe
    
    Public Class Form1
    
        <StructLayout(LayoutKind.Sequential)>
        Public Structure MARGINS
            Public cxLeftWidth, cxRightWidth, cyTopHeight, cyBottomHeight As Integer
            Public Sub New(ByVal left As Integer, ByVal right As Integer, ByVal top As Integer, ByVal bottom As Integer)
                cxLeftWidth = left
                cyTopHeight = top
                cxRightWidth = right
                cyBottomHeight = bottom
            End Sub
        End Structure
    
        <DllImport("Dwmapi.dll", SetLastError:=True, CharSet:=CharSet.Auto)>
        Public Shared Function DwmExtendFrameIntoClientArea(ByVal hwnd As IntPtr, ByRef margins As MARGINS) As Integer
        End Function
    
        <DllImport("Dwmapi.dll", SetLastError:=True, CharSet:=CharSet.Auto)>
        Public Shared Function DwmIsCompositionEnabled(ByRef enabled As Boolean) As Integer
        End Function
    
        <DllImport("Dwmapi.dll", SetLastError:=True, CharSet:=CharSet.Auto)>
        Public Shared Function DwmDefWindowProc(ByVal hWnd As IntPtr, ByVal msg As Integer, ByVal wParam As IntPtr, ByVal lParam As IntPtr, ByRef plResult As IntPtr) As Boolean
        End Function
    
        Public Const WM_CREATE As Integer = &H1
        Public Const WM_ACTIVATE As Integer = &H6
        Public Const WM_ACTIVATEAPP As Integer = &H1C
        Public Const WM_NCCALCSIZE As Integer = &H83
        Public Const WM_NCHITTEST As Integer = &H84
        Public Const WM_NCACTIVATE As Integer = &H86
        Public Const WM_RBUTTONDOWN As Integer = &H204
        Public Const WM_RBUTTONUP As Integer = &H205
        Public Const WM_NCLBUTTONDOWN As Integer = &HA1
        Public Const WM_NCLBUTTONUP As Integer = &HA2
        Public Const WM_NCRBUTTONDOWN As Integer = &HA4
        Public Const WM_NCRBUTTONUP As Integer = &HA5
    
        Public Const WS_OVERLAPPED As Integer = &H0, WS_POPUP As Integer = &H80000000, WS_CHILD As Integer = &H40000000, WS_MINIMIZE As Integer = &H20000000, WS_VISIBLE As Integer = &H10000000, WS_DISABLED As Integer = &H8000000, WS_CLIPSIBLINGS As Integer = &H4000000, WS_CLIPCHILDREN As Integer = &H2000000, WS_MAXIMIZE As Integer = &H1000000, WS_CAPTION As Integer = &HC00000, WS_BORDER As Integer = &H800000, WS_DLGFRAME As Integer = &H400000, WS_VSCROLL As Integer = &H200000, WS_HSCROLL As Integer = &H100000, WS_SYSMENU As Integer = &H80000, WS_THICKFRAME As Integer = &H40000, WS_TABSTOP As Integer = &H10000, WS_MINIMIZEBOX As Integer = &H20000, WS_MAXIMIZEBOX As Integer = &H10000
        Public Const WS_OVERLAPPEDWINDOW As Integer = WS_OVERLAPPED Or WS_CAPTION Or WS_SYSMENU Or WS_THICKFRAME Or WS_MINIMIZEBOX Or WS_MAXIMIZEBOX
    
        Public Const SWP_NOREDRAW As Integer = &H8, SWP_FRAMECHANGED As Integer = &H20, SWP_NOCOPYBITS As Integer = &H100, SWP_NOOWNERZORDER As Integer = &H200, SWP_NOSENDCHANGING As Integer = &H400, SWP_NOREPOSITION As Integer = SWP_NOOWNERZORDER, SWP_DEFERERASE As Integer = &H2000, SWP_ASYNCWINDOWPOS As Integer = &H4000
    
        <DllImport("User32.dll", SetLastError:=True, CharSet:=CharSet.Auto)>
        Public Shared Function SetWindowPos(ByVal hWnd As IntPtr, ByVal hWndInsertAfter As IntPtr, ByVal x As Integer, ByVal y As Integer, ByVal cx As Integer, ByVal cy As Integer, ByVal flags As Integer) As Boolean
        End Function
    
        <StructLayout(LayoutKind.Sequential)>
        Public Structure RECT
            Public left As Integer
            Public top As Integer
            Public right As Integer
            Public bottom As Integer
            Public Sub New(left As Integer, top As Integer, right As Integer, bottom As Integer)
                Me.left = left
                Me.top = top
                Me.right = right
                Me.bottom = bottom
            End Sub
        End Structure
    
        <DllImport("User32.dll", SetLastError:=True, CharSet:=CharSet.Auto)>
        Public Shared Function GetWindowRect(hWnd As IntPtr, ByRef lpRect As RECT) As Boolean
        End Function
    
        <DllImport("User32.dll", SetLastError:=True, CharSet:=CharSet.Auto)>
        Public Shared Function AdjustWindowRectEx(ByRef lpRect As RECT, ByVal dwStyle As Integer, ByVal bMenu As Boolean, ByVal dwExStyle As Integer) As Boolean
        End Function
    
        Public Const HTNOWHERE As Integer = 0, HTTRANSPARENT As Integer = -1, HTCAPTION As Integer = 2, HTSYSMENU As Integer = 3, HTGROWBOX As Integer = 4, HTMENU As Integer = 5,
        HTHSCROLL As Integer = 6, HTVSCROLL As Integer = 7, HTMINBUTTON As Integer = 8, HTMAXBUTTON As Integer = 9, HTLEFT As Integer = 10, HTRIGHT As Integer = 11, HTTOP As Integer = 12,
        HTTOPLEFT As Integer = 13, HTTOPRIGHT As Integer = 14, HTBOTTOM As Integer = 15, HTBOTTOMLEFT As Integer = 16, HTBOTTOMRIGHT As Integer = 17, HTBORDER As Integer = 18,
        HTCLOSE As Integer = 20, HTHELP As Integer = 21, HTMDIMAXBUTTON As Integer = 66, HTMDIMINBUTTON As Integer = 67, HTMDICLOSE As Integer = 68
    
        Public Structure NCCALCSIZE_PARAMS
            Public rect0 As RECT
            Public rect1 As RECT
            Public rect2 As RECT
            Public lppos As IntPtr
        End Structure
    
        Public Shared Function HIWORD(ByVal i As Integer) As Integer
            Return CShort(i >> 16)
        End Function
    
        Public Shared Function LOWORD(ByVal i As Integer) As Integer
            Return CShort(i And &HFFFF)
        End Function
    
        Public Shared Function GET_X_LPARAM(ByVal lParam As IntPtr) As Integer
            Return LOWORD(lParam.ToInt32())
        End Function
    
        Public Shared Function GET_Y_LPARAM(ByVal lParam As IntPtr) As Integer
            Return HIWORD(lParam.ToInt32())
        End Function
    
        <DllImport("User32.dll", SetLastError:=True, CharSet:=CharSet.Auto)>
        Public Shared Function DestroyWindow(hWnd As IntPtr) As Boolean
        End Function
    
        Private Shared windowMargins As MARGINS
        Private Const TOPEXTENDWIDTH As Integer = 2
        Private Const LEFTEXTENDWIDTH As Integer = 2
        Private Const RIGHTEXTENDWIDTH As Integer = 2
        Private Const BOTTOMEXTENDWIDTH As Integer = 2
    
        Friend WithEvents Button1 As Button
    
        Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
            Button1 = New Button()
            Button1.Location = New Point(350, 6)
            Button1.Text = "Test Button"
            Button1.BackColor = Color.Transparent
            Button1.UseCompatibleTextRendering = True
            Me.Controls.Add(Button1)
    
            Me.BackColor = System.Drawing.Color.Black
    
            CenterToScreen()
        End Sub
    
        Protected Overrides Sub WndProc(ByRef m As Message)
            Dim fCallDWP As Boolean = True
            Dim fDwmEnabled As Boolean = False
            Dim lRet As Integer = 0
            Dim hr As Integer = 0
            ' Winproc worker for custom frame issues.
            hr = DwmIsCompositionEnabled(fDwmEnabled)
            If (hr = 0) Then
                lRet = CustomCaptionProc(m.HWnd, m.Msg, m.WParam, m.LParam, fCallDWP)
            End If
            ' Winproc worker for the rest of the application.
            If (fCallDWP) Then
                MyBase.WndProc(m)
            Else
                m.Result = CType(lRet, IntPtr)
            End If
        End Sub
    
        Private Shared Function CustomCaptionProc(ByVal hWnd As IntPtr, ByVal message As UInteger, ByVal wParam As IntPtr, ByVal lParam As IntPtr, ByRef pfCallDWP As Boolean) As Integer
            Dim lRet As IntPtr = IntPtr.Zero
            Dim hr As Integer = 0
            Dim fCallDWP As Boolean = True
    
            fCallDWP = Not DwmDefWindowProc(hWnd, message, wParam, lParam, lRet)
            ' Handle window creation.
            If (message = WM_CREATE) Then
                Dim rcClient As RECT = New RECT()
                GetWindowRect(hWnd, rcClient)
                SetWindowPos(hWnd, IntPtr.Zero, rcClient.left, rcClient.top, (rcClient.right - rcClient.left), (rcClient.bottom - rcClient.top), SWP_FRAMECHANGED)
    
                fCallDWP = True
                lRet = IntPtr.Zero
            End If
    
            'If (message = WM_ACTIVATE Or message = WM_NCACTIVATE Or message = WM_ACTIVATEAPP) Then
            If (message = WM_ACTIVATE) Then
                windowMargins.cxLeftWidth = LEFTEXTENDWIDTH
                windowMargins.cxRightWidth = RIGHTEXTENDWIDTH
                windowMargins.cyBottomHeight = BOTTOMEXTENDWIDTH
                windowMargins.cyTopHeight = TOPEXTENDWIDTH
                DwmExtendFrameIntoClientArea(hWnd, windowMargins)
    
                fCallDWP = True
                lRet = IntPtr.Zero
            End If
    
            ' Handle the non-client size message.
            If ((message = WM_NCCALCSIZE) And (wParam = CType(1, IntPtr))) Then
                Dim pncsp As NCCALCSIZE_PARAMS = CType(Marshal.PtrToStructure(lParam, GetType(NCCALCSIZE_PARAMS)), NCCALCSIZE_PARAMS)
                pncsp.rect0.Top = pncsp.rect0.Top + 0
                pncsp.rect0.bottom = pncsp.rect0.bottom + 0
                pncsp.rect0.left = pncsp.rect0.left - 0
                pncsp.rect0.right = pncsp.rect0.right - 0
                Marshal.StructureToPtr(pncsp, lParam, False)
                ' No need to pass the message on to the DefWindowProc.
                lRet = IntPtr.Zero
                fCallDWP = False
    
            End If
    
            ' Handle hit testing in the NCA if not handled by DwmDefWindowProc.
            If ((message = WM_NCHITTEST) And (lRet = IntPtr.Zero)) Then
                lRet = HitTestNCA(hWnd, wParam, lParam)
                If (lRet <> CType(HTNOWHERE, IntPtr)) Then
                    fCallDWP = False
                End If
            End If
    
            ' Close window on Right mouse button
            If (message = WM_NCRBUTTONDOWN) Then
                System.Threading.Thread.Sleep(200)
                DestroyWindow(hWnd)
            End If
    
            pfCallDWP = fCallDWP
            Return CType(lRet, Integer)
        End Function
    
        Private Shared Function HitTestNCA(ByVal hWnd As IntPtr, ByVal wParam As IntPtr, ByVal lParam As IntPtr) As IntPtr
            ' Get the point coordinates for the hit test.
            Dim ptMouse As New Point(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam))
    
            ' Get the window rectangle.
            Dim rcWindow As RECT = Nothing
            GetWindowRect(hWnd, rcWindow)
    
            ' Get the frame rectangle, adjusted for the style without a caption.
            Dim rcFrame As New RECT(0, 0, 0, 0)
            AdjustWindowRectEx(rcFrame, WS_OVERLAPPEDWINDOW And Not WS_CAPTION, False, 0)
            Dim uRow As UShort = 1
            Dim uCol As UShort = 1
            Dim fOnResizeBorder As Boolean = False
    
            ' Determine if the point is at the top or bottom of the window.
            If ptMouse.Y >= rcWindow.top AndAlso ptMouse.Y < rcWindow.top + TOPEXTENDWIDTH Then
                fOnResizeBorder = (ptMouse.Y < (rcWindow.top - rcFrame.top))
                uRow = 0
            ElseIf ptMouse.Y < rcWindow.bottom AndAlso ptMouse.Y >= rcWindow.bottom - BOTTOMEXTENDWIDTH Then
                uRow = 2
            End If
    
            ' Determine if the point is at the left or right of the window.
            If ptMouse.X >= rcWindow.left AndAlso ptMouse.X < rcWindow.left + LEFTEXTENDWIDTH Then
                uCol = 0 ' left side
            ElseIf ptMouse.X < rcWindow.right AndAlso ptMouse.X >= rcWindow.right - RIGHTEXTENDWIDTH Then
                uCol = 2 ' right side
            End If
    
            'Dim hitTests(,) As Integer = {
            '    {HTTOPLEFT, If(fOnResizeBorder, HTTOP, HTCAPTION), HTTOPRIGHT},
            '    {HTLEFT, HTNOWHERE, HTRIGHT},
            '    {HTBOTTOMLEFT, HTBOTTOM, HTBOTTOMRIGHT}
            '}
            Dim hitTests(,) As Integer = {
                {HTTOPLEFT, If(fOnResizeBorder, HTTOP, HTCAPTION), HTTOPRIGHT},
                {HTLEFT, HTCAPTION, HTRIGHT},
                {HTBOTTOMLEFT, HTBOTTOM, HTBOTTOMRIGHT}
            }
    
            Return New IntPtr(hitTests(uRow, uCol))
        End Function
    
        Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
            MessageBox.Show("Button clicked", "Information", MessageBoxButtons.OK, MessageBoxIcon.Information)
        End Sub
    End Class
    

    Friday, September 4, 2020 11:06 AM
  • I tried it and it work well.

    But have other problem: when I set window state = maximized some control nearby the edge of form will be go out of screen.

    Friday, September 4, 2020 4:32 PM
  • I tried it and it work well.

    But have other problem: when I set window state = maximized some control nearby the edge of form will be go out of screen.

    You can increase borders when the window is maximized, in WM_NCCALCSIZE

    For example, I add 6 to top when it is maximized :

    If (IsZoomed(hWnd)) Then
        pncsp.rect0.top = pncsp.rect0.top + 6
        pncsp.rect0.bottom = pncsp.rect0.bottom + 0
        pncsp.rect0.left = pncsp.rect0.left - 0
        pncsp.rect0.right = pncsp.rect0.right - 0
    Else
        pncsp.rect0.top = pncsp.rect0.top + 0
        pncsp.rect0.bottom = pncsp.rect0.bottom + 0
        pncsp.rect0.left = pncsp.rect0.left - 0
        pncsp.rect0.right = pncsp.rect0.right - 0
    End If

    with :

        <DllImport("User32.dll", SetLastError:=True, CharSet:=CharSet.Auto)>
        Public Shared Function IsZoomed(hWnd As IntPtr) As Boolean
        End Function


    • Edited by Castorix31 Friday, September 4, 2020 5:17 PM
    Friday, September 4, 2020 5:07 PM
  • That look great! Let me try it. But let me know if you have any other notices when apply this one. Because my application already have many users. We must be carefully
    Friday, September 4, 2020 11:16 PM
  • The border size should be calculated from Windows System Metrics 

    This works on my OS (Windows 10 - 1909) =>

    Dim nBorderWidth = GetSystemMetrics(SM_CXFRAME) + GetSystemMetrics(SM_CXPADDEDBORDER)
    Dim nBorderHeight = GetSystemMetrics(SM_CYFRAME) + GetSystemMetrics(SM_CXPADDEDBORDER)
    
    If (IsZoomed(hWnd)) Then
        pncsp.rect0.top = pncsp.rect0.top + nBorderHeight
        pncsp.rect0.bottom = pncsp.rect0.bottom - nBorderHeight
        pncsp.rect0.left = pncsp.rect0.left + nBorderWidth
        pncsp.rect0.right = pncsp.rect0.right - nBorderWidth
    Else
        pncsp.rect0.top = pncsp.rect0.top + 0
        pncsp.rect0.bottom = pncsp.rect0.bottom + 0
        pncsp.rect0.left = pncsp.rect0.left - 0
        pncsp.rect0.right = pncsp.rect0.right - 0
    End If


    with :

        <DllImport("User32.dll", SetLastError:=True, CharSet:=CharSet.Auto)>
        Public Shared Function GetSystemMetrics(nIndex As Integer) As Integer
        End Function
        
        Public Const SM_CXDLGFRAME = 7
        Public Const SM_CYDLGFRAME = 8
        Public Const SM_CXFIXEDFRAME = SM_CXDLGFRAME ' ;win40 name change
        Public Const SM_CYFIXEDFRAME = SM_CYDLGFRAME ' ;win40 name change
        Public Const SM_CXFRAME = 32
        Public Const SM_CYFRAME = 33
        Public Const SM_CXPADDEDBORDER = 92

    I added OnPaint to colorize the borders in Red and, when maximized, I get (left part of the window, button at (1, 1)) =>



    • Edited by Castorix31 Saturday, September 5, 2020 9:28 AM
    Saturday, September 5, 2020 9:24 AM
  • Hi Lisa Bui,

    Did you solve your problem? If your question has been answered then please click the "Mark as Answer" Link at the bottom of the correct post(s), so that it will help other members to find the solution quickly if they face a similar issue.

    Best Regards,

    Xingyu Zhao


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    Monday, September 14, 2020 8:54 AM