65.9K
CodeProject 正在变化。 阅读更多。
Home

我的假按钮 第一部分

starIconstarIconstarIconstarIconemptyStarIcon

4.00/5 (2投票s)

2012年1月27日

CPOL

3分钟阅读

viewsIcon

14770

downloadIcon

272

如何使用 GDI+ 制作一个假按钮。

引言

大家好,

在开始之前,首先我想深表歉意。这是因为我的英语很差,所以我使用谷歌翻译写了这篇文章。再次深表歉意。

这是我第一次写文章。所以,如果出现问题,请指正错误之处。

我一直在学习和使用 Visual Basic,从版本 5 开始。借此机会,我想分享一下关于 GDI + 的知识。对我来说,当我了解 GDI + 时。我真的很惊讶。众所周知,发生这种情况是因为 Visual Basic 5 和 Visual Basic 6 不了解它。更值得注意的是,您可以测试鼠标光标在单击区域时的准确性。如果您有 MSDN,您可以通过打开页面 How to: Use Hit Testing with a Region 来学习它。阅读完这篇文章后,我突然想到,我的心里说,等等,这基本上是在制作一个控件。

开始吧

运行 Visual Basic 后。创建一个 Windows 应用程序类型的项目。之后将其命名为 GDIPP01。 GDIPP01 是 GDI + Project 1 的扩展。只是一个首字母缩写词。一旦项目制作完成,您将找到文件 Form1.vb。此时您不需要更改其名称。之后创建一个新的代码文件类型的文件,您也不需要更改其名称。因此,默认情况下,该文件将被命名为 CodeFile1.vb。

在开始之前,我将概述稍后将要完成的事情,从

  • MyPath。

MyPath 是一个模块。此模块用于操作路径和区域。

  • MyColor。

MyColor 是组件类类型的模块。此组件将用于操作颜色。结果可以是 Color 或 Brush。

  • MyButton。

MyButton 是组件类型的类模块。此组件将在 Form1.vb 上创建一个假按钮

注意:MyPath、MyColor 和 MyButton 将仅在一个类中创建,即 CodeFile1.vb。

现在,进入 CodeFile1.vb 文件拥有的代码视图窗口。之后键入以下代码

Imports System.ComponentModel

Public Module MyPath
    Dim vPath As New Drawing2D.GraphicsPath
    Function GetRoundedRectangle(ByVal Size As SizeF, _
               ByVal Rounded As Single) As Drawing2D.GraphicsPath
        vPath.Dispose()
        vPath = New Drawing2D.GraphicsPath

        Dim r1 As New Rectangle(0, 0, Rounded * 2, Rounded * 2)
        Dim r2 As New Rectangle(Size.Width - r1.Width, 0, r1.Width, r1.Height)
        Dim r3 As New Rectangle(r2.X, Size.Height - r1.Height, r1.Width, r1.Height)
        Dim r4 As New Rectangle(r1.X, r3.Y, r1.Width, r1.Height)

        Dim l1() As PointF = {New PointF(Rounded, 0), New PointF(Size.Width - Rounded, 0)}
        Dim l2() As PointF = {New PointF(Size.Width, Rounded), New PointF(Size.Width, Size.Height - Rounded)}
        Dim l3() As PointF = {New PointF(Size.Width - Rounded, Size.Height), New PointF(Rounded, Size.Height)}
        Dim l4() As PointF = {New PointF(0, Size.Height - Rounded), New PointF(0, Rounded)}

        vPath.AddArc(r1, -180, 90)
        vPath.AddLines(l1)
        vPath.AddArc(r2, -90, 90)
        vPath.AddLines(l2)
        vPath.AddArc(r3, 0, 90)
        vPath.AddLines(l3)
        vPath.AddArc(r4, 90, 90)
        vPath.AddLines(l4)

        Return vPath
    End Function
End Module

到这里,您已经完成了 MyPath 模块的制作。现在我们将制作 MyColor 类。以下是您应该键入的内容

