Introduction
Hi all,
Before you begin, first I
wish to apologize profusely. This happens because my English is very bad,
that's why I wrote this article using google translator. Once again I say
apologize profusely.
This is my first time
writing an article. So, when things go wrong, please be informed where lies the
fault.
I have long been studying and using Visual
Basic, starting from version 5. And on this occasion, I would like to share
about GDI +. For me, when I know GDI +. I am really amazed he made. Known, this
occurs because the Visual Basic 5 and Visual Basic 6 does not know him. And a
still more remarkable is, you can test the accuracy of the mouse cursor when
you click on an area. If you have MSDN, you can learn it by opening a page How
to: Use Hit Testing with a Region. After reading the article, it suddenly
occurred to me, and my heart said, wait a second, this is basically making a control.
Let's begin
After run Visual Basic. Make a project of type
Windows Application. And after that name them GDIPP01. GDIPP01 is an extension
of GDI + Project 1. Only an acronym's after all. Once the project is made, then
you will find the file Form1.vb. At this time you do not need to change its
name. After that create a new file with type of Code File, and you do not need
to change its name. So by default the file will be named CodeFile1.vb.
Before starting, I will explain in outline what will be
done later, starting from:
MyPath
is a module. This module serves to manipulate the path and the region.
MyColor
is a module of type component classes. This component will be used to
manipulate color. Where the outcome can be either Color or Brush.
MyButton is a class module that component type. This component which
will make a fake button on the Form1.vb
Notes: MyPath, MyColor and
MyButton will be created in one class only, which is CodeFile1.vb.
And now, go into code view window owned
CodeFile1.vb file. And after that type the following code:
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
Up here, You have finished making MyPath
Module. And now we will make MyColor Class. Here's what you should type:
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
Up here yo have finished making MyColor Class. Next we will make MyButton Class. Here's what you should type:
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
Up here yo have finished making MyButton Class. Immediately you build your project. Later, if
successful you will find two new components in the toolbox window, illustrated
more or less like the following:
After that, you drag a window MyButton component to
design view owned Form1.vb. After that, this is what happened:
At this time, MyButton component has been created. And
now look at the properties window. This is all property owned by MyButton:
And now, let's remove the existing MyButton1 components
in Form1.vb. This is done because I prefer to design a code via the code window
than the design view window. After that, let's go into the code window owned by
Form1.vb, and type the following code:
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
When finished typing the code listed above, we just run
the program. Later, more or less looks like the following:
And now, you can test all the buttons. And also you can
change the value of property owned by each of the buttons. To do so, you just
need to click the combobox which available, more or less like this
illustration:
After that click on the items available. For example, I
change some property values owned by vButtonNormal as follows:
Property
|
Value
|
Rounded
|
30
|
LayoutHeight
|
100
|
LayoutLeft
|
120
|
MatrixRotate
|
10
|
MatrixShearY
|
0.5
|
StringFont
-> Size
|
12
|
And the results are more or less like the following:
Points of Interest
Interesting is not it. When the control is normally not
able to do things like that. Precisely control which fake, in this case
MyButton, could do such a thing. Until this is my first article this time. If
anyone wants to ask, you can send an email to wahyu.pratama@hotmail.com.
History
Keep a running update of any changes or improvements you've
made here.