Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / Languages / VB

Custom MenuStrip and A Form Without Borders (Full Control)

4.88/5 (5 votes)
10 Sep 2015CPOL1 min read 18.1K   478  
Working code of the custom MenuStrip on the LinearGradientBrush constructor base. And how to control Form without borders.

Introduction

'How to: Create a Linear Gradient' or 'FormBorderStyle Enumeration' you can read on MSDN. But I am publishing a working code and application that you can use to move and resize form with FormBorderStyle.None. I use custom MenuString where I create a MinimizeBox, MaximizeBox, CloseBox, File, Options and Help as ToolStripMenuItem. It looks like this:

What Is the Problem?

After you change the form border style on FormBorderStyle.None, you will receive an invalid-form without "default" titlebar. It cannot move, it cannot resize, this form becomes unmanageable. Add MenuStrip control with Dock Top and add some controls (RadioButton, Button, etc. at your discretion) for check form usability. And go to...

Using the Code

We define the File, Options, Help (or what do you want) on the left side MenuStrip, and three elements indicated asterisk, which will control buttons form on the right side (all of them as regular ToolStripMenuItem).

For draw MenuStrip , we encapsulate LinearGradientBrush constructor in Pain event. The LinearGradientBrush constructor receives four arguments: two points and two colors.

VB.NET
Dim contr As Color = Color.FromName("Control")
    Dim g2 As Byte = contr.G
    Dim b2 As Byte = contr.B
    Dim r2 As Byte = contr.R
    Dim a2 As Byte = contr.A
    Dim contrblack As Color = Color.FromName("Black")
    Dim g3 As Byte = contrblack.G
    Dim b3 As Byte = contrblack.B
    Dim r3 As Byte = contrblack.R
    Dim a3 As Byte = contrblack.A

Private Sub MenuStrip1_Paint(ByVal sender As Object, _
ByVal e As System.Windows.Forms.PaintEventArgs) Handles MenuStrip1.Paint
        'Encapsulates both two-color gradients and custom multicolor gradients
        Dim linGrBrush As New LinearGradientBrush_
        (New Point(0, 0), New Point(0, MenuStrip1.Size.Height), _
                          Color.FromArgb(a2, r2, g2, b2), Color.FromArgb(a3, r3, g3, b3))
        Dim pen As New Pen(linGrBrush)
        e.Graphics.FillRectangle(linGrBrush, 0, 0, MenuStrip1.Size.Width, MenuStrip1.Size.Height)
    End Sub

...and, for imitation drab and drag form of the element MenuStrip, insert short code for window handle, the message WM_NCLBUTTONDOWN, the message wparam field HT_CAPTION (a parameter in the current position), the message Iparam field from WndProc.

VB.NET
'Imitation drag form on MenuStrip1
    Private Sub MenuStrip1_MouseDown(ByVal sender As Object, _
    ByVal e As System.Windows.Forms.MouseEventArgs) Handles MenuStrip1.MouseDown
        'For drag the form 
        Const HT_CAPTION As Integer = &H2
        Const WM_NCLBUTTONDOWN As Integer = &HA1

        If (e.Button = Windows.Forms.MouseButtons.Left) Then
            MenuStrip1.Capture = False
            Me.WndProc(Message.Create(Me.Handle, _
            WM_NCLBUTTONDOWN, CType(HT_CAPTION, IntPtr), IntPtr.Zero))
        End If
    End Sub

Similarly draws other items. The MinimizeBox for example. The variable 'entryMin=false' if MouseLeave event is raised. And 'entryMin=true' if MouseEnter event is raised.

VB.NET
Dim lightgray As Color = Color.FromName("LightGray")
    Dim g8 As Byte = lightgray.G
    Dim b8 As Byte = lightgray.B
    Dim r8 As Byte = lightgray.R
    Dim a8 As Byte = lightgray.A
    Dim gray As Color = Color.FromName("Gray")
    Dim g9 As Byte = gray.G
    Dim b9 As Byte = gray.B
    Dim r9 As Byte = gray.R
    Dim a9 As Byte = gray.A
    Dim entryMin As Boolean = False

    Private Sub MinToolStripMenuItem_Paint(ByVal sender As Object, _
    ByVal e As System.Windows.Forms.PaintEventArgs) Handles MinToolStripMenuItem.Paint

        ' Create string to draw.
        Dim drawString As [String] = "Sample Text"
        ' Create font and brush.
        Dim drawFont As New Font("Arial", 16)
        Dim drawBrush As New SolidBrush(Color.Black)
        ' Create point for upper-left corner of drawing.
        Dim drawPoint As New PointF(150.0F, 150.0F)
        ' Draw string to screen.
        e.Graphics.DrawString(drawString, drawFont, drawBrush, drawPoint)

        If entryMin Then

            'Location bottom control depending of form size
            MinToolStripMenuItem.Margin = New System.Windows.Forms.Padding(we, 2, 2, 2)

            'Encapsulates both two-color gradients and custom multicolor gradients
            Dim linGrBrush As New LinearGradientBrush(New Point(0, 0), _
            New Point(0, MinToolStripMenuItem.Size.Height), _
                      Color.FromArgb(a9, r9, g9, b9), Color.FromArgb(a8, r8, g8, b8))
            Dim pen As New Pen(linGrBrush)
            e.Graphics.FillRectangle(linGrBrush, 0, 0, _
            MinToolStripMenuItem.Size.Width, MinToolStripMenuItem.Size.Height)

            Dim bks As Color = Color.Black
            e.Graphics.DrawLine(New Pen(New SolidBrush(bks), 2), 7, 11, 19, 11)

        Else

            'Location bottom control depending of form size
            MinToolStripMenuItem.Margin = New System.Windows.Forms.Padding(we, 2, 2, 2)

            'Encapsulates both two-color gradients and custom multicolor gradients
            Dim linGrBrush As New LinearGradientBrush(New Point(0, 0), _
            	New Point(0, MinToolStripMenuItem.Size.Height), _
                Color.FromArgb(a8, r8, g8, b8), Color.FromArgb(a9, r9, g9, b9))
            Dim pen As New Pen(linGrBrush)
            e.Graphics.FillRectangle(linGrBrush, 0, 0, _
            MinToolStripMenuItem.Size.Width, MinToolStripMenuItem.Size.Height)

            Dim bks As Color = Color.Black
            e.Graphics.DrawLine(New Pen(New SolidBrush(bks), 2), 9, 10, 17, 10)

        End If

    End Sub

For resize form, we have:

VB.NET
#Region "Override the WinProc"
    'To override the WinProc and wrap the WM_NCHITTEST message in this method.
    Protected Overrides Sub WndProc(ByRef m As Message)
        Const WM_NCHITTEST As Integer = &H84
        MyBase.WndProc(m)
        ' The WM_ACTIVATEAPP message occurs when the application
        ' becomes is active. 
        If m.Msg = WM_NCHITTEST Then
            m.Result = HitTestNCA(m.HWnd, m.WParam, m.LParam)
        End If
    End Sub

...

Points of Interest

All buttons are interactive and change image.

Reference

History

  • Released 10/09/2015

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)