Public Class MyColor
    Inherits Component

    Dim vColor As Color = Drawing.Color.White
    Dim vTransBool As Boolean = False
    Dim vTransInt As Integer = 255
    Event ColorChanged(ByVal o As Object)
    Property Color() As Color
        Get
            Return vColor
        End Get
        Set(ByVal value As Color)
            vColor = value
            RaiseEvent ColorChanged(Me)
        End Set
    End Property
    Property CanTransparent() As Boolean
        Get
            Return vTransBool
        End Get
        Set(ByVal value As Boolean)
            vTransBool = value
            RaiseEvent ColorChanged(Me)
        End Set
    End Property
    Property TransparentValue() As Integer
        Get
            Return vTransInt
        End Get
        Set(ByVal value As Integer)
            vTransInt = value
            RaiseEvent ColorChanged(Me)
        End Set
    End Property
    Function GetColor() As Color
        With Me
            If .vTransBool = True Then
                Return Drawing.Color.FromArgb(.vTransInt, .vColor)
            Else
                Return .vColor
            End If
        End With
    End Function
    Function GetBrush() As Brush
        Return New SolidBrush(Me.GetColor)
    End Function

    Sub New()
        MyBase.New()
    End Sub
    Sub New(ByVal Color As Color, Optional ByVal CanTransparent As _
            Boolean = False, Optional ByVal TransparentValue As Integer = 255)
        MyBase.New()
        With Me
            .Color = Color
            .CanTransparent = CanTransparent
            .TransparentValue = TransparentValue
        End With
    End Sub
End Class

到这里,您已经完成了 MyColor 类的制作。接下来我们将制作 MyButton 类。以下是您应该键入的内容

Public Class MyButton
    Inherits Component

#Region "- Building Layout -"
    Dim vRect As New RectangleF(0, 0, 100, 30)
    Private Const CLayout As String = "Layout"
    <Category(CLayout)> _
    Property LayoutLeft() As Single
        Get
            Return vRect.X
        End Get
        Set(ByVal value As Single)
            vRect.X = value
        End Set
    End Property
    <Category(CLayout)> _
    Property LayoutTop() As Single
        Get
            Return vRect.Y
        End Get
        Set(ByVal value As Single)
            vRect.Y = value
        End Set
    End Property
    <Category(CLayout)> _
    Property LayoutWidth() As Single
        Get
            Return vRect.Width
        End Get
        Set(ByVal value As Single)
            vRect.Width = value
        End Set
    End Property
    <Category(CLayout)> _
    Property LayoutHeight() As Single
        Get
            Return vRect.Height
        End Get
        Set(ByVal value As Single)
            vRect.Height = value
        End Set
    End Property
    Function GetRectangle() As Rectangle
        Return New Rectangle(vRect.X, vRect.Y, vRect.Width, vRect.Height)
    End Function
    Function GetRectangleF() As RectangleF
        Return vRect
    End Function
#End Region

#Region "- Matrix -"
    Dim vScale As New PointF(1, 1)
    Dim vShear As New PointF
    Dim vRotate As Single
    Private Const CMatrix As String = "Matrix"
    <Category(CMatrix)> _
    Property MatrixRotate() As Single
        Get
            Return vRotate
        End Get
        Set(ByVal value As Single)
            vRotate = value
        End Set
    End Property
    <Category(CMatrix)> _
    Property MatrixScaleX() As Single
        Get
            Return vScale.X
        End Get
        Set(ByVal value As Single)
            vScale.X = value
        End Set
    End Property
    <Category(CMatrix)> _
    Property MatrixScaleY() As Single
        Get
            Return vScale.Y
        End Get
        Set(ByVal value As Single)
            vScale.Y = value
        End Set
    End Property
    <Category(CMatrix)> _
    Property MatrixShearX() As Single
        Get
            Return vShear.X
        End Get
        Set(ByVal value As Single)
            vShear.X = value
        End Set
    End Property
    <Category(CMatrix)> _
    Property MatrixShearY() As Single
        Get
            Return vShear.Y
        End Get
        Set(ByVal value As Single)
            vShear.Y = value
        End Set
    End Property
#End Region

