明輝手游網(wǎng)中心:是一個免費(fèi)提供流行視頻軟件教程、在線學(xué)習(xí)分享的學(xué)習(xí)平臺!

使用VB.NET開發(fā)定制控件

[摘要]正常情況下,在開發(fā).NET Windows應(yīng)用程序時,我們都會用到System.Windows.Forms名字空間的控件?晒┪覀兪褂玫目丶芏,從Label、TextBox等簡單的控件到Month...
正常情況下,在開發(fā).NET Windows應(yīng)用程序時,我們都會用到System.Windows.Forms名字空間的控件?晒┪覀兪褂玫目丶芏啵瑥腖abel、TextBox等簡單的控件到MonthCalendar、ColorDialog等功能更豐富、更復(fù)雜的控件。盡管這些控件對于我們需要開發(fā)的大多數(shù)Windows應(yīng)用程序已經(jīng)足夠好了,但有時我們也需要自己開發(fā)一些System.Windows.Forms名字空間不包括的控件。本篇文章將講述如何使用VB.NET創(chuàng)建定制控件,尤其是在需要提供自己的圖形用戶接口時。
開發(fā)定制的控件并不困難。在開發(fā)定制控件時,我們可以使用現(xiàn)有的控件,或者對Control或UserControl類進(jìn)行擴(kuò)展。結(jié)合使用現(xiàn)有的控件使我們減少提供接口的麻煩,擴(kuò)展Control或UserControl類意味著我們需要覆蓋OnPaint方法,自己繪制圖形用戶接口。本篇文章中,我們由UserControl類派生了一個定制控件,UserControl類本身也是由繼承Control類而生成的。因此讀者需要對這二個類有一定的了解。
Control類非常重要,因為它是Windows可視化組件的父類,我們開發(fā)的定制類將是Control類的一個子類。我們的定制類一般不會直接由Control類派生而成,相反,一般是對UserControl類進(jìn)行擴(kuò)展。
Control類
Control類提供向Windows應(yīng)用程序用戶顯示信息的類所要求的基本功能,它處理用戶通過鍵盤和鼠標(biāo)進(jìn)行的輸入,以及消息的分配和安全。更重要的是,Control類定義了控件的范圍(位置和大。,盡管它不實現(xiàn)控件的繪制。
Windows表單控件使用了環(huán)境屬性,因此其子控件的顯示與其周圍環(huán)境相似。缺省情況下,環(huán)境屬性是由其父控件獲得的,如果類沒有父控件或者其環(huán)境屬性沒有設(shè)置,則控件試圖通過Site屬性設(shè)置環(huán)境屬性的值。如果控件沒有確定位置,不支持環(huán)境屬性,或者AmbientProperties對象的屬性沒有設(shè)置,控件就會使用缺省值。一般情況下,控件的環(huán)境特性表示控件的一個特征,例如BackColor,它會傳遞給子控件。例如,缺省情況下,Button控件將具有與其父表單控件相同的BackColor環(huán)境屬性。
許多Control類的屬性、方法和事件都會不加變化地傳遞給子類。
Control類的屬性
下面是Control類的一些最重要的屬性
BackColor
控件的背景顏色,是由一個System.Drawing.Color對象表示的。我們可以使用如下所示的代碼將一個System.Drawing.Color對象賦給該屬性:
control.BackColor = System.Drawing.Color.Red

Enabled
一個表示該控件是否可用的布爾型值,缺省情況下其值為True。
Location
控件的左上角在其窗口中的位置,由一個System.Drawing.Point對象表示。
Name
控件的名字。
Parent
返回控件的父控件或容器的引用。例如,在一個表單中添加的控件的父控件就是該表單,下面的代碼將Button1控件所在的表單的標(biāo)題欄改為“Thank you.”:
Button1.Parent.Text = "Thank you."

Size
控件的大小,由System.Drawing.Size對象表示。
Text
與控件相關(guān)的字符串。例如,在Label控件中,Text屬性就是顯示在標(biāo)簽體上的字符串。
Control類的方法
下面是一些Control類最經(jīng)常使用的方法

BringToFront
如果該控件在其他一些控件下面,完整地顯示該控件。換一句話說,這一方法能夠顯示一個完整的控件。
CreateGraphics
獲取控件的System.Drawing.Graphics對象,我們可以在其上利用System.Drawing.Graphics類的各種方法進(jìn)行顯示。例如,下面的代碼獲取名字為Button1的控件的Graphics圖像,然后在按鈕上劃一條對角的綠線:
Imports System.Drawing

Dim graphics As Graphics = Button1.CreateGraphics
Dim pen As Pen = New Pen(Color.Green)
graphics.DrawLine(pen, 0, 0, _
Button1.Size.Width, Button1.Size.Height)
但是,用這種方法在控件上畫圖,所畫的圖像不是“永久”的。當(dāng)控件或者包含控件的表單被重畫時,用這種方式畫的圖像就會消失。
Focus
將焦點(diǎn)給予該控件,使它成為活動控件
Hide
將控件的Visible屬性設(shè)置為False,使它不被顯示出來。
GetNextControl
按Tab鍵控制次序返回下一個控件。
OnXXX
觸發(fā)XXX事件。這里的XXX可以是Click、ControlAdded、ControlRemoved、DoubleClick、DragDrop、DragEnter、DragLeave、DragOver、Enter、GotFocus、KeyDown、KeyPress、KeyUp、LostFocus、MouseDown、MouseEnter、MouseHover、MouseLeave、MouseMove、MouseUp、Move、Paint、Resize和TextChanged。例如,調(diào)用控件的OnClick方法就會觸發(fā)其Click事件。
Show
將控件的Visible屬性設(shè)置為True,以顯示該控件。
UserControl類
UserControl類提供一個可以用來創(chuàng)建其他控件的空控件,它是Control類的一個間接子類。由該控件派生的對象如下所示:
·System.Object
·System.MarshalByRefObject
·System.ComponentModel.Component
·System.Windows.Forms.Control
·System.Windows.Forms.ScrollableControl
·System.Windows.Forms.ContainerControl
·System.Windows.Forms.UserControl

UserControl類從ContainerControl類繼承所有的標(biāo)準(zhǔn)位置和與內(nèi)存處理有關(guān)的代碼。在用戶定制控件中還需要這些代碼。
RoundButton控件
有了Control和UserControl這二個類,開發(fā)定制的Windows控件就是輕而易舉的了。我們的定制類是通過繼承UserControl類而生成的,由于UserControl也是由繼承Control類而生成的,我們的定制類將會繼承Control類的所有有用的方法、屬性和事件。例如,由于是繼承Control類生成的,我們的定制類會自動地?fù)碛惺录幚沓绦颉?
在開發(fā)定制控件時特別重要的一個問題是如何顯示定制控件的用戶界面。無論如何組織定制控件,需要注意的是,定制控件有時會重新顯示。因此,當(dāng)定制控件重繪時,必須重新繪制用戶界面。考慮到控件每次重繪時,都會調(diào)用Control類的OnPaint方法,使用新的繪制定制控件用戶界面的OnPaint方法覆蓋該方法就能保證定制控件的保持一定的外觀。
表1中的代碼是一個名稱為RoundButton的控件,在圖1中,表單上有一個RoundButton定制控件,表2是其代碼。我們需要作的工作基本上就是覆蓋OnPaint方法。系統(tǒng)向該方法傳遞一個PaintEventArgs對象,從該方法中我們可以獲得控件的System.Drawing.Graphics對象,然后使用它的方法繪制定制控件的用戶界面。
表1:RoundButton控件
Imports System.Windows.Forms
Imports System.Drawing

