创建自定义控件:Casino Royale






4.42/5 (5投票s)
学习如何从头开始创建自己的赌场主题控件。
背景
请确保您
- 对 OOP 有一定的了解。
- 知道如何使用
System.Drawing
和Control.CreateGraphics()
绘制到窗体上。 - 想要学习如何创建控件!
关于代码...
在这篇文章中,我将向您展示如何创建两个具有赌场主题的控件:骰子和扑克牌。虽然这些控件在创建应用程序时可能完全无用,但它们应该能让您非常深入地了解如何编写其他控件。
第一部分 - 骰子
在这篇文章中您将创建的两个控件中,骰子打磨得更好,因此是更好的例子。但是,一旦您在这里完成,扑克牌应该有很多可以去自定义的领域。
打开 VS 并创建一个名为“Custom Controls”的新类库项目。您可以删除默认的Class1.vb,因为我们不会使用它。向项目添加一个用户控件,并将其命名为 Dice
(或 Die
)。您新创建的控件是一个小矩形。单击它并更改这些属性
- 将
BackColor
设置为 **白色**。 - 将
BorderStyle
设置为 **FixedSingle**。 - 将
Size
设置为 **120, 120**。
对于第一部分编程,创建一个新属性:Public Property Pips() as Integer
。设置时,请务必检查数字是否在 1 到 6 之间。如果是,则将 Pips
设置为 value
并调用 Me.Refresh()
。创建另一个 System.Drawing.Brush
类型的 Public
属性,名为 PipBrush
。这是绘制点数的画笔。
Dim _Pips As Integer = 1
Public Property Pips() As Integer
Get
Return _Pips
End Get
Set(ByVal value As Integer)
If value > 6 Then
Throw New ArgumentOutOfRangeException("Pips", _
"The number of Pips cannot be greater than 6.")
ElseIf value < 1 Then
Throw New ArgumentOutOfRangeException("Pips", _
"The number of Pips cannot be less than 1.")
Else
_Pips = value
Me.Refresh()
End If
End Set
End Property
Dim _brush As Brush = New SolidBrush(Color.Black)
Public Property PipBrush() As Brush
Get
Return _brush
End Get
Set(ByVal value As Brush)
_brush = value
End Set
End Property
完整的代码包含在示例项目中。
现在一切都设置好了,我们需要在 Dice.Paint
事件中绘制点数。请确保您使用的是 paint 事件,而不是 load 事件!这是因为如果您将代码放在 load 事件中,当骰子被另一个窗口遮挡时,点数将会消失。以下是该方法的一部分(其余部分可在下载的 Custom Controls 项目中找到)
Dim DrawingArea As Graphics = Me.CreateGraphics()
Dim DefaultSize As New Size(PipSize, PipSize)
'Define all possible placements for pips
Dim pntUpLeft As New Point(8, 8)
Dim pntUpRight As New Point(88, 8)
Dim pntMidLeft As New Point(8, 48)
Dim pntMid As New Point(48, 48)
Dim pntMidRight As New Point(88, 48)
Dim pntBotLeft As New Point(8, 88)
Dim pntBotRight As New Point(88, 88)
'Draw the pips in the correct places depending on how many there are.
'Each pip should have a diameter of 24px.
Select Case Me.Pips
Case 1
Dim Pip1 As New Rectangle(pntMid, DefaultSize)
DrawingArea.FillEllipse(Me.PipBrush, Pip1)
Case 2
Dim Pip1 As New Rectangle(pntUpLeft, DefaultSize)
Dim Pip2 As New Rectangle(pntBotRight, DefaultSize)
DrawingArea.FillEllipse(Me.PipBrush, Pip1)
DrawingArea.FillEllipse(Me.PipBrush, Pip2)
Case 3
...
Case 4
...
Case 5
...
Case 6
...
End Select
这是绘制骰子上的点数的代码。它相当重复,所以在前两个条件之后,您应该就能明白意思了。Case 1
在骰子有一个点数时调用。Dim Pip1 As New Rectangle(pntMid, DefaultSize)
定义了点数的位置和大小。最后,DrawingArea.FillEllipse(Me.PipBrush, Pip1)
绘制并填充了圆形。如果您想知道,PipSize
是一个等于 24 的常量。
再补充一点:在示例项目中,有一个名为 **Hidden Properties** 的区域。这些是什么?它们是从 UserControl
继承的属性,我们不希望用户访问它们,或者它们不会影响控件。通过遵循这些示例,您可以隐藏(或使其有用)其他一些无用的属性。
Public Shadows ReadOnly Property NameOfProperty() As Type
Get
Return Nothing
End Get
End Property
第二部分 - 扑克牌
我将开始教您制作一个基本的扑克牌控件,但大部分情况下,您可以随意摆弄它,然后……随便怎么弄都可以。这里唯一新的概念是将控件放置在控件上。我们正在制作的扑克牌就像一个窗体——您可以在上面放置任何其他控件,正如您将在几秒钟内看到的。首先,向项目添加另一个用户控件,命名为 Card
。然后,像这样设置它的属性
- 将
BorderStyle
设置为 **FixedSingle**。 - 将
Size
设置为 **150, 165**。
然后向窗体添加两个 Label
控件
Label 1
- 将
Name
设置为 **labPhrase**。 - 将
Text
设置为 **Phrase**。 - 将
Location
设置为 **3,11**。
Label 2
- 将
Name
设置为 **labAbbreviation**。 - 将
Location
设置为 **21,66**。 - 将
Font
设置为 **Arial, 48pt**。 - 将
Text
设置为 **♥X**,或者任何两个字符的字符串。
设计师部分就是这些了。请注意,用户将无法访问您放置的单个标签,只能访问整个扑克牌。
现在我们必须找到一种方法来指定每张牌是哪一张——每张牌的数字或值,例如 9、10、J、Q 等。您可以使用整数并验证它是否在正确范围内,但如果有人不立即知道 King=13 呢?与其强迫他们费力计算,不如创建一个枚举。同时,也为牌的花色创建一个。
Public Enum Suits
JokerBlack = -2
JokerRed = -1
Clubs = 0
Diamonds = 1
Spades = 2
Hearts = 3
End Enum
Public Enum Cards
Joker = 0
Two = 2
Three = 3
Four = 4
Five = 5
Six = 6
Seven = 7
Eight = 8
Nine = 9
Ten = 10
Jack = 11
Queen = 12
King = 13
Ace = 14
End Enum
请注意,有三个不同的项目指向百搭牌:JokerRed
、JokerBlack
和 Joker
。选择其中任何一个,该牌就是百搭牌。请记住,我的想法只是指导;如果您找到更好的方法,请去做! " />
CardNumber
和 Suit
属性很简单,只是存储和检索值。
Dim _crdNum As Cards = Cards.Joker
Public Property CardNumber() As Cards
Get
Return _crdNum
End Get
Set(ByVal value As Cards)
'Save the previous value to use it for the event.
Dim old As Cards = _crdNum
_crdNum = value
RaiseEvent CardNumberChanged(old, value)
End Set
End Property
Dim _stSuit As Suits = Suits.JokerBlack
Public Property Suit() As Suits
...
End Property
UpdateCard()
方法类似于骰子控件中的 paint 事件。每当您需要显示对扑克牌所做的更改时,请调用它。同样,有关 SuitChanged
和 CardNumberChanged
事件何时被调用以及 IsBlack
和 IsRed
方法的更多信息,请参阅 Custom Controls 项目。
Private Sub Card_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
UpdateCard()
End Sub
Private Sub UpdateCard() Handles Me.SuitChanged, Me.CardNumberChanged
Dim strAbbr As String
Dim strPhrase As String
'Make sure the card suit isn't a joker.
If (Me.Suit <> Suits.JokerRed) And (Me.Suit <> Suits.JokerBlack) Then
Dim IsNotRoyalty As Boolean = Me.CardNumber <> _
Cards.Jack And Me.CardNumber <> Cards.Queen And _
Me.CardNumber <> Cards.King And Me.CardNumber <> Cards.Ace
'Make sure the card isn't royalty.
If IsNotRoyalty Then
strAbbr = Me.CardNumber & strSymbols(Me.Suit)
'If it is royalty, set its abbreviation to its suit
'and first letter of the card's name.
Else
strAbbr = Me.CardNumber.ToString()(0) & strSymbols(Me.Suit)
End If
'Make sure the card number isn't set to joker.
If Me.CardNumber <> Cards.Joker Then
strPhrase = Me.CardNumber.ToString & _
" of " & Me.Suit.ToString
'If the # is a joker, than set it's phrase
'to "Joker", and its abbreviation to "JK"
Else
strPhrase = "Joker"
strAbbr = "JK"
End If
'If the suit is a joker, set its abbreviation and phrase.
Else
strPhrase = "Joker"
strAbbr = "JK"
End If
'Check to see which color the card is
If Me.Suit = Suits.Clubs Or Me.Suit = Suits.Spades Or Me.Suit = Suits.JokerBlack Then
IsBlack()
Else
IsRed()
End If
'Change the labels' texts
labAbbreviation.Text = strAbbr
labPhrase.Text = strPhrase
End Sub
就这样!我建议向您的解决方案添加一个新的 Windows 应用程序项目来测试这些控件。
待办事项
- 创建一个
Deck
集合。
Public Class Deck
_Inherits System.Collections.ObjectModel.Collection(Of Card)
...
End Class
历史
- 7/14/07
- 文章已提交。