#Region "- Font & String Format -"
    Dim vFont As New Font("tahoma", 8)
    Dim vFormat As New StringFormat
    Dim vStr As String = "My Button"
    Dim WithEvents vStrColor As New MyColor(Color.Yellow)
    Private Const CFont As String = "Writing Styles"
    <Category(CFont)> _
    Property StringFont() As Font
        Get
            Return vFont
        End Get
        Set(ByVal value As Font)
            vFont = value
        End Set
    End Property
    <Category(CFont)> _
    Property StringVerticalAlingment() As StringAlignment
        Get
            Return vFormat.Alignment
        End Get
        Set(ByVal value As StringAlignment)
            vFormat.Alignment = value
        End Set
    End Property
    <Category(CFont)> _
    Property StringHorizontalAlingment() As StringAlignment
        Get
            Return vFormat.LineAlignment
        End Get
        Set(ByVal value As StringAlignment)
            vFormat.LineAlignment = value
        End Set
    End Property
    <Category(CFont)> _
    Property StringTrimming() As StringTrimming
        Get
            Return vFormat.Trimming
        End Get
        Set(ByVal value As StringTrimming)
            vFormat.Trimming = value
        End Set
    End Property
    <Category(CFont)> _
    Property StringFormatFlags() As StringFormatFlags
        Get
            Return vFormat.FormatFlags
        End Get
        Set(ByVal value As StringFormatFlags)
            vFormat.FormatFlags = value
        End Set
    End Property
    <Category(CFont)> _
    Property StringText() As String
        Get
            Return vStr
        End Get
        Set(ByVal value As String)
            vStr = value
        End Set
    End Property
    <Category(CFont)> _
    ReadOnly Property StringColor() As MyColor
        Get
            Return vStrColor
        End Get
    End Property
#End Region

#Region "- Gradient -"
    Dim WithEvents vColor1 As New MyColor(Color.Red), vColor2 As New MyColor(Color.Blue)
    Dim vColorRotate As Single
    Dim vGamma As Boolean = False
    Private Const CBackcolor As String = "Background Color"
    <Category(CBackcolor)> _
    ReadOnly Property GradientColor1() As MyColor
        Get
            Return vColor1
        End Get
    End Property
    <Category(CBackcolor)> _
    ReadOnly Property GradientColor2() As MyColor
        Get
            Return vColor2
        End Get
    End Property
    <Category(CBackcolor)> _
    Property GradientRotate() As Single
        Get
            Return vColorRotate
        End Get
        Set(ByVal value As Single)
            vColorRotate = value
        End Set
    End Property
    <Category(CBackcolor)> _
    Property GradientGamma() As Boolean
        Get
            Return vGamma
        End Get
        Set(ByVal value As Boolean)
            vGamma = value
        End Set
    End Property
#End Region

#Region "- Else -"
    Dim vRounded As Single = 10
    Private Const CElse As String = "Else"
    <Category(CElse)> _
    Property Rounded() As Single
        Get
            Return vRounded
        End Get
        Set(ByVal value As Single)
            vRounded = value
        End Set
    End Property