Public Class RoundButton : Inherits UserControl


Public BackgroundColor As Color = Color.Blue
Protected Overrides Sub OnPaint(ByVal e As PaintEventArgs)

Dim graphics As Graphics = e.Graphics
Dim penWidth As Integer = 4
Dim pen As Pen = New Pen(Color.Black, 4)

Dim fontHeight As Integer = 10
Dim font As Font = New Font("Arial", fontHeight)

Dim brush As SolidBrush = New SolidBrush(BackgroundColor)
graphics.FillEllipse(brush, 0, 0, Width, Height)
Dim textBrush As SolidBrush = New SolidBrush(Color.Black)

graphics.DrawEllipse(pen, CInt(penWidth / 2), _
CInt(penWidth / 2), Width - penWidth, Height - penWidth)

graphics.DrawString(Text, font, textBrush, penWidth, _
Height / 2 - fontHeight)
End Sub
End Class
表1中的代碼非常地簡單,簡直令人不能相信。我們的定制類只有一個方法:OnPaint。簡單地說,該方法傳遞一個PaintEventArgs對象,從中我們可以獲得System.Drawing.Graphics對象。這一Graphics對象表示我們的定制控件的繪制區(qū),無論在該Graphics對象上繪制什么東西,它都會顯示為定制用戶控件的界面。
在Windows的編程中,繪制圖形時需要用到筆、畫筆等對象,要書寫文本,就需要字體對象。下面OnPaint方法中的代碼創(chuàng)建了一個寬度為4的System.Drawing.Pen對象:

Dim penWidth As Integer = 4
Dim pen As Pen = New Pen(Color.Black, 4)


然后再創(chuàng)建一個高度為10的Arial Font對象:

