如何在表单顶部栏上放置一个按钮

时间:2014-09-12 16:27:22

标签: vb.net winforms gdi+ vb.net-2010

使用VB.Net 2012

我想在控制框左侧和标题右侧的窗体上添加一个命令按钮。这可能吗?

我没有通过“标准”看到这样做的方法。 windows意味着可能还有一些更高级的GDI技巧?

我打算添加一张我想要完成的图片,但显然我的声望太低而不能张贴图片,我会尝试一张ascii图片,请用你的想象力!

  ________________________________________________________
  |Q Windows Title          [New BUTTON]      [ _ O  X ] |
  |______________________________________________________|
  |                                                      |
  | Normal windows area                                  |

1 个答案:

答案 0 :(得分:0)

它有一些工作但可以完成。创建一个新类 APIHelp

Imports System.Runtime.InteropServices

Public Class APIHelp

    Public Const WS_EX_LAYERED As Int32 = 524288
    'Public Const HTCAPTION As Int32 = 2
    'Public Const WM_NCHITTEST As Int32 = 132
    Public Const ULW_ALPHA As Int32 = 2
    Public Const AC_SRC_OVER As Byte = 0
    Public Const AC_SRC_ALPHA As Byte = 1

    Public Enum Bool
        [False] = 0
        [True] = 1
    End Enum

    <StructLayout(LayoutKind.Sequential)> _
    Public Structure Point
        Public x As Int32
        Public y As Int32

        Public Sub New(ByVal x As Int32, ByVal y As Int32)
            Me.x = x
            Me.y = y
        End Sub
    End Structure

    <StructLayout(LayoutKind.Sequential)> _
    Public Structure Size
        Public cx As Int32
        Public cy As Int32

        Public Sub New(ByVal cx As Int32, ByVal cy As Int32)
            Me.cx = cx
            Me.cy = cy
        End Sub
    End Structure

    <StructLayout(LayoutKind.Sequential, Pack:=1)> _
    Private Structure ARGB
        Public Blue As Byte
        Public Green As Byte
        Public Red As Byte
        Public Alpha As Byte
    End Structure

    <StructLayout(LayoutKind.Sequential, Pack:=1)> _
    Public Structure BLENDFUNCTION
        Public BlendOp As Byte
        Public BlendFlags As Byte
        Public SourceConstantAlpha As Byte
        Public AlphaFormat As Byte
    End Structure

    Public Declare Auto Function UpdateLayeredWindow Lib "user32.dll" (ByVal hwnd As IntPtr, ByVal hdcDst As IntPtr, ByRef pptDst As Point, ByRef psize As Size, ByVal hdcSrc As IntPtr, ByRef pprSrc As Point, _
                      ByVal crKey As Int32, ByRef pblend As BLENDFUNCTION, ByVal dwFlags As Int32) As Bool

    Public Declare Auto Function CreateCompatibleDC Lib "gdi32.dll" (ByVal hDC As IntPtr) As IntPtr

    Public Declare Auto Function GetDC Lib "user32.dll" (ByVal hWnd As IntPtr) As IntPtr

    <DllImport("user32.dll", ExactSpelling:=True)> _
    Public Shared Function ReleaseDC(ByVal hWnd As IntPtr, ByVal hDC As IntPtr) As Integer
    End Function

    Public Declare Auto Function DeleteDC Lib "gdi32.dll" (ByVal hdc As IntPtr) As Bool

    <DllImport("gdi32.dll", ExactSpelling:=True)> _
    Public Shared Function SelectObject(ByVal hDC As IntPtr, ByVal hObject As IntPtr) As IntPtr
    End Function
    Public Declare Auto Function DeleteObject Lib "gdi32.dll" (ByVal hObject As IntPtr) As Bool

End Class

添加新表单,例如 Form2 。设置 TopMost = False FormBorderStyle =无 ShowInTaskbar = False 。此表单将是您的按钮。因为我们想要透明地绘制我们设置 WS_EX_LAYERED 样式并且我们绘制 使用 UpdateLayeredWindow 功能。您无法直接在具有 WS_EX_LAYERED 样式的表单上绘图。 您必须使用设备上下文,在其中绘制然后调用 UpdateLayeredWindow

Public Class Form2

Private sourceLocation As New APIHelp.Point(0, 0)
Private newSize As New APIHelp.Size(...., .....)
Private newLocation As APIHelp.Point
Private blend As New APIHelp.BLENDFUNCTION()
Private memDcNormal, memDcEnter, memDcDown, screenDc, hBmpNormal, hBmpNormalOld, _
        hBmpEnter, hBmpEnterOld, hBmpDown, hBmpDownOld As IntPtr

Private Sub Form2_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
    Me.Location = New Point(Form1.Location.X + ..., Form1.Location.Y + ...) 'complete the dots
    Me.Size = New Size(..., ...) 'size of button

    Initialize()

End Sub

Private Sub Initialize()
    ' Only works with a 32bpp bitmap
    blend.BlendOp = APIHelp.AC_SRC_OVER
    ' Always 0
    blend.BlendFlags = 0
    ' Set to 255 for per-pixel alpha values
    blend.SourceConstantAlpha = 255
    ' Only works when the bitmap contains an alpha channel
    blend.AlphaFormat = APIHelp.AC_SRC_ALPHA

    screenDc = APIHelp.GetDC(IntPtr.Zero)

    Using bmp As Bitmap = CType(Bitmap.FromFile(".....Normal.png"), Bitmap)
        memDcNormal = IntPtr.Zero
        memDcNormal = APIHelp.CreateCompatibleDC(screenDc)
        hBmpNormal = bmp.GetHbitmap(Color.FromArgb(0))
        hBmpNormalOld = APIHelp.SelectObject(memDcNormal, hBmpNormal)
    End Using

    Using bmp As Bitmap = CType(Bitmap.FromFile("......Enter.png"), Bitmap)
        memDcEnter = IntPtr.Zero
        memDcEnter = APIHelp.CreateCompatibleDC(screenDc)
        hBmpEnter = bmp.GetHbitmap(Color.FromArgb(0))
        hBmpEnterOld = APIHelp.SelectObject(memDcEnter, hBmpEnter)
    End Using

    Using bmp As Bitmap = CType(Bitmap.FromFile("......Down.png"), Bitmap)
        memDcDown = IntPtr.Zero
        memDcDown = APIHelp.CreateCompatibleDC(screenDc)
        hBmpDown= bmp.GetHbitmap(Color.FromArgb(0))
        hBmpDownOld = APIHelp.SelectObject(memDcDown, hBmpDown)
    End Using

    APIHelp.DeleteDC(screenDc)
End Sub


Protected Overloads Overrides ReadOnly Property CreateParams() As CreateParams
    Get
        'Add the layered extended style (WS_EX_LAYERED) to this window
        Dim createParam As CreateParams = MyBase.CreateParams
        createParam.ExStyle = createParam.ExStyle Or 524288 'WS_EX_LAYERED
        Return createParam
    End Get
End Property


Private Sub Form2_MouseDown(sender As System.Object, e As System.Windows.Forms.MouseEventArgs) Handles MyBase.MouseDown
    newLocation = New APIHelp.Point(Me.Location.X, Me.Location.Y)

    APIHelp.UpdateLayeredWindow(Handle, IntPtr.Zero, newLocation, newSize, memDcDown, sourceLocation, _
                                0, blend, APIHelp.ULW_ALPHA)
End Sub

Private Sub Form2_MouseEnter(sender As System.Object, e As System.EventArgs) Handles MyBase.MouseEnter
    newLocation = New APIHelp.Point(Me.Location.X, Me.Location.Y)

    APIHelp.UpdateLayeredWindow(Handle, IntPtr.Zero, newLocation, newSize, memDcEnter, sourceLocation, _
                                0, blend, APIHelp.ULW_ALPHA)
End Sub

Private Sub Form2_MouseMove(sender As System.Object, e As System.Windows.Forms.MouseEventArgs) Handles MyBase.MouseMove
    Static i As Integer = 1
    Static j As Integer = 1

    If e.Button = Windows.Forms.MouseButtons.Left Then
        If e.X < 0 Or e.X > Me.Width Or e.Y < 0 Or e.Y > Me.Height Then
            If i = 1 Then
                newLocation = New APIHelp.Point(Me.Location.X, Me.Location.Y)

                APIHelp.UpdateLayeredWindow(Handle, IntPtr.Zero, newLocation, newSize, memDcNormal, sourceLocation, _
                                            0, blend, APIHelp.ULW_ALPHA)
                i = 0
                j = 1
            End If
        Else
            If j = 1 Then
                newLocation = New APIHelp.Point(Me.Location.X, Me.Location.Y)

                APIHelp.UpdateLayeredWindow(Handle, IntPtr.Zero, newLocation, newSize, memDcDown, sourceLocation, _
                                            0, blend, APIHelp.ULW_ALPHA)
                j = 0
                i = 1
            End If
        End If
    End If
End Sub

Private Sub Form2_MouseLeave(sender As System.Object, e As System.EventArgs) Handles MyBase.MouseLeave
    newLocation = New APIHelp.Point(Me.Location.X, Me.Location.Y)

    APIHelp.UpdateLayeredWindow(Handle, IntPtr.Zero, newLocation, newSize, memDcNormal, sourceLocation, _
                                0, blend, APIHelp.ULW_ALPHA)
End Sub

Private Sub Form2_MouseClick(sender As System.Object, e As System.Windows.Forms.MouseEventArgs) Handles MyBase.MouseClick
    newLocation = New APIHelp.Point(Me.Location.X, Me.Location.Y)

    APIHelp.UpdateLayeredWindow(Handle, IntPtr.Zero, newLocation, newSize, memDcEnter, sourceLocation, _
                                0, blend, APIHelp.ULW_ALPHA)

    'Do your staff

End Sub

Private Sub Form2_FormClosing(sender As System.Object, e As System.Windows.Forms.FormClosingEventArgs) Handles MyBase.FormClosing
    APIHelp.SelectObject(memDcNormal, hBmpNormalOld)
    APIHelp.DeleteObject(hBmpNormal)
    APIHelp.DeleteDC(memDcNormal)

    APIHelp.SelectObject(memDcEnter, hBmpEnterOld)
    APIHelp.DeleteObject(hBmpEnter)
    APIHelp.DeleteDC(memDcEnter)

    APIHelp.SelectObject(memDcDown, hBmpDownOld)
    APIHelp.DeleteObject(hBmpDown)
    APIHelp.DeleteDC(memDcDown)
End Sub

End Class

从上面的代码中可以看出,按钮的每个状态都需要三个png图像。

初始形式:

Private Sub Form1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load

    Form2.Show(Me)
End Sub

Private Sub Form1_Move(sender As System.Object, e As System.EventArgs) Handles MyBase.Move
    Form2.Location = New Point(Me.Location.X + ..., Me.Location.Y + ...)
End Sub

瓦尔特