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 sure-shot and a working answer.
Can anyone help me around with this issue? I've checked on Google and other website too but it fails to render. I want the code to work on Windows XP, Windows Vista and Windows 7.
I would be grateful if you will be able to give a working code and the button must even be able to accept click events and post it to the form it is on for some action.
Thanks in advance
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.
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
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.
来源:https://stackoverflow.com/questions/6172470/adding-a-custom-button-in-title-bar-vb-net