Click here to Skip to main content
15,867,330 members
Articles / Programming Languages / C#
Article

Drawing Cards with Cards.dll

Rate me:
Please Sign up or sign in to vote.
4.85/5 (24 votes)
18 Sep 20035 min read 209K   3.4K   61   40
An article on drawing cards using the cards.dll supplied with windows

Introduction

Article shows how to use cards.dll that ships with windows, turn it into a class, and use it in a simple project that draws the reverse side of each of the 16 types of card backing.

Windows 2000 card backs

Windows XP card backs.

Background

In my programming life, I have always fancied writing a card game. Up until recently, this has been a daunting task, but I decided to bite the bullet and have a go. Over the last six months I have been teaching myself C#, so I decided that this would be the language to write the game in.

Presented below is part of the interface to cards.dll. I have mainly used two articles as my reference material that I found on the web, written originally for C. One is an MSDN article from 1996 by Dave Edson, the other comes from a site called catch22 by James Brown. I have tried to amalgamate these two articles to give a clearer overview of the cards.dll, while providing the code for C#.

Cards.dll

Cards.dll exports five functions which you can use to draw card images. Each of these is listed below, with an overview of each function and a detailed breakdown of what the arguments do. You cannot get directly to the bitmaps held within the dll, however in order to draw them, you supply a graphics device context to be drawn upon.

cdtInit

C#
[DllImport("cards.dll")]
private static extern bool cdtInit( ref int width, ref int height );

cdtInit initializes the cards.dll library. As you can see the method takes two arguments which are stored as the width and height of the card in pixels. The return value is either TRUE for when the cards.dll has been initialized, or FALSE if an error has occurred. The constructor for the cardsdll class will throw an exception if there is an error. This is shown in the snippet below.

C#
if( !cdtInit( ref width, ref height ) )
   throw new Exception ( "cards.dll did not load" );

Although, you can supply a height and width, I have found that by changing these numbers, the card actually stays the same size.

cdtTerm

C#
[DllImport("cards.dll")]
private static extern void cdtTerm();

cdtTerm is the uninitialization method. It cleans up the card resources. This is called in the Dispose() method of the cardsdll class. It is a one time function which needs to be called just before the application finishes.

cdtDraw

C#
[DllImport("cards.dll")]
private static extern bool cdtDraw( IntPtr hdc, int x, int y, 
    int card, int mode, long color );

cdtDraw draws a card. This method takes a number of parameters listed below;

  • IntPtr hdc - Pass in the device context from Graphics.GetHdc().
  • int x - upper left corner of the card.
  • int y - upper left corner of the card.
  • int card - card to draw, (this is dependant upon the mode selected).
  • int mode - mode
    • mdFaceUp - draw face up card
    • mdFaceDown - draw face down card
    • mdHilite - draw face up card inverted
    • mdGhost - draw a ghost card, the card parameter is ignored
    • mdRemove - draw rectangle of background color at x, y
    • mdDeckX - draw an X
    • mdDeckO - draw an O
  • long color - table background color (only required for mdGhost and mdRemove) or when drawing the cross hatch card back.

The return value is TRUE if the draw was successful, and FALSE otherwise.

cdtDrawExt

C#
[DllImport("cards.dll")]
private static extern bool cdtDrawExt( IntPtr hdc, int x, int y, 
    int dx, int dy, int card, int type, long color );

cdtDrawExt also draws a card. The difference is that by supplying arguments dx and dy, the size of the card can be varied.

cdtAnimate

cdtAnimate animates the backs of certain cards. In windows 2000 and previous the following cards animate.

  • ROBOT - Meter moves over 4 frames
  • CASTLE - Bats flapping around castle over 2 frames
  • ISLAND - Sun sticks tongue out over 4 frames
  • CARDHAND - Cards running up and down sleeve over 4 frames

Call cdtAnimate every 250 ms for proper animation speed. The return value is TRUE if the animation was successful, and FALSE when the animation has finished.

