Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Creating Custom Controls: Casino Royale

0.00/5 (No votes)
21 May 2012 1  
Learn to create your own casino-themed controls from scratch.

Texas Hold'em Poker with the card control.

Background

Make sure you:

  1. Have a decent understanding of OOP.
  2. Know how to draw to the form using System.Drawing and Control.CreateGraphics().
  3. Want to learn how to create controls! 

About the code...

For this article, I'll show you how to create two controls with a casino theme: dice and cards. While these may be completely useless as controls when creating applications, they should give you a very good understanding of how to code others. 

Part 1 - Dice

Of the two controls you'll be creating in this article, the dice are better polished, and thus a better example. However, once you're done here, the cards should have lots of areas you can go and customize.

Open up VS and create a new Class Library project named "Custom Controls". You can delete the default Class1.vb as we won't be using it. Add a user control to the project, and name it Dice (or Die). Your new control is a little rectangle. Click it and change these properties:

  • BackColor to White.
  • BorderStyle to FixedSingle.
  • Size to 120, 120.

For the first bit of programming, create a new property: Public Property Pips() as Integer. When set, make sure you check to see if the number is from 1 to 6. If it is, set Pips to value and call Me.Refresh(). Create another Public property as a System.Drawing.Brush called PipBrush. This is the brush that will paint the pips.

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

The complete code is in the sample project.

Now that everything's set, we need to draw the dots in the Dice.Paint event. Make sure it's the paint event, and not the load event you're working with! This is because if you put the code in the load event, when the die is obscured by another window, the pips will disappear. Here is the part of the method (the rest is available in the downloadable Custom Controls project):

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

This is the code that draws the dots (pips) onto the die. It's pretty repetitive, so after the first two conditions, you should get the idea. Case 1 is called if there is one pip on the die. Dim Pip1 As New Rectangle(pntMid, DefaultSize) defines where the dot will be and how big it is. Lastly, DrawingArea.FillEllipse(Me.PipBrush, Pip1) draws the circle and fills it in. In case you're wondering, PipSize is a constant equal to 24.

One more note: in the sample project, there is a region called Hidden Properties. What are these? They're properties that were inherited from UserControl that either we don't want the user to have access to, or they won't effect the control. By following these examples, there are some other useless properties you can hide (or make useful).

Public Shadows ReadOnly Property NameOfProperty() As Type
    Get
        Return Nothing
    End Get
End Property

Part 2 - Cards

I'll get you started on making a basic card control, but for the most part, you can play around with it and um... botch it anyway you please. The only new concept here is placing controls on controls. The card we're making is like a form - you can put any other control on it, as you'll see in a few seconds. First, add another user control to the project, naming it Card. Then, set its properties like this:

  • BorderStyle to FixedSingle.
  • Size to 150, 165.

Then add two Labels to the form:

Label 1

  • Name to labPhrase.
  • Text to Phrase.
  • Location to 3,11.

Label 2

  • Name to labAbbreviation.
  • Location to 21,66.
  • Font to Arial, 48pt.
  • Text to ♥X, or any two-character string.

That's it for the designer. Note that the user won't have access to the individual labels you placed, only the card as a whole.

Now we have to find a way to specify which card is which - the number or value of each card, like 9, 10, Jack, Queen, etc. You could just use integers and verify it's in the correct range, but what if someone doesn't know that King = 13 off the top of their heads? Instead of forcing them to count on their fingers and toes, we can create an enum. While we're at it, make another one for the card's suit, too.

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

Notice there are three different items referring to jokers: JokerRed, JokerBlack, and Joker. If any one of these is chosen, the card is a joker. Remember, my ideas are just guidelines; if you find a better way to do something, do it! Smile | <img src= " />

The CardNumber and Suit properties are simple, just storing and retrieving values.

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

The UpdateCard() method is like the paint event in the dice control. Call it whenever you need to show the changes made to a card. Again, refer to the Custom Controls project for more on when the SuitChanged and CardNumberChanged events are called and the IsBlack and IsRed methods.

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()

And that about wraps it up! I recommend adding a new Windows Application project to your solution to test the controls.

Things to Do

  • Create a Deck collection.
  • Public Class Deck
       _Inherits System.Collections.ObjectModel.Collection(Of Card)
            ...
    End Class
  • Make the die resizable and adjust the pip size and position accordingly.
  • Make the card adjust to when it is resized.
  • Create Yahtzee! and Texas Hold'Em games with the new controls.

History

  • 7/14/07
    • Article submitted.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here