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
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
If you mean winforms, I can think of two ways to do this:
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.