I was wondering is there a way to get a button on the application title bar...more likely like the one in the firefox 4 and on opera latest browser.


Is it any possible to get a button like that or just a regular button on the title bar?...thought it will be nice to try it out in the programming :icon_smile:

Attachments Untitled-1.jpg 16.92 KB

Hi,

Create a form and change in the properties:

borderstyle = Fixedtoolwindow
Controlbox = False
Startposition= centerscreen

Then add the buttons you need for your application.

Just a thought :)

I put together this example. It may need some tweaking but it appears to be working ok. Should at least give you some ideas.

You can draw the button anyway you like. This draws a visual style button if visual styles are supported.

Option Strict On

Imports System.Runtime.InteropServices

Public Class Form1

    Private Const WM_NCPAINT As Integer = 133
    Private Const WM_NCMOUSEMOVE As Integer = 160
    Private Const WM_NCLBUTTONDOWN As Integer = 161
    Private Const WM_NCLBUTTONUP As Integer = 162
    Private Const WM_NCLBUTTONDBLCLK As Integer = 163
    Private Const WM_NCACTIVATE As Integer = 134
    Private Const WM_NCMOUSELEAVE As Integer = 674

    Private TitleBarButtonRectangle As Rectangle
    Private TitleBarButtonState As ButtonState
    Private TitleBarMouseIsDown As Boolean

    Private Enum ButtonState As Byte
        Normal
        Hot
        Pressed
    End Enum

    Sub New()

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

        ' Add any initialization after the InitializeComponent() call.

        'Set the x and width of the button.  Adjust the height and y position
        'in the size button sub.  The y position will need to change on window
        'state changes.
        TitleBarButtonRectangle = New Rectangle(30, 0, 75, 25)
        SizeButton()
    End Sub

    Protected Overrides Sub WndProc(ByRef m As System.Windows.Forms.Message)
        'Process the non client area messages here.

        Select Case m.Msg

            Case WM_NCPAINT, WM_NCACTIVATE, WM_NCMOUSELEAVE
                'process the message and reset the button to the normal state
                'and draw it. This will draw the initial button and repaint it
                'if the title bar needs a paint update.
                MyBase.WndProc(m)
                TitleBarButtonState = ButtonState.Normal
                TitleBarMouseIsDown = False
                DrawButton(TitleBarButtonState)

            Case WM_NCMOUSEMOVE
                'The mouse is moving in the non client area.

                If TitleBarButtonRectangle.Contains(GetNonClientPoint(CInt(m.LParam))) Then
                    'the mouse is in the button
                    'If the mouse is down then draw it pressed if not already
                    'If the mouse is not down then draw it hot if not already
                    If TitleBarMouseIsDown Then
                        If TitleBarButtonState <> ButtonState.Pressed Then
                            TitleBarButtonState = ButtonState.Pressed
                            DrawButton(TitleBarButtonState)
                        End If
                    Else
                        If TitleBarButtonState <> ButtonState.Hot Then
                            TitleBarButtonState = ButtonState.Hot
                            DrawButton(TitleBarButtonState)
                        End If
                    End If

                Else
                    'The mouse is not in the button.
                    'If the mouse is down then draw it hot, when the
                    'mouse moves back into the button it will be redrawn pressed.

                    'Otherwise draw it normal if its not already.
                    If TitleBarMouseIsDown Then
                        If TitleBarButtonState <> ButtonState.Hot Then
                            TitleBarButtonState = ButtonState.Hot
                            DrawButton(TitleBarButtonState)
                        End If
                    Else
                        If TitleBarButtonState <> ButtonState.Normal Then
                            TitleBarButtonState = ButtonState.Normal
                            DrawButton(TitleBarButtonState)
                        End If

                    End If

                End If

                'When the mouse is down and it leaves the window 
                'it will remain in its hot or pressed state. when the
                'mouse is let up outside the window and moved it will 
                'recieve a message to repaint.

                'Process all the mouse moves.
                MyBase.WndProc(m)

            Case WM_NCLBUTTONDOWN
                'Left mouse button has been held down in the non client area

                'If the mouse is inside the button then change its state to pressed
                'and redraw it.  Store that the mouse is down.
                If TitleBarButtonRectangle.Contains(GetNonClientPoint(CInt(m.LParam))) Then
                    TitleBarButtonState = ButtonState.Pressed
                    DrawButton(TitleBarButtonState)
                    TitleBarMouseIsDown = True
                Else
                    'process the message it was clicked somewhere in the non client
                    'area but not in the button.
                    MyBase.WndProc(m)
                End If


            Case WM_NCLBUTTONUP
                'Mouse is being released in the non client area

                If TitleBarMouseIsDown AndAlso TitleBarButtonRectangle.Contains(GetNonClientPoint(CInt(m.LParam))) Then
                    'The mouse was down and the mouse is in the button.
                    'It has been pressed.
                    TitleBarButtonState = ButtonState.Hot
                    DrawButton(TitleBarButtonState)
                    MsgBox("You clicked the button on the title bar.")

                Else
                    'Process the message and reset the button to normal if its not already.
                    MyBase.WndProc(m)

                    If TitleBarButtonState <> ButtonState.Normal Then
                        TitleBarButtonState = ButtonState.Normal
                        DrawButton(TitleBarButtonState)
                    End If

                End If

                'Reset that the mouse is down
                TitleBarMouseIsDown = False

            Case WM_NCLBUTTONDBLCLK
                'Mouse has been double clicked in the non client area.

                'If the cursor is in the button then don't process the double click
                'If processed the form will change window states.
                If Not TitleBarButtonRectangle.Contains(GetNonClientPoint(CInt(m.LParam))) Then
                    MyBase.WndProc(m)
                End If

            Case Else

                'Process the regular messages
                MyBase.WndProc(m)

        End Select

    End Sub

    Private Function GetNonClientPoint(ByVal lParam As Integer) As Point
        'The lo word in the lparam is the x coordinate and the hi word is the y.
        'The coordinates are in screen coordinates so subtract the location of the
        'form to get the location on the title bar.  This will have to be adjusted.
        'There will be issues on mdi forms.
        Dim ScreenPoint As New Point(CInt(lParam And Short.MaxValue), CInt(lParam >> 16))
        Return ScreenPoint - CType(Me.Location, Size)
    End Function

    Private Sub DrawButton(ByVal buttonState As ButtonState)
        'Gets the graphics to the entire window.
        'Draws a visual style button.
        'Draw your own graphics here.
        'If using the visual style renderer then you will need
        'any alternate drawing mode in case the renderer is not
        'supported.  ControlPaint will draw a button without 
        'visual styles.

        Dim EntireWindowGraphics As Graphics = Graphics.FromHdc(GetWindowDC(Me.Handle))

        Dim StrFrmt As New StringFormat
        StrFrmt.LineAlignment = StringAlignment.Center
        StrFrmt.Alignment = StringAlignment.Center
        StrFrmt.FormatFlags = StringFormatFlags.NoWrap
        StrFrmt.Trimming = StringTrimming.EllipsisCharacter

        Select Case buttonState
            Case Form1.ButtonState.Normal
                If VisualStyles.VisualStyleRenderer.IsSupported Then
                    Dim VisualRenderer As New VisualStyles.VisualStyleRenderer(VisualStyles.VisualStyleElement.Button.PushButton.Normal)
                    VisualRenderer.DrawBackground(EntireWindowGraphics, TitleBarButtonRectangle)
                Else
                    ControlPaint.DrawButton(EntireWindowGraphics, TitleBarButtonRectangle, Windows.Forms.ButtonState.Normal)
                End If

            Case Form1.ButtonState.Hot
                If VisualStyles.VisualStyleRenderer.IsSupported Then
                    Dim VisualRenderer As New VisualStyles.VisualStyleRenderer(VisualStyles.VisualStyleElement.Button.PushButton.Hot)
                    VisualRenderer.DrawBackground(EntireWindowGraphics, TitleBarButtonRectangle)
                Else
                    ControlPaint.DrawButton(EntireWindowGraphics, TitleBarButtonRectangle, Windows.Forms.ButtonState.Normal)
                End If

            Case Form1.ButtonState.Pressed
                If VisualStyles.VisualStyleRenderer.IsSupported Then
                    Dim VisualRenderer As New VisualStyles.VisualStyleRenderer(VisualStyles.VisualStyleElement.Button.PushButton.Pressed)
                    VisualRenderer.DrawBackground(EntireWindowGraphics, TitleBarButtonRectangle)
                Else
                    ControlPaint.DrawButton(EntireWindowGraphics, TitleBarButtonRectangle, Windows.Forms.ButtonState.Pushed)
                End If

        End Select

        EntireWindowGraphics.TextRenderingHint = Drawing.Text.TextRenderingHint.ClearTypeGridFit
        EntireWindowGraphics.DrawString("Click Me", Me.Font, Brushes.Black, TitleBarButtonRectangle, StrFrmt)
        EntireWindowGraphics.Dispose()
        StrFrmt.Dispose()
    End Sub

    Private Sub SizeButton()
        'This is hard coded for a sizable 3d window border.
        'Other properties of the systemInformation class can
        'adjust for fixed and single borders.
        'SystemInformation.BorderSize
        'SystemInformation.FixedFrameBorderSize

        'if the window is maximized then its sizing border will not be
        'displayed so the y is set to the bordersize and the height of the button
        'is set to the caption height.  If its not maximized the y is set to
        '0 and the button height is set to the caption height plus the border size.
        If Me.WindowState = FormWindowState.Normal Then
            TitleBarButtonRectangle.Y = 0
            TitleBarButtonRectangle.Height = SystemInformation.CaptionHeight + SystemInformation.HorizontalResizeBorderThickness
        Else
            TitleBarButtonRectangle.Y = SystemInformation.HorizontalResizeBorderThickness
            TitleBarButtonRectangle.Height = SystemInformation.CaptionHeight
        End If
    End Sub

    Private Sub Form1_SizeChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.SizeChanged
        'Change the size of the button.
        'May have been maximized or normalized
        SizeButton()
    End Sub

    'Gets the graphics to the entire window.
    <DllImport("user32.dll")> _
    Public Shared Function GetWindowDC(ByVal hWnd As IntPtr) As IntPtr
    End Function

End Class

Edited 5 Years Ago by Unhnd_Exception: n/a

Very strange result with the code. It appears to be exactly what I need, but - the button itself is being clipped to the area of the client window, so that just the bottom edge of the button is showing at the top of the client area. Or maybe the titlebar is being draw after/on top of the button? The button itself is functional.

The strange part is the very first time I ran it, this didn't happen. I swear I saw the whole button draw properly in the titlebar, although as implied above, it's a little wider than the title bar so the bottom part of the button spilled over into the client region. So then I started to work with the example to meet my specific requirements and since then I get only the behavior described in the first paragraph.

Any ideas or suggestions? Thanks!

This article has been dead for over six months. Start a new discussion instead.