1

how to color formborder color in vb.net? I want color formborder equal to backcolor 45, 66, 50. What do I mean in the yellow circle in the screenshot below?. Formbordercolor note : I use visual studio 2010 Thanks roy

FormBorder

roy
  • 693
  • 2
  • 11
  • It's not easy and straightforward. It involves handling native windows messages like [`WM_NCPAINT`](https://learn.microsoft.com/en-us/windows/win32/gdi/wm-ncpaint?WT.mc_id=DT-MVP-5003235) and calling native windows function. Probably the easiest way of doing it, is using a borderless form, and using a toolbar or menu as titlebar. – Reza Aghaei Dec 27 '21 at 10:13
  • @RezaAghaei , if it can with code it's better if indeed another solution can you guide me? – roy Dec 27 '21 at 13:41
  • There are many similar questions in stackoverflow, but I couldn't find an example of a custom titlebar, so I posted the custom titlebar using VB.NET. – Reza Aghaei Dec 27 '21 at 23:32
  • My answer is using syntax of the newer versions of language. I do not have VS 2010, but I assume you can modify it on you machine. – Reza Aghaei Dec 27 '21 at 23:44
  • @RezaAghaei , ,thank you for your reply but I have an error. FindForm()' >>Value of type 'System.Windows.Forms.Form' cannot be converted to 'System.Drawing.Image' , FindForm()>>Value of type 'System.Windows.Forms.Form' cannot be converted to 'String',f.Icon >> Value of type 'System.Drawing.Icon' cannot be converted to 'System.Drawing.Image' and ? >> The '?' character cannot be used here . – roy Dec 28 '21 at 12:45
  • As I mentioned in the comments, I have written the answer with VS2019 and I don't have VS 2010, but anyhow, I modified it to the extent that I could, hope it works on your machine. But it's working perfectly in my environment. – Reza Aghaei Dec 28 '21 at 15:31
  • @RezaAghaei , Thanks for your reply. This runs perfectly and I have uploaded a screenshot of the original form that I marked round in blue, first at the top can it be the same size as the original size? If it could be better when it has a long distance for Movable and second at the bottom can it be sizeable? Because I try not to be sizeable. – roy Dec 29 '21 at 02:10
  • If you want to continue using this approach, then the next problem that you need to solve is allowing the user to resize the form. In this case, I'd rather to not change the answer as the post is long enough and its focus is on the titlebar. You can do some research and try to apply the solutions that you find in stackoverflow, for example [this one](https://stackoverflow.com/a/52094960/3110834). Later if you have any further question, please feel free to ask a new question and I'll try to help if I have any idea. – Reza Aghaei Dec 29 '21 at 10:17
  • @RezaAghaei , Okay thank you very much. you are my teacher and master .i have latest post can you help me ? https://stackoverflow.com/questions/70519360/how-to-filter-datagridview-with-combobbox-without-query-and-with-invisible-colum – roy Dec 29 '21 at 12:25
  • No problem @Roy. I put some comments under your other post. – Reza Aghaei Dec 29 '21 at 14:57

1 Answers1

0

As I mentioned in the comment, it's not a trivial thing to do. It involves handling native windows messages like WM_NCPAINT and calling native windows API function, and painting the titlebar and handling different situations yourself.

It probably will be easier if you use a borderless form, and the show a custom titlebar yourself. As an idea for a custom titlebar, you can use a MenuStrip.

There are many similar questions in stackoverflow, but I couldn't find an example of a custom titlebar (specially in VB.NET), so I posted the custom titlebar using VB.NET here.

Custom Titlebar using ManuStrip

In this example, I've created a custom titlebar class based on the menu strip, which supports the following features:

  • It has Close, Maximize/Restore, and Minimize buttons
  • It shows the Form's icon and text
  • Double click on the titlebar works and it maximizes or restores the form
  • Rightclick on the titlebar works and it shows system menu
  • Doubleclick on icon works and it closes the form
  • It's Movable; you can move the form by dragging the titlebar

I cannot tell it's a full-fledge titlebar, but it's a good proof of concept:

enter image description here

You can modify the appearance and behaviors based on your requirements. Here is the code:

