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

创建自定义控件:Casino Royale

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.42/5 (5投票s)

2007年7月14日

CDDL

4分钟阅读

viewsIcon

45858

downloadIcon

354

学习如何从头开始创建自己的赌场主题控件。

Texas Hold'em Poker with the card control.

背景

请确保您

  1. 对 OOP 有一定的了解
  2. 知道如何使用 System.DrawingControl.CreateGraphics() 绘制到窗体上。
  3. 想要学习如何创建控件! 

关于代码...

在这篇文章中,我将向您展示如何创建两个具有赌场主题的控件:骰子和扑克牌。虽然这些控件在创建应用程序时可能完全无用,但它们应该能让您非常深入地了解如何编写其他控件。 

第一部分 - 骰子

在这篇文章中您将创建的两个控件中,骰子打磨得更好,因此是更好的例子。但是,一旦您在这里完成,扑克牌应该有很多可以去自定义的领域。

打开 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

请注意,有三个不同的项目指向百搭牌:JokerRedJokerBlackJoker。选择其中任何一个,该牌就是百搭牌。请记住,我的想法只是指导;如果您找到更好的方法,请去做!微笑 | <img src= " />

CardNumberSuit 属性很简单,只是存储和检索值。

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 事件。每当您需要显示对扑克牌所做的更改时,请调用它。同样,有关 SuitChangedCardNumberChanged 事件何时被调用以及 IsBlackIsRed 方法的更多信息,请参阅 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

Explains UpdateCard()

就这样!我建议向您的解决方案添加一个新的 Windows 应用程序项目来测试这些控件。

待办事项

  • 创建一个 Deck 集合。
  • Public Class Deck
       _Inherits System.Collections.ObjectModel.Collection(Of Card)
            ...
    End Class
  • 使骰子可调整大小,并相应地调整点数大小和位置。
  • 使扑克牌在调整大小时进行相应调整。
  • 使用新控件创建 Yahtzee! 和 Texas Hold'Em 游戏。

历史

  • 7/14/07
    • 文章已提交。
© . All rights reserved.