#End Region

    Dim vMousePress, vMouseFocus As Boolean
    Dim vMousePoint As New Point
    Private Function OnAreaTarget(ByVal p As Point) As Boolean
        With Me
            Try
                Using m1 As New Drawing2D.Matrix
                    m1.RotateAt(.vRotate, New PointF(.vRect.Width / 2, .vRect.Height / 2))
                    m1.Scale(.vScale.X, .vScale.Y)
                    m1.Shear(.vShear.X, .vShear.Y)
                    Using m2 As New Drawing2D.Matrix
                        m2.Translate(.vRect.X, .vRect.Y)
                        m2.Multiply(m1)
                        Using gp As New Drawing2D.GraphicsPath
                            gp.AddPath(MyPath.GetRoundedRectangle(.vRect.Size, .vRounded), False)
                            gp.Transform(m2)
                            Using Region As New Region(gp)
                                Return Region.IsVisible(p)
                            End Using
                        End Using
                    End Using
                End Using
            Catch ex As Exception
            End Try
        End With
    End Function

    Dim WithEvents vControl As New Control
    Event Click(ByVal o As Object)
    Event DoubleClick(ByVal o As Object)
    Sub BindingControl(ByVal c As Control)
        vControl = c
    End Sub
    Private Sub eColorChanged(ByVal o As Object) Handles _
                 vColor1.ColorChanged, vColor2.ColorChanged, vStrColor.ColorChanged
        Me.vControl.Invalidate()
    End Sub
    Private Sub ePaint(ByVal o As Object, ByVal e As PaintEventArgs) Handles vControl.Paint
        With Me
            Try
                Dim g As Graphics = e.Graphics

                Dim gc As Drawing2D.GraphicsContainer = g.BeginContainer

                g.CompositingQuality = Drawing2D.CompositingQuality.AssumeLinear
                g.PixelOffsetMode = Drawing2D.PixelOffsetMode.Half
                g.SmoothingMode = Drawing2D.SmoothingMode.AntiAlias
                g.TextRenderingHint = Drawing.Text.TextRenderingHint.AntiAlias

                Dim Path As New Drawing2D.GraphicsPath
                Path.AddPath(MyPath.GetRoundedRectangle(.vRect.Size, .vRounded), False)

                Using m1 As New Drawing2D.Matrix
                    m1.RotateAt(.vRotate, New PointF(.vRect.Width / 2, .vRect.Height / 2))
                    m1.Scale(.vScale.X, .vScale.Y)
                    m1.Shear(.vShear.X, .vShear.Y)
                    Using m2 As New Drawing2D.Matrix
                        m2.Translate(.vRect.X, .vRect.Y)
                        m2.Multiply(m1)
                        g.MultiplyTransform(m2)
                    End Using
                End Using

                Using lgb As New Drawing2D.LinearGradientBrush(New Rectangle(0, 0, _
                  .vRect.Width, .vRect.Height), .vColor1.GetColor, .vColor2.GetColor, .vColorRotate, True)
                    lgb.GammaCorrection = .vGamma
                    g.FillPath(lgb, Path)
                End Using

                If .vMouseFocus = True Then
                    Using Trans As New MyColor(Color.White, True, 50)
                        g.FillRectangle(Trans.GetBrush, New Rectangle(0, 0, _
                          .vRect.Width, IIf(.vMousePress, .vRect.Height / 2, .vRect.Height / 2.4)))
                    End Using
                End If

                g.DrawString(.vStr, .vFont, .vStrColor.GetBrush, _
                  New Rectangle(4, 4, .vRect.Width - 8, .vRect.Height - 8), .vFormat)

                If .vMouseFocus = True Then
                    g.DrawPath(New Pen(Color.Orange, IIf(.vMousePress, 4, 2)), Path)
                End If

                Path.Dispose()

                g.EndContainer(gc)
            Catch ex As Exception
            End Try
        End With
    End Sub
    Private Sub eMouseClick(ByVal o As Object, ByVal e As MouseEventArgs) Handles vControl.MouseClick
        If Me.OnAreaTarget(e.Location) = True Then
            RaiseEvent Click(Me)
        End If
    End Sub
    Private Sub eMouseDoubleClick(ByVal o As Object, _
      ByVal e As MouseEventArgs) Handles vControl.MouseDoubleClick
        If Me.OnAreaTarget(e.Location) = True Then
            RaiseEvent DoubleClick(Me)
        End If
    End Sub
    Private Sub eMouseDown(ByVal o As Object, ByVal e As MouseEventArgs) Handles vControl.MouseDown
        With Me
            Try
                If .OnAreaTarget(e.Location) = True Then
                    If .vMousePress = False Then
                        .vMousePress = True
                        .vControl.Invalidate()
                    Else
                        .vMousePress = True
                    End If
                End If
            Catch ex As Exception
            End Try
        End With
    End Sub
    Private Sub eMouseUp(ByVal o As Object, ByVal e As MouseEventArgs) Handles vControl.MouseUp
        With Me
            Try
                If .vMousePress = True Then
                    .vMousePress = False
                    .vControl.Invalidate()
                Else
                    .vMousePress = False
                End If
            Catch ex As Exception
            End Try
        End With
    End Sub
    Private Sub eMouseMove(ByVal o As Object, ByVal e As MouseEventArgs) Handles vControl.MouseMove
        With Me
            Try
                If .OnAreaTarget(e.Location) = True Then
                    If .vMouseFocus = False Then
                        .vMouseFocus = True
                        .vControl.Invalidate()
                    Else
                        .vMouseFocus = True
                    End If
                Else
                    If .vMouseFocus = True Then
                        .vMouseFocus = False
                        .vControl.Invalidate()
                    Else
                        .vMouseFocus = False
                    End If
                End If
            Catch ex As Exception
            End Try
        End With
    End Sub

    Sub New()
        MyBase.New()
        With Me
            Try
                With .vFormat
                    .Alignment = StringAlignment.Center
                    .LineAlignment = StringAlignment.Center
                    .FormatFlags = Drawing.StringFormatFlags.DisplayFormatControl
                    .Trimming = Drawing.StringTrimming.EllipsisCharacter
                End With
            Catch ex As Exception
            End Try
        End With
    End Sub
End Class

到这里,您已经完成了 MyButton 类的制作。立即构建您的项目。稍后,如果成功,您将在工具箱窗口中找到两个新组件,大致如下所示

之后,将一个 MyButton 组件拖到 Form1.vb 拥有的设计视图中。之后,会发生以下情况

此时,已创建 MyButton 组件。现在查看属性窗口。这是 MyButton 拥有的所有属性