Imports System.Runtime.InteropServices
Public Class CustomTitleBar
    Inherits MenuStrip
    Private CloseButton As ToolStripMenuItem
    Private MaximizeButton As ToolStripMenuItem
    Private MinimizeButton As ToolStripMenuItem
    Private IconLabel As ToolStripLabel
    Private TextLabel As ToolStripLabel
    Public Sub New()
        MyBase.New()
        CloseButton = New ToolStripMenuItem()
        MaximizeButton = New ToolStripMenuItem()
        MinimizeButton = New ToolStripMenuItem()
        IconLabel = New ToolStripLabel()
        TextLabel = New ToolStripLabel()
        'IconLabel
        IconLabel.Alignment = ToolStripItemAlignment.Left
        IconLabel.AutoSize = False
        IconLabel.Name = "IconLabel"
        IconLabel.Size = New Size(64, 64)
        IconLabel.Text = ""
        'TextLabel
        TextLabel.Alignment = ToolStripItemAlignment.Left
        TextLabel.AutoSize = True
        TextLabel.Name = "TextLabel"
        TextLabel.Text = ""
        'CloseButton
        CloseButton.Alignment = ToolStripItemAlignment.Right
        CloseButton.AutoSize = False
        CloseButton.Name = "CloseButton"
        CloseButton.Size = New Size(64, 64)
        CloseButton.Text = "✕"
        AddHandler CloseButton.Click,  AddressOf CloseButton_Click
        'MaximizeButton
        MaximizeButton.Alignment = ToolStripItemAlignment.Right
        MaximizeButton.AutoSize = False
        MaximizeButton.Name = "MaximizeButton"
        MaximizeButton.Size = New Size(64, 64)
        MaximizeButton.Text = "⬜"
        AddHandler MaximizeButton.Click, AddressOf MaximizeButton_Click
        'MinimizeButton
        MinimizeButton.Alignment = ToolStripItemAlignment.Right
        MinimizeButton.AutoSize = False
        MinimizeButton.Name = "MinimizeButton"
        MinimizeButton.Size = New Size(64, 64)
        MinimizeButton.Text = "―"
        AddHandler MinimizeButton.Click, AddressOf MinimizeButton_Click
        GripStyle = ToolStripGripStyle.Hidden
        Me.Padding = New Padding(1)
        ImageScalingSize = New System.Drawing.Size(32, 32)
        Me.AutoSize = True
        Me.Dock = DockStyle.Top
        Me.TabStop=False
        Items.Add(IconLabel)
        Items.Add(TextLabel)
        Items.Add(CloseButton)
        Items.Add(MaximizeButton)
        Items.Add(MinimizeButton)
    End Sub
    private sub MinimizeButton_Click(sender As Object, e As EventArgs)
        Dim f = FindForm()
        If (f Is Nothing) Then Return
        f.WindowState = FormWindowState.Minimized
    End sub
    private sub MaximizeButton_Click(sender As Object, e As EventArgs)
        Dim f = FindForm()
        If (f Is Nothing) Then Return
        If (f.WindowState = FormWindowState.Normal) Then
            f.WindowState = FormWindowState.Maximized
        ElseIf f.WindowState = FormWindowState.Maximized Then
            f.WindowState = FormWindowState.Normal
        End If
    End sub
    private sub CloseButton_Click(sender As Object, e As EventArgs)
        Dim f = FindForm()
        If (f Is Nothing) Then Return
        f.Close()
    End sub
   
    Protected Overrides Sub OnMouseDown(e As MouseEventArgs)
        MyBase.OnMouseDown(e)
        Dim f = FindForm()
        If (f Is Nothing) Then Return
        If (e.Button = MouseButtons.Left) Then
            If (e.Clicks = 1 AndAlso _
                e.Location.X < MinimizeButton.Bounds.X AndAlso _
                e.Location.X > IconLabel.Bounds.Right) Then
                ReleaseCapture()
                SendMessage(f.Handle, WM_NCLBUTTONDOWN, HT_CAPTION, 0)
            End If
        ElseIf (e.Button = MouseButtons.Right) Then
            Dim menu = GetSystemMenu(f.Handle, False)
            Dim command = TrackPopupMenu(menu, _
                    TPM_RETURNCMD + TPM_LEFTBUTTON + TPM_RIGHTBUTTON, _
                    MousePosition.X, MousePosition.Y, IntPtr.Zero, _
                    f.Handle, IntPtr.Zero)
            If (command > 0) Then
                SendMessage(f.Handle, _
                    WM_SYSCOMMAND, command, IntPtr.Zero)
            End If
        End If
    End Sub
    Protected Overrides Sub OnMouseDoubleClick(e As MouseEventArgs)
        MyBase.OnMouseDoubleClick(e)
        Dim f = FindForm()
        If (f Is Nothing) Then Return
        If (e.X < IconLabel.Bounds.Right) Then
            f.Close()
        ElseIf (f.WindowState = FormWindowState.Normal) Then
            f.WindowState = FormWindowState.Maximized
        ElseIf f.WindowState = FormWindowState.Maximized Then
            f.WindowState = FormWindowState.Normal
        End If
    End Sub
    Protected Overrides Sub OnParentChanged(e As EventArgs)
        MyBase.OnParentChanged(e)
        Dim f = FindForm()
        If (f Is Nothing) Then Return
        UpdateIcon()
        UpdateText()
        AddHandler f.TextChanged, AddressOf Parent_TextChanged
    End Sub
    Protected Overrides Sub OnHandleCreated(e As EventArgs)
        MyBase.OnHandleCreated(e)
        UpdateIcon()
        UpdateText()
    End Sub
    Private sub Parent_TextChanged(sender As Object, e As EventArgs)
        UpdateText()
    End sub
    Private sub UpdateIcon()
        Dim f = FindForm()
        If (f Is Nothing) Then Return
        If(f.Icon IsNot Nothing)
            IconLabel.Image = f.Icon.ToBitmap()
        End If
    End sub
    Private sub UpdateText()
        Dim f = FindForm()
        If (f Is Nothing) Then Return
        TextLabel.Text = f.Text
    End sub

    Private Const TPM_LEFTBUTTON As Integer = &H0
    Private Const TPM_RIGHTBUTTON As Integer = &H2
    Private Const TPM_RETURNCMD As Integer = &H100
    Private Const WM_SYSCOMMAND As Integer = &H112
    <DllImport("user32.dll")> _
    Private Shared Function GetSystemMenu(hWnd As IntPtr, _
        bRevert As Boolean) As IntPtr
    End Function
    <DllImport("user32.dll")> _
    Private Shared Function TrackPopupMenu( _
         hMenu As IntPtr,  uFlags As Integer, _
         x As Integer,  y As Integer,  nReserved As Integer, _
         hWnd As IntPtr,  prcRect As IntPtr) As Integer
    End Function
    Private Const WM_NCLBUTTONDOWN As Integer = &HA1
    Private Const HT_CAPTION As Integer = &H2
    <DllImport("User32")> _
    Private Shared Function SendMessage(hWnd As IntPtr, msg As Integer, _
        wParam As Integer, lParam As Integer) As Integer
    End Function
    <DllImport("User32")> _
    Private Shared Function ReleaseCapture() As Boolean
    End Function
End Class

After you build the project, you can drop an instance of CustomTitleBar to the form. To support showing system context menu, you need to add the following code to your form:

Public Class Form1
    Private Const WS_SYSMENU As Integer = &H80000
    Private Const WS_MINIMIZEBOX As Integer = &H20000
    Private Const WS_MAXIMIZEBOX As Integer = &H10000
    Protected Overrides ReadOnly Property CreateParams _
        As System.Windows.Forms.CreateParams
        Get
            Dim p = MyBase.CreateParams
            p.Style = WS_SYSMENU + WS_MINIMIZEBOX + WS_MAXIMIZEBOX
            Return p
        End Get
    End Property
End Class
Reza Aghaei
  • 120,393
  • 18
  • 203
  • 398
  • ,thank you for your reply but I have an error. `FindForm()' >>Value of type 'System.Windows.Forms.Form' cannot be converted to 'System.Drawing.Image' `, `FindForm()`>>Value of type 'System.Windows.Forms.Form' cannot be converted to 'String',`f.Icon` >> Value of type 'System.Drawing.Icon' cannot be converted to 'System.Drawing.Image' and `?` >> The '?' character cannot be used here . – roy Dec 28 '21 at 03:05