C#
[DllImport("cards.dll")]
private static extern bool cdtAnimate( IntPtr hdc, int cardback, 
    int x, int y, int frame );

Bitmap numbering

One final point to note about the dll is the numbering of the bitmaps within it. The lowest card (zero) is the Ace of Clubs, next card is the Ace of Diamonds, etc. What happens is that the 52 playing cards rotate from Clubs, Diamonds, Hearts to Spades and back to Clubs again, starting at the Ace and working up to the King. I have provided 2 enumerations for the suit and rank of card.

C#
public enum eSUIT : int
{
  CLUBS   = 0,
  DIAMOND = 1,
  HEARTS  = 2,
  SPADES  = 3
}

public enum eRank : int
{
  ACE   = 0,
  TWO   = 1,
  THREE = 2,
  FOUR  = 3,
  FIVE  = 4,
  SIX   = 5,
  SEVEN = 6,
  EIGHT = 7,
  NINE  = 8,
  TEN   = 9,
  JACK  = 10,
  QUEEN = 11,
  KING  = 12
}

A card value can be calculated using the simple formula

C#
card = rank + suit * 4;

For example, the 4 of Diamonds is

C#
card = ( (int)eRank.FOUR + (int)eSUIT.DIAMOND ) * 4;

Giving the value to card of 13.

The 16 card back designs as shown in the images are cards 53 through to 68. Again, I have provided an enumeration for this.

C#
public enum eBACK : int
{
  CROSSHATCH = 53, /* XP = CROSSHATCH */
  WEAVE1     = 54, /* XP = SKY */
  WEAVE2     = 55, /* XP = MINERAL */
  ROBOT      = 56, /* XP = FISH */
  FLOWERS    = 57, /* XP = FROG */
  VINE1      = 58, /* XP = MOONFLOWER */
  VINE2      = 59, /* XP = ISLAND */
  FISH1      = 60, /* XP = SQUARES */
  FISH2      = 61, /* XP = MAGENTA */
  SHELLS     = 62, /* XP = SANDDUNES */
  CASTLE     = 63, /* XP = SPACE */
  ISLAND     = 64, /* XP = LINES */
  CARDHAND   = 65, /* XP = TOYCARS */
  UNUSED     = 66, /* XP = UNUSED */
  THE_X      = 67, /* XP = THE_X */
  THE_O      = 68  /* XP = THE_0 */
}

I have not investigated whether the cards in XP animate or not. (Maybe another article!)

cardsdll class

In my code example, each of the interfaces to the dll are private, so in order to use them I have made some public functions. The main one of these I have used is to draw the backs of the cards.

C#
public bool drawCardBack( IntPtr hdc, int x, int y, eBACK back )

Inside the actual function is a call to cdtDraw(. . .) with the last two arguments fixed at mdFaceDown and 0. mdFaceDown is a constant declaration in the class as one of the card types.

Similarly, each way of drawing a card has a public interface.

C#
public bool drawCard( IntPtr hdc, int x, int y, int card, 
    int mode, long color )
public bool drawCardBack( IntPtr hdc, int x, int y, eBACK back )
public bool drawAnimatedBack( IntPtr hdc, int x, int y, 
    int card, int frame )
public bool drawInvertedCard( IntPtr hdc, int x, int y, int card )
public bool drawEmptyCard( IntPtr hdc, int x, int y, long color )
public bool drawExtrudedCard( IntPtr hdc, int x, int y, int dx, 
    int dy, int card, int mode, long color )

Using the code

As an example, in order to draw the bottom right corner card, the following call is made.

C#
cardHandle.drawCardBack( hdc, 250, 310, eBACK.THE_O );

Where cardHandle is an instance of the cardsdll class.

Conclusion

I didn't realize how easy drawing a card could be till I looked at cards.dll. I hope people find this, my first article useful.

History

  • 15.09.03 - Initial Publication.

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