Dim fontHeight As Integer = 10
Dim font As Font = New Font("Arial", fontHeight)

我們要作的最后一步的準(zhǔn)備工作是實例化一個SolidBrush對象,并使其顏色與backgroundColor字段的顏色一致。
Dim brush As SolidBrush = New SolidBrush(backgroundColor)

現(xiàn)在我們就可以來畫了。對于控制的底部,我們可以使用Graphics類的FillEllipse方法,圓的高和寬與控件的高和寬是相同的:
graphics.FillEllipse(brush, 0, 0, Width, Height)
然后,我們可以實例化另一個畫筆,用來完成對文本的繪制:
Dim textBrush As SolidBrush = New SolidBrush(Color.Black)


至于圓形,我們可以使用Graphics類的DrawEllipse方法:
graphics.DrawEllipse(pen, Cint(penWidth/2), _
CInt(penWidth/2), Width - penWidth, Height - penWidth)


最后,我們使用DrawString方法在Graphics對象上繪制文本內(nèi)容:
graphics.DrawString(Text, font, textBrush, penWidth, _
Height / 2 - fontHeight)


我們最后得到的RoundButton控件如下圖所示


圖:picture1

好了,把控件的代碼編譯為一個.DLL文件,它就可以供我們隨時使用了。
表2中的代碼是一個調(diào)用了RoundButton控件、名稱為MyForm的表單。
表2:RoundButton控件的調(diào)用

Public Class MyForm
Inherits System.Windows.Forms.Form

#Region " Windows Form Designer generated code "

Private WithEvents roundButton As RoundButton
Public Sub New()
MyBase.New()

'這個調(diào)用是Windows Form Designer所要求的
InitializeComponent()

'在InitializeComponent()調(diào)用后,可以添加任意的實例化代碼

End Sub

'表單覆蓋,整理組件列表
Protected Overloads Overrides Sub Dispose(ByVal disposing As Boolean)
If disposing Then
If Not (components Is Nothing) Then
components.Dispose()
End If
End If
MyBase.Dispose(disposing)
End Sub

'Windows Form Designer所要求的
Private components As System.ComponentModel.IContainer

'注意:下面的過程是Windows Form Designer所要求的,
'可以使用Windows Form Designer對它進(jìn)行修改,
'但不要使用軟件編輯程序進(jìn)行修改
Private Sub InitializeComponent()
'
'MyForm
'
Me.AutoScaleBaseSize = New System.Drawing.Size(5, 13)
Me.ClientSize = New System.Drawing.Size(292, 273)
Me.Name = "MyForm"
Me.Text = "Using Custom Control"

roundButton = New RoundButton()
AddHandler roundButton.Click, AddressOf roundButton_Click
roundButton.Text = "Click Here!"
roundButton.BackgroundColor = System.Drawing.Color.White
roundButton.Size = New System.Drawing.Size(80, 80)
roundButton.Location = New System.Drawing.Point(100, 30)
Me.Controls.Add(roundButton)

End Sub

#End Region

Private Sub roundButton_Click(ByVal source As Object, ByVal e As EventArgs)
MessageBox.Show("Thank you.")
End Sub
Public Shared Sub Main()
Dim form As MyForm = New MyForm()
Application.Run(form)
End Sub

End Class

在InitializeComponent方法中,表單對一個RoundButton對象進(jìn)行實例化,并將RoundButton控件的Click事件與事件處理程序roundButton_Click連接起來:
roundButton = New RoundButton()
AddHandler roundButton.Click, AddressOf roundButton_Click

需要注意的是,由于我們沒有在RoundButton類中定義任何事件,因此它的事件處理能力是繼承Control類而得來的。
我們下一步要作的就是設(shè)置RoundButton控件的一些屬性了:
roundButton.Text = "Click Here!"
roundButton.BackgroundColor = System.Drawing.Color.White
roundButton.Size = New System.Drawing.Size(80, 80)
roundButton.Location = New System.Drawing.Point(100, 30)

最后,將roundButton控件添加到表單的控件集中:
Me.Controls.Add(roundButton)
當(dāng)用戶點(diǎn)擊控件觸發(fā)Click事件時,Click事件調(diào)用roundButton_Click事件處理程序,顯示一個消息框:
Private Sub roundButton_Click(ByVal source As Object, _
ByVal e As EventArgs)
MessageBox.Show("Thank you.")
End Sub
結(jié)論
在本篇文章中,我們介紹了開發(fā)定制控件時需要理解的System.Windows.Forms名字空間中二個重要的類:Control和UserControl。另外,我們還介紹了如何通過直接擴(kuò)充UserControl類開發(fā)自己的定制控件以及如何在Windows表單中使用定制控件。