现在,让我们删除 Form1.vb 中现有的 MyButton1 组件。这样做是因为我更喜欢通过代码窗口而不是设计视图窗口来设计代码。之后,让我们进入 Form1.vb 拥有的代码窗口,并键入以下代码

Public Class Form1
    Dim WithEvents vComboBox As New ComboBox
    Dim WithEvents vButtonMin, vButtonMax, vButtonNormal, vButtonOut As New MyButton
    Dim WithEvents vPropGrid As New PropertyGrid
    Private Sub eLoad(ByVal o As System.Object, ByVal e As EventArgs) Handles MyBase.Load
        With Me
            Try
                .DoubleBuffered = True
                .ControlBox = False

                Dim ArrayString() As String = {"Minimum", "Maximum", "Normal", "Close"}
                .vComboBox.Items.AddRange(ArrayString)
                .vComboBox.DropDownStyle = ComboBoxStyle.DropDownList
                .vComboBox.Width = 200
                .vComboBox.SelectedIndex = 0

                Dim ArrayButton() As MyButton = {.vButtonMin, .vButtonMax, .vButtonNormal, .vButtonOut}
                For a As Integer = 0 To ArrayButton.Length - 1
                    ArrayButton(a).LayoutLeft = 10
                    If a = 0 Then
                        ArrayButton(a).LayoutTop = 10
                    Else
                        ArrayButton(a).LayoutTop = ArrayButton(a - 1).LayoutTop + ArrayButton(a - 1).LayoutHeight + 10
                    End If
                    ArrayButton(a).StringText = ArrayString(a)
                    ArrayButton(a).BindingControl(Me)
                Next

                .Controls.Add(.vComboBox)
                .Controls.Add(.vPropGrid)

                .Size = New Size(640, 480)
            Catch ex As Exception
            End Try
        End With
    End Sub
    Private Sub eResize(ByVal o As Object, ByVal e As EventArgs) Handles Me.Resize
        With Me
            Try
                .vComboBox.Location = New Point(.ClientSize.Width - .vComboBox.Width - 10, 10)

                .vPropGrid.Location = New Point(.vComboBox.Left, .vComboBox.Bottom + 10)
                .vPropGrid.Size = New Size(.vComboBox.Width, .ClientSize.Height - .vPropGrid.Top - 10)

                .Invalidate()
            Catch ex As Exception
            End Try
        End With
    End Sub
    Private Sub eComboBoxSelIndexChanged(ByVal o As Object, _
                      ByVal e As EventArgs) Handles vComboBox.SelectedIndexChanged
        With Me
            Try
                Dim ArrayButton() As MyButton = {.vButtonMin, .vButtonMax, .vButtonNormal, .vButtonOut}
                .vPropGrid.SelectedObject = ArrayButton(.vComboBox.SelectedIndex)
            Catch ex As Exception
            End Try
        End With
    End Sub
    Private Sub ePropValChanged(ByVal s As Object, ByVal e As _
      PropertyValueChangedEventArgs) Handles vPropGrid.PropertyValueChanged
        Me.Invalidate()
    End Sub
    Private Sub eMyButtonClick(ByVal o As Object) Handles vButtonMin.Click, _
                 vButtonMax.Click, vButtonNormal.Click, vButtonOut.Click
        With Me
            Try
                If o Is .vButtonMin Then
                    .WindowState = FormWindowState.Minimized
                End If

                If o Is .vButtonMax Then
                    .WindowState = FormWindowState.Maximized
                End If

                If o Is .vButtonNormal Then
                    .WindowState = FormWindowState.Normal
                End If

                If o Is .vButtonOut Then
                    .Close()
                End If
            Catch ex As Exception
            End Try
        End With
    End Sub
End Class

完成键入上面列出的代码后,我们只需运行该程序。稍后,看起来大致如下

现在,您可以测试所有按钮。您也可以更改每个按钮拥有的属性值。为此,您只需单击可用的组合框,大致如图所示

之后单击可用的项目。例如,我将 vButtonNormal 拥有的某些属性值更改如下

属性

圆角

30

布局高度

100

布局左侧

120

矩阵旋转

10

矩阵倾斜 Y

0.5

StringFont -> 大小

12

结果大致如下

关注点

是不是很有趣。当控件通常无法执行此类操作时。精确控制哪个是假的,在这种情况下,MyButton 可能会这样做。到此为止是我第一次写这篇文章。如果有人想问,您可以发送电子邮件至 wahyu.pratama@hotmail.com。

© . All rights reserved.