Adding a custom button in title bar VB.NET

后端 未结 3 1960
情书的邮戳
情书的邮戳 2021-01-07 04:45

I was just wondering if there was a possible way to add a custom button into the title bar using VB.NET. I\'ve seen many such questions on Stack Overflow but failed to get a

相关标签:
3条回答
  • 2021-01-07 05:21

    As Matthew Scharley writes in his answer here:

    The following will work in XP, I have no Vista machine handy to test it, but I think you're issues are steming from an incorrect hWnd somehow. Anyway, on with the poorly commented code.

    I think this doesn't show up graphically in Vista and 7. The translated version of Matthew's code is as follows:

    ' The state of our little button
    Private _buttState As ButtonState = ButtonState.Normal
    Private _buttPosition As New Rectangle()
    
    <DllImport("user32.dll")> _
    Private Shared Function GetWindowDC(hWnd As IntPtr) As IntPtr
    End Function
    <DllImport("user32.dll")> _
    Private Shared Function GetWindowRect(hWnd As IntPtr, ByRef lpRect As Rectangle) As Integer
    End Function
    <DllImport("user32.dll")> _
    Private Shared Function ReleaseDC(hWnd As IntPtr, hDC As IntPtr) As Integer
    End Function
    Protected Overrides Sub WndProc(ByRef m As Message)
        Dim x As Integer, y As Integer
        Dim windowRect As New Rectangle()
        GetWindowRect(m.HWnd, windowRect)
    
        Select Case m.Msg
            ' WM_NCPAINT
            ' WM_PAINT
            Case &H85, &Ha
                MyBase.WndProc(m)
    
                DrawButton(m.HWnd)
    
                m.Result = IntPtr.Zero
    
                Exit Select
    
            ' WM_ACTIVATE
            Case &H86
                MyBase.WndProc(m)
                DrawButton(m.HWnd)
    
                Exit Select
    
            ' WM_NCMOUSEMOVE
            Case &Ha0
                ' Extract the least significant 16 bits
                x = (CInt(m.LParam) << 16) >> 16
                ' Extract the most significant 16 bits
                y = CInt(m.LParam) >> 16
    
                x -= windowRect.Left
                y -= windowRect.Top
    
                MyBase.WndProc(m)
    
                If Not _buttPosition.Contains(New Point(x, y)) AndAlso _buttState = ButtonState.Pushed Then
                    _buttState = ButtonState.Normal
                    DrawButton(m.HWnd)
                End If
    
                Exit Select
    
            ' WM_NCLBUTTONDOWN
            Case &Ha1
                ' Extract the least significant 16 bits
                x = (CInt(m.LParam) << 16) >> 16
                ' Extract the most significant 16 bits
                y = CInt(m.LParam) >> 16
    
                x -= windowRect.Left
                y -= windowRect.Top
    
                If _buttPosition.Contains(New Point(x, y)) Then
                    _buttState = ButtonState.Pushed
                    DrawButton(m.HWnd)
                Else
                    MyBase.WndProc(m)
                End If
    
                Exit Select
    
            ' WM_NCLBUTTONUP
            Case &Ha2
                ' Extract the least significant 16 bits
                x = (CInt(m.LParam) << 16) >> 16
                ' Extract the most significant 16 bits
                y = CInt(m.LParam) >> 16
    
                x -= windowRect.Left
                y -= windowRect.Top
    
                If _buttPosition.Contains(New Point(x, y)) AndAlso _buttState = ButtonState.Pushed Then
                    _buttState = ButtonState.Normal
                    ' [[TODO]]: Fire a click event for your button 
                    '           however you want to do it.
                    DrawButton(m.HWnd)
                Else
                    MyBase.WndProc(m)
                End If
    
                Exit Select
    
            ' WM_NCHITTEST
            Case &H84
                ' Extract the least significant 16 bits
                x = (CInt(m.LParam) << 16) >> 16
                ' Extract the most significant 16 bits
                y = CInt(m.LParam) >> 16
    
                x -= windowRect.Left
                y -= windowRect.Top
    
                If _buttPosition.Contains(New Point(x, y)) Then
                    m.Result = DirectCast(18, IntPtr)
                Else
                    ' HTBORDER
                    MyBase.WndProc(m)
                End If
    
                Exit Select
            Case Else
    
                MyBase.WndProc(m)
                Exit Select
        End Select
    End Sub
    
    Private Sub DrawButton(hwnd As IntPtr)
        Dim hDC As IntPtr = GetWindowDC(hwnd)
        Dim x As Integer, y As Integer
    
        Using g As Graphics = Graphics.FromHdc(hDC)
            ' Work out size and positioning
            Dim CaptionHeight As Integer = Bounds.Height - ClientRectangle.Height
            Dim ButtonSize As Size = SystemInformation.CaptionButtonSize
            x = Bounds.Width - 4 * ButtonSize.Width
            y = (CaptionHeight - ButtonSize.Height) \ 2
            _buttPosition.Location = New Point(x, y)
    
            ' Work out color
            Dim color As Brush
            If _buttState = ButtonState.Pushed Then
                color = Brushes.LightGreen
            Else
                color = Brushes.Red
            End If
    
            ' Draw our "button"
            g.FillRectangle(color, x, y, ButtonSize.Width, ButtonSize.Height)
        End Using
    
        ReleaseDC(hwnd, hDC)
    End Sub
    
    Private Sub Form1_Load(sender As Object, e As EventArgs)
        _buttPosition.Size = SystemInformation.CaptionButtonSize
    End Sub
    
    0 讨论(0)
  • 2021-01-07 05:33

    If you mean winforms, I can think of two ways to do this:

    • Hide the titlebar and replace it with your own, which I don't recommend.
    • Build the button as a very small form that you keep docked in the correct position every time your window moves.
    0 讨论(0)
  • 2021-01-07 05:37

    Here is an example with some working code:

    http://www.dreamincode.net/forums/topic/69215-2008-custom-title-bar/

    Basically, you need to create a form with no border, then roll your own "Titlebar" which will basically be an area at the top that you can customize however you want. This is a difficult solution to fully implement properly, but it is probably the way that will best accomplish this.

    0 讨论(0)
提交回复
热议问题