Written By
Software Developer (Senior)
United Kingdom United Kingdom
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
QuestionUnable to find an entry point named 'cdtInit' in DLL Pin
Geno Carman3-Apr-21 5:35
Geno Carman3-Apr-21 5:35 
Bugdll cards Pin
Member 1095663417-Apr-17 22:42
Member 1095663417-Apr-17 22:42 
GeneralProblem with showing cards.... [modified] Pin
nikola8725-Feb-09 3:25
nikola8725-Feb-09 3:25 
QuestionVista problem... Pin
rebulanyum27-Nov-08 0:49
rebulanyum27-Nov-08 0:49 
GeneralcdtInit width and height parameters Pin
Wayland Young19-Feb-08 3:44
professionalWayland Young19-Feb-08 3:44 
First of all, good job on the new code and explanations.

Secondly, the width and height parameters to cdtInit are not intended to change the width and height of the cards. You correctly note that even if you change these values, they will always be initialized to defaults of 71x97. That's because the function wasn't intended for you to ever change the values, but for the correct values to be returned to you, hence they are byref parameters and should be initialized to 0 or -1 and will contain the correct width and height values after the function call. Not a big deal, just a little more explanation.

Thanks
QuestionHow do I add the code to C# project? Pin
arabdad30-Jan-07 3:43
arabdad30-Jan-07 3:43 
GeneralVS2k5 Users Pin
Mythrandil12-Jan-07 2:58
Mythrandil12-Jan-07 2:58 
Questionabout card drawing in VS 2005 Pin
alvi_du6-Aug-06 20:57
alvi_du6-Aug-06 20:57 
AnswerRe: about card drawing in VS 2005 Pin
Mike Kitchen6-Aug-06 23:15
Mike Kitchen6-Aug-06 23:15 
GeneralRe: about card drawing in VS 2005 Pin
Jonathan McCaffrey30-Nov-06 13:38
Jonathan McCaffrey30-Nov-06 13:38 
GeneralRe: about card drawing in VS 2005 Pin
mjb10-Sep-08 12:20
mjb10-Sep-08 12:20 
GeneralRe: about card drawing in VS 2005 Pin
mjb10-Sep-08 12:40
mjb10-Sep-08 12:40 
GeneralPInvoke signature errors Pin
hestol24-Feb-06 2:44
hestol24-Feb-06 2:44 
General"the card actually stays the same size" Pin
The_Mega_ZZTer7-Oct-05 9:01
The_Mega_ZZTer7-Oct-05 9:01 
GeneralCard != (Suit + Rank) * 4 Pin
kcd224636576629-Jul-05 22:31
kcd224636576629-Jul-05 22:31 
GeneralRe: Card != (Suit + Rank) * 4 Pin
kcd224636576629-Jul-05 22:35
kcd224636576629-Jul-05 22:35 
AnswerRe: Card != (Suit + Rank) * 4 Pin
Douglas R. Keesler27-Apr-06 17:00
Douglas R. Keesler27-Apr-06 17:00 
GeneralCard Selection Screen Pin
Bob Bonser9-Feb-05 6:42
Bob Bonser9-Feb-05 6:42 
AnswerRe: Card Selection Screen Pin
Douglas R. Keesler27-Apr-06 17:09
Douglas R. Keesler27-Apr-06 17:09 
GeneralA few style comments Pin
braduhrich18-Apr-04 5:52
braduhrich18-Apr-04 5:52 
GeneralRe: A few style comments Pin
Mike Kitchen18-Apr-04 21:37
Mike Kitchen18-Apr-04 21:37 
GeneralRotations Pin
oOomen5-Apr-04 23:42
oOomen5-Apr-04 23:42 
GeneralRe: Rotations Pin
Mike Kitchen18-Apr-04 21:35
Mike Kitchen18-Apr-04 21:35 
GeneralMinor Typo Pin
Codin' Carlos19-Sep-03 5:44
Codin' Carlos19-Sep-03 5:44 
GeneralRe: Minor Typo Pin
publicjoe19-Sep-03 9:52
publicjoe19-Sep-03 9:52 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.