WPF NotifyIcon control!

by Coding4Fun on May 26, 2009

wpfNotifyIcon If you’ve ever had a WPF application and wanted a notify icon in your system tray, you’ve had to import the System.Windows bits.  This always seemed to me as a hack to get it but at least I could do.  Fear not anymore, Philipp Sumi has created a WPF NotifyIcon component!

Features at a glance
  • Custom Popups (interactive controls) on mouse clicks.
  • Customized ToolTips (Vista and above) with fallback mechanism for xp/2003.
  • Rich event model including attached events to trigger animations in Popups, ToolTips, and balloon messages. I just love that.
  • Full support for standard Windows balloons, including custom icons.
  • Custom balloons that pop up in the tray area that can be styled with effects
  • WPF context menus.
  • You can define whether to show Popups on left-, right-, double-clicks etc. The same goes for context menus.
  • Simple data binding for Popups, ToolTips and custom balloons through attached properties and derived data context.
  • Command support for single / double clicks on the tray icon.

{ Comments on this entry are closed }

Cropping with ASP.Net

by Coding4Fun on May 22, 2009

image

Cem Sisman created a ASP.Net image cropping control for the JQuery plugin, Jcrop.

Demos:

Matthew Paulson has a quick and dirty write up on how to implement this on your page too.

The codeplex project needs to be updated to correct some IE8 issues but I’m hoping all you need to do is download the new version of JCrop and everything should be fixed.

{ Comments on this entry are closed }

Virtual code execution via IL interpretation

May 22, 2009

As Soma announced, we just shipped VS2010 Beta1. This includes dump debugging support for managed code and a very cool bonus feature tucked in there that I’ll blog about today.

Dump-debugging (aka post-mortem debugging) is very useful and a long-requested feature for managed code.  The downside is that with a dump-file, you don’t have a live process anymore, and so property-evaluation won’t work. That’s because property evaluation is implemented by hijacking a thread in the debuggee to run the function of interest, commonly a ToString() or property-getter. There’s no live thread to hijack in post-mortem debugging.

We have a mitigation for that in VS2010. In addition to loading the dump file, we can also interpret the IL opcodes of the function and simulate execution to show the results in the debugger.

 

Here, I’ll just blog about the end-user experience and some top-level points. I’ll save the technical drill down for future blogs.

Consider the following sample:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;

public class Point
{
    int m_x;
    int m_y;
    public Point(int x, int y)
    {
        m_x = x;
        m_y = y;
    }
    public override string ToString()
    {
        return String.Format("({0},{1})", this.X, this.Y);
    }

    public int X
    {
        get
        {
            return m_x;
        }
    }
    public int Y
    {
        get
        {
            return m_y;
        }
    }
}

public class Program
{
    static void Main(string[] args)
    {
        Dictionary<int, string> dict = new Dictionary<int, string>();
        dict[5] = "Five";
        dict[3] = "three";

        Point p = new Point(3, 4);

    }

    public static int  Dot(Point p1, Point p2)
    {
        int r2 = p1.X * p2.X + p1.Y * p2.Y;
        return r2;
    }

}

 

Suppose you have a dump-file from a thread stopped at the end of Main() (See newly added menu item “Debug | Save Dump As …”; load dump-file via “File | Open | File …”).

Normally, you could see the locals (dict, p) and their raw fields, but you wouldn’t be able to see the properties or ToString() values. So it would look something like this:

image

But with the interpreter, you can actually simulate execution. With the IL interpreter, here’s what it looks like in the watch window:

image

Which is exactly what you’d expect with live-debugging.  (In one sense, “everything still works like it worked before” is not a gratifying demo…)

The ‘*’ after the values are indications that they came from the interpreter.  Note you still need to ensure that property-evaluation is enabled in “Tools | options | Debugging”:

image

 

 

 

 

How does it work?
The Interpreter gets the raw IL opcodes via ICorDebug and then simulates execution of those opcodes. For example, when you inspect “p.X” in the watch window, the debugger can get the raw IL opcodes:

.method public hidebysig specialname instance int32
        get_X() cil managed
{
  // Code size       12 (0xc)
  .maxstack  1
  .locals init ([0] int32 CS$1$0000)
  IL_0000:  nop
  IL_0001:  ldarg.0
  IL_0002:  ldfld      int32 Point::m_x
  IL_0007:  stloc.0
  IL_0008:  br.s       IL_000a
  IL_000a:  ldloc.0
  IL_000b:  ret
} // end of method Point::get_X

And then translate that ldfld opcode into a ICorDebug field fetch the same way it would fetch “p.m_x”. The problem gets a lot harder then that (eg, how does it interpret a newobj instruction?) but that’s the basic idea.

 

Other things it can interpret:

The immediate window is also wired up to use the interpreter when dump-debugging. Here are some sample things that work. Again, note the ‘*’ means the results are in the interpreter and the debuggee is not modified.

Simulating new objects:
? new Point(10,12).ToString()
“(10,12)”*

Basic reflection:
? typeof(Point).FullName
“Point”*

Dynamic method invocation:
? typeof(Point).GetMethod(”get_X”).Invoke(new Point(6,7), null)
0×00000006*

Calling functions, and even mixing debuggee data (the local variable ‘p’) with interpreter generated data (via the ‘new’ expression):
? Dot(p,new Point(10,20))
110*

 

It even works for Visualizers

Notice that it can even load the Visualizer for the Dictionary (dict) and show you the contents as a pretty array view rather than just the raw view of buckets. Visualizers are their own dll,  and we can verify that the dll is not actually loaded into the debuggee. For example, the Dictionary visualizer dll is  Microsoft.VisualStudio.DebuggerVisualizers.dll, but that’s not in the module list:

image

 

That’s because the interpreter has virtualized loading the visualizer dll into its own “virtual interpreter” space and not the actual debuggee process space. That’s important because in a dump file, you can’t load a visualizer dll post-mortem.

 

 

Other issues:

There are lots of other details here that I’m skipping over, like:

  1. The interpreter is definitely not bullet proof. If it sees something it can’t interpreter (like a pinvoke or dangerous code), then it simply aborts the interpretation attempt.
  2. The intepreter is recursive, so it can handle functions that call other functions. (Notice that ToString call get_X.)
  3. How does it deal with side-effecting operations?
  4. How does it handle virtual dispatch call opcodes?
  5. How does it handle ecalls?
  6. How does it handle reflection

 

Other advantages?

There are other advantages of IL interpretation for function evaluation, mainly that it addresses the ”func-eval is evil” problems by essentially degenerating dangerous func-evals to safe field accesses.

  1. It is provably safe because it errs on the side of safety. The interpreter is completely non-invasive (it operates on a dump-file!).
  2. No accidentally executing dangerous code.
  3. Side-effect free func-evals. This is a natural consequence of it being non-invasive.
  4. Bullet proof func-eval abort.
  5. Bullet proof protection against recursive properties that stack-overflow.
  6. It allows func-eval to occur at places previously impossible, such as in dump-files, when the thread is in native code, retail code, or places where there is no thread to hijack.

Closing thoughts

We realize that the interpreter is definitely not perfect. That’s part of why we choose to have it active in dump-files but not replace func-eval in regular execution. For dump-file scenarios, it took something that would have been completely broken and made many things work. 

Read the full article →

Rook to bishop, pawn to queen, checkmate

May 21, 2009

ChessBoard[1] Ever wonder how to build a chess game?  Jacques Fournier has built a c# chess game with a built in game import engine.

Jacques’s version has the following features:

  • Visual interface
  • Multiple difficulty levels
  • Database of book openings
  • Loading / saving of game
  • Undo / redo functions
  • Reversing the board
  • Player against computer
  • Computer against computer
  • Player against player
  • Creating your own chess board (manually or from PGN)
  • Hints for the player

If you want a chess program in Visual Basic, Kaushal Golwala has a version of a chess game which can be found at vbdotnetheaven.com!

Read the full article →

Classic JukeBox

May 19, 2009

CJBLogo Remember the classic arcade style jukeboxes? Today we will be creating our own jukebox using WPF, WMP, a little bit of 3D, some very basic electronics (costing less than $10 USD) and a splash of M-V-VM

Rudi Grobler

  • Difficulty: Intermediate
  • Time Required: 2-4 hours
  • Cost: ~$10 for the 5 buttons and the LPT connector
  • Software: Visual C# Express Edition 2008
  • Source Code Download: Available on CodePlex

Introduction

A couple of weeks ago I took my son to the game arcade to play a little… while playing, I noticed in the corner a old jukebox… I started wondering how difficult it would be to recreate one of these using “real” hardware and WPF? This article explorers how to make real hardware control software applications in a practical manner

M-V-VM

“Once a developer becomes comfortable with WPF and MVVM, it can be difficult to differentiate the two. MVVM is the lingua franca of WPF developers because it is well suited to the WPF platform, and WPF was designed to make it easy to build applications using the MVVM pattern (amongst others). In fact, Microsoft was using MVVM internally to develop WPF applications, such as Microsoft Expression Blend, while the core WPF platform was under construction. Many aspects of WPF, such as the look-less control model and data templates, utilize the strong separation of display from state and behavior promoted by MVVM.”

WPF Apps With The Model-View-ViewModel Design Pattern by Josh Smith

The M-V-VM pattern helps to separate the logic from the UI which is VERY important when you actually want to manipulate the logic from external sources (Like real push buttons). Our MediaViewModel is extremely simple…

ViewModel

The MediaViewModel has a collection of albums (Which gets fetched when Initialize() is called) and also exposes some commands

Setting up Windows Media Player media library

WMPMediaLibrary

Ensure that your Windows Media Player (WMP) media library has some media. I added a few albums to my library by clicking on the Add to library… menu option.

TIP - I also ensured that all my CD’s that I do add has full ID3 tags and album art

Fetching WMP media library

To fetch the media library from WMP, we have to use a little bit of COM

“Microsoft COM (Component Object Model) technology in the Microsoft Windows-family of Operating Systems enables software components to communicate. COM is used by developers to create re-usable software components, link components together to build applications, and take advantage of Windows services. The family of COM technologies includes COM+, Distributed COM (DCOM) and ActiveX® Controls.”

Adding a reference to a COM component is just as easy as adding a reference to a .NET assembly. Click the Project menu and select Add Reference, then click the COM tab on the Add Reference dialog.

AddWmpComReference

The WMP library is a flat structure of media items, so the Albums -> Tracks hierarchy must be created manually. Here is our Model

Model

We will be abstracting the fetching of the data by using a IMediaLibraryRepository. By using a interface we have the added advantage of supporting other media sources (like iTunes, etc) in the future

C#:

public interface IMediaLibraryRepository
{
    IList<Album> GetAlbums();
}

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, “Courier New”, courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

And here is our WMP-specific implementation

C#:

public class WMPMediaLibraryRepository : IMediaLibraryRepository
{
    public IList<Album> GetAlbums()
    {
        List<Album> Albums = new List();
        WindowsMediaPlayer wmp = new WindowsMediaPlayer();
        IWMPPlaylist playlist = wmp.mediaCollection.getAll();
        for (int i = 0; i < playlist.count; i++)
        {
            IWMPMedia media = (IWMPMedia)playlist.get_Item(i); 

            Track track = new Track();
            track.Title = media.getItemInfo("Title");
            track.Location = media.getItemInfo("SourceUrl");
            track.Number = media.getItemInfo("OriginalIndex");
            string albumName = media.getItemInfo("Album"); 

            var album = (from a in Albums
                            where a.Name == albumName
                            select a).FirstOrDefault(); 

            if (album != null)
            {
                album.Tracks.Add(track);
            }
            else
            {
                Album a = new Album();
                a.Name = albumName;
                string dir = System.IO.Path.GetDirectoryName(track.Location);
                FileInfo file = new FileInfo(System.IO.Path.Combine(dir, "Folder.jpg"));
                if (file.Exists)
                {
                    a.Cover = file.FullName;
                }
                a.Artist = media.getItemInfo("AlbumArtist");
                a.Tracks.Add(track);
                if (albumName != string.Empty)
                {
                    Albums.Add(a);
                }
            }
        }
        return Albums;
    }
}

Commands

All the interaction between the View and the ViewModel happens by using ICommand. We will be using the RelayCommand

RelayCommand - An ICommand whose delegates can be attached for Execute and CanExecute

The MediaViewModel exposes the following commands

  • NextAlbum
  • PreviousAlbum
  • SongUp
  • SongDown
  • PlaySong

To create a RelayCommand, we first need the CanExecute and Execute delegates

C#:

private bool SongUpCanExecute(object parameter)
{
    return (TracksCollectionView.CurrentPosition > 0);
} 

private void SongUpExecute(object parameter)
{
    if (TracksCollectionView != null)
    {
        TracksCollectionView.MoveCurrentToPrevious();
    }
}

And then create the command

C#:

private ICommand songUp;
public ICommand SongUp
{
    get
    {
        if (songUp == null)
        {
            songUp = new RelayCommand(SongUpExecute, SongUpCanExecute);
        }
        return songUp;
    }
}

The RelayCommand is very well suited to the M-V-VM pattern because it allows me to encapsulate the whole command and its executing logic very cleanly in my ViewModel. The View can then just bind to these commands!

For more information about custom ICommand implementations, read The Power of ICommand

TurnThePage 3D WPF Book Control

“The Great Library of Alexandria was founded in 300 B.C.E. with the grand objective of collecting the world’s knowledge in one place; at its height, the library contained nearly 750,000 scrolls. In the modern world, the British Library contains one of the foremost collections; among its twenty million books and manuscripts are some of the rarest works in existence. It holds the Diamond Sutra, the oldest printed book; Mercator’s first atlas of Europe; the Lindisfarne Gospels; Leonardo da Vinci’s personal notebook; the Magna Carta; and the Codex Sinaiticus, one of the two earliest Christian Bibles. Such unique items must, of course, be treated with the utmost care. If they are on public display at all, they are well protected behind glass, and direct interaction is limited to a handful of individuals.

Happily, these works are now being digitized for the first time in order to reach a broad audience. Even better, the digitized versions are being turned into a rich interactive experience that adds curatorial content and brings the books to life. In collaboration with a UK-based software developer, the British Library developed a Windows®-based application called Turning the Pages that offers a virtual facsimile in three-dimensional space of a growing number of the library’s most precious items”

Turning the Pages with WPF by Tim Sneath

By using the free book control (released by Mitsuru Furuta on CodePlex), we will be transforming our WMP media library into a book browsing experience!

To use the controls, we need to reference the WPMMitsuControls.dll and add the following namespace

xmlns:controls="clr-namespace:WPFMitsuControls;assembly=WPFMitsuControls"

Because Book derive from ItemsControl, we can bind it to any collection using ItemsSource and change the ItemTemplate (Like we would using ListBox, ListView, etc)

<controls:Book ItemsSource="...">
    <controls:Book.ItemTemplate>
        ...
    </controls:Book.ItemTemplate>
</controls:Book>

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, “Courier New”, courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

Accessing the parallel port

parallelPort1

parallelPortReg

We will be using the status register (Base + 1) for feedback from the keypad. To access the keypad we need a hardware IO driver (I will be using inpout32.dll). inpout32.dll is a win32 dll so we need to p/invoke

C#:

public class PortAccess
{
    [DllImport("inpout32.dll", EntryPoint = "Out32")]
    public static extern void Output(int adress, int value); 

    [DllImport("inpout32.dll", EntryPoint = "Inp32")]
    public static extern int Input(int adress);
}

For more information on how to access the LPT port using managed code, first read the following CodeProject article:

Electronics 101

Schematic

This is a very basic schematic of how my keypad is wired up…

Cable

I had a keypad laying round which I used but you can also use normal push buttons available at your local electronics shop (Here is a list of push buttons available from RadioShack)

WindowWithKeypadSupport

The last part we need to cover is how to react to a key being pressed on the keypad. I sub-classed the WPF Window and created my own WindowWithKeypadSupport. WindowWithKeypadSupport has a background thread running which monitors the LPT port. If a button is pressed, it raises a PreviewKeypadDown routed event.

C#:

public class WindowWithKeypadSupport : Window
{
    public static readonly RoutedEvent PreviewKeypadDownEvent; 

    static WindowWithKeypadSupport()
    {
        WindowWithKeypadSupport.PreviewKeypadDownEvent =
            EventManager.RegisterRoutedEvent( "PreviewKeypadDown",
            RoutingStrategy.Bubble, typeof(KeypadEventHandler),
            typeof(WindowWithKeypadSupport));
    } 

    public event RoutedEventHandler PreviewKeypadDown
    {
        add
        {
            base.AddHandler(WindowWithKeypadSupport.PreviewKeypadDownEvent, value);
        }
        remove
        {
            base.RemoveHandler(WindowWithKeypadSupport.PreviewKeypadDownEvent, value);
        }
    }
    // The rest of the class is omited for brevity 
} 

To raise the event, we need to invoke back to the UI thread

C#:

Dispatcher.BeginInvoke(DispatcherPriority.Background,
    (SendOrPostCallback)delegate
    {
        KeypadEventArgs e = new KeypadEventArgs(
            WindowWithKeypadSupport.PreviewKeypadDownEvent, this);
        e.Key = CreateKeyFromIOPortValue(keyValue);
        base.RaiseEvent(e);
    }, null);

Here is a example of how to instantiate the WindowWithKeyadSupport

<controls:WindowWithKeypadSupport x:Class="ClassicJukebox.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:controls="clr-namespace:ClassicJukebox"
    PreviewKeypadDown="WindowWithKeypadSupport_PreviewKeypadDown" />

TIP - I also react to keyboard buttons being pressed… Use the left, right, up, down and enter keys to control the jukebox

And thats it…

ClassicJukebox

Conclusion

WPF provides a very powerful infrastructure for creating applications that can mix 3D & hardware effortless! The binding architecture and command support allows for great separation of concerns!

And probably the most important advantage of WPF? It makes writing applications fun…

About the author

Rudi Grobler’s main area of interest is development in the embedded space (his day-to-day job). In the last 10 years Rudi interfaced to various devices in the embedded space ranging from Graphic LCDs using parallel port, various bill acceptors, RoboHum, smart card readers, Wii remote, data acquisition devices, petrol pumps and much, much more!About 2 years ago, he received a copy of Charles Petzold’s WPF book and fell in love…

His ramblings can be found at http://dotnet.org.za/rudi

Read the full article →

Who made my text circular?

May 14, 2009

Step5_SettingUpAnimation Ever see text following a path and wonder how they did that?  Silverzine shows you how to make text that will follow a circular path and rotate.

SilverZine uses Expression Blend to accomplish this tutorial.  They talk about how to keyframe it, space items out, and use the render transform origin.

Read the full article →

Hopping in Silverlight

May 12, 2009

frogger_original Michael Ceranski has an article over at Code Project about recreating the classic game Frogger in Silverlight.

Michael goes in about creating sprites, collision detection, and animation.  He created lanes for the traffic in design time then made them transparent when the application loaded.  Smart!

Nice job Michael.

Read the full article →

Building Multiplayer Texas Holdem Poker For The Zune

May 5, 2009

clip_image002Have you ever been interested in creating a game that harnesses XNA’s powerful network library to create multiplayer experiences for the Zune device?

The Zune firmware version 3.1 brought us a professionally built incarnation of Texas Holdem that supports network play. Understanding how to send and receive data with the Zune can be a little daunting at first, but once you understand the pattern, it’s easy.

To build out the entire game, you probably need about a week, but you can build some simpler examples in far less time.

This is an earlier project from before the release of my Zune game development book. Accordingly, some of the code samples you see in this article may be inconsistent with what you find in the download. The code in the article is the “correct” way to do things. The code in the download is still a work in progress.

The Workflow

Developing multiplayer games for the Zune is interesting because you have to deploy to each device individually. Once you have a build that works for you, it’s helpful to run-deploy (Control+F5) to one device, leave it running there, and then plug in the other Zune and debug-deploy (F5) to it. This way you have one debuggable instance of the game running. Make sure to set the appropriate Zune device as the default in the XNA Game Studio Device Center (accessible from the Tools menu).

Starting A Network Session

Because the Zunes connect over an ad-hoc, peer-to-peer connection rather than through an access point, you will have to designate one Zune as the host device. The host is usually determined to be the one that creates a new game. Therefore, all Zunes that join the host’s network session are simply peers. The difference between the host and the peers is that the host usually maintains the game state on top of executing the game as well, because the game data has to be centralized somewhere. Keep that in mind, because if one Zune is doing substantially more processing, it can lag behind and mess up your network session. Also, remember that all Zunes are running the exact same copy of the game, so the game must support both host and peer scenarios.

Create / Join / Lobby Model

Most peer-to-peer connected games allow a user to create or join a game. After doing so, the player is funneled into an area called the Lobby where they can specify their readiness. When all players are ready, the host can start the game. Some of this functionality is provided directly by the XNA Framework’s Net and GamerServices libraries.

I normally create three separate screens based on the Network Game State Management sample from the Creators Club website. The first is the Create screen, which looks exactly like a lobby. It starts up a network session and waits for players to join and become ready. The code to create a network session looks like this (note that I have employed some abstraction to make my code a little more cohesive):

C#

public void CreateZuneSession(int maxNetworkPlayers)
{
    KillSession();

    try
    {
        Session = NetworkSession.Create(NetworkSessionType.SystemLink, 1,
            maxNetworkPlayers);
        Me = Session.LocalGamers[0];
    }
    catch (NetworkNotAvailableException)
    {
        throw new NetworkNotAvailableException("Zune wireless is not
            enabled.");
    }
    catch (NetworkException ne)
    {
        throw ne;
    }

    if (Session == null)
        throw new NetworkException("The network session could not be
            created.");
}

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, “Courier New”, courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

All Zune network sessions are of the type SystemLink, much like LAN-networked Xbox consoles. The ‘1’ parameter specifies the number of local players – of course, on a Zune, there can only be one.

This line of code sets the Session property to a newly created network session. The Join screen, running on another Zune, will find this session asynchronously as an available network session and attempt to join it. The first step is to enumerate available network sessions:

C#

/// <summary>
/// Asynchronous: Begins to discover network sessions.
/// </summary>
public void BeginGetAvailableSessions()
{
    // Destroy any existing connections
    KillSession();

    NetworkSession.BeginFind(NetworkSessionType.SystemLink, 1, null, new
        AsyncCallback(SessionsFoundCallback), null);
}

This code looks for SystemLink sessions and calls the callback method SessionsFoundCallback when the operation completes (successfully or unsuccessfully). If sessions are found, an event is fired. Other screens can subscribe to this event and transition to other screens or do other processing with the network session.

C#

/// <summary>
/// Called when network sessions are found.
/// </summary>
/// <param name="result"></param>
public void SessionsFoundCallback(IAsyncResult result)
{
    AvailableNetworkSessionCollection availableSessions = null;
    availableSessions = NetworkSession.EndFind(result);

    if (NetworkSessionsFound != null)
        NetworkSessionsFound(availableSessions);
}        

When all players are ready and the host presses the middle button, the network session’s StartGame() method is called, which will cause all connected peers to receive a GameStarted event. This loads up the playing screen.

C#

if (allPlayersReady && atLeastTwoPlayers)
{
    if (ScreenManager.Network.Session != null)
        ScreenManager.Network.Session.StartGame();
}

That’s basically how to connect up two Zunes in a network session. See my book for a much more detailed explanation.

Dealing With Cards

As Poker is a card game, you might want to develop a testable, standalone library that you can use not only to house your objects, but also to write out all the intense logic required for a game like poker. The task of determining what a player’s best hand is out of seven cards (and whether it beats another player’s hand) is more in-depth than you might expect.

An easy way to go about this is to create a Zune game library. I called mine CardLib. CardLib has objects such as these:

  • Card which has a suit, a value, some comparers and some utility methods)
  • Deck, which has a collection of cards and methods like Shuffle, ResetDeck, etc.
  • Dealer, which has a deck, a list of the five community cards, and methods like Shuffle, DealCard, Burn, DealFlop, DealTurn, etc.
  • HoldemHand, which contains all of the logic for determining what a hand is (always 7 cards)
  • BestHand, which takes a HoldemHand and determines what the best possible hand is within that hand

Shuffling Cards

Shuffling cards is surprisingly easy. I use the Knuth-Fisher-Yates shuffling algorithm, which takes every card in the deck and randomly swaps it with another.

C#

/// <summary>
/// Knuth-Fisher-Yates shuffling algorithm:
/// http://www.codinghorror.com/blog/archives/001015.html
/// </summary>
public void Shuffle()
{
    Random rand = new Random();
    for (int cardIndex = _cards.Count - 1; cardIndex > 0; cardIndex--)
    {
        int randomIndex = rand.Next(cardIndex + 1);
        SwapCardsByIndex(cardIndex, randomIndex);
    }
    _dealIndex = 0;
}

Poker Logic

An example method you’ll see in this library is this snippet to check if the hand is a royal flush:

C#

public bool IsRoyalFlush(out List<Card> winningCards)
{
    List<Card> straightFlushCards;

    if (IsStraightFlush(out straightFlushCards))
    {
        // Check to make sure the straight flush cards are: 10 J Q K A
        straightFlushCards.Sort();

        if (straightFlushCards[0].Value == 10 &&
            straightFlushCards[1].Value == Card.Jack &&
            straightFlushCards[2].Value == Card.Queen &&
            straightFlushCards[3].Value == Card.King &&
            straightFlushCards[4].Value == Card.Ace)
        {
            winningCards = straightFlushCards;
            return true;
        }

        else
        {
            winningCards = null;
            return false;
        }
    }
    else
    {
        winningCards = null;
        return false;
    }
}

There is a ton of similar and even more disgusting logic to peruse in the HoldemHand.cs file in the region entitled “Poker Logic Fun Times.” This logic covers every possible poker hand and could probably be refactored to be way more elegant.

When it comes time to evaluate the winner, each player’s best hand is determined and they are evaluated against each other to determine the winner. This code returns a list of WinnerInfo objects, which returns the player info and a list of the cards they won with.

C#

public List<WinnerInfo> DetermineWinners()
{
    BestHand overallBestHand = null;
    HoldemPlayer winner = null;

    List<WinnerInfo> winners = new List<WinnerInfo>();

    foreach (HoldemPlayer player in _players)
    {
        if (player.Status != PlayerStatus.Folded)
        {
            HoldemHand tempHand = new HoldemHand(player.Pocket, _communityCards);
            BestHand bestHand = tempHand.GetBestHand();

            if (overallBestHand == null) // if there is no best hand yet
            {
                overallBestHand = bestHand;
                winner = player;
                winners.Add(new WinnerInfo(overallBestHand, winner, Me));
            }
            else
            {
                // if this hand beats the current best hand
                if (BestHand.Beats(bestHand, overallBestHand))
                {
                    winners.Clear();
                    overallBestHand = bestHand;
                    winner = player;
                    winners.Add(new WinnerInfo(overallBestHand, winner, Me));
                }
                else
                {
                    if (BestHand.IsEquivalentTo(bestHand, overallBestHand))
                    {
                        winners.Add(new WinnerInfo(bestHand, player, Me));
                    }
                }
            }
        }
    }

    _winners = winners;
    return winners;
}

Drawing Cards On The Screen

Rather than have 52 different sprites that represent each possible card, I just made my own sheet of Zune-sized playing cards. Horizontally, they are ordered by value (1-13) and vertically they are ordered by suit (both alphabetically and corresponding to the numeric value of the Suit enumeration in the project, 1-4).

clip_image004

When a specific card is requested to be drawn, a formula is used to calculate the source rectangle from this larger image. This is very similar to how fonts worked before spritefonts were introduced into XNA. This allows us to strip out the graphic of a specific card and draw it onscreen at some other location.

C#

private void DrawCard(Card card, Vector2 position)
{
    if (card != Card.Undefined && card.Suit != Suit.Unassigned)
        ScreenManager.SpriteBatch.Draw(_texDeck, position, GetCardSourceRect(card), Color.White);
}

private Rectangle GetCardSourceRect(Card card)
{
    if (card.Suit == Suit.Unassigned)
        throw new ArgumentException("Unassigned cards cannot be drawn.");

    int cardColumn = card.Value - 1;
    int cardRow = (int)card.Suit - 1;

    int x = cardColumn * MainScreenElements.CARD_WIDTH;
    int y = cardRow * MainScreenElements.CARD_HEIGHT;

    return new Rectangle(x, y, MainScreenElements.CARD_WIDTH, MainScreenElements.CARD_HEIGHT);
}

Managing Network Data

One thing that increases the complexity of this game (in no small way) is the management of network data. First of all, the host’s actions are a superset of the peer’s actions (a host is also a peer, but it also has to manage the game and network state). For example, when a peer decides to bet, it has to send a message to the host saying “I would like to bet,” and then the host will process that message and relay it to the other peers. The host is also responsible for managing whose turn it is and determining who the winner is. Theoretically, you could do a lot of this with every peer acting equally but it feels safer to me to have the host responsible for important activities like dealing cards. In fact, the host has to be the only one who can deal cards, because if each client maintained its own deck, it would be randomized for every peer when the deck is shuffled.

How Data Is Sent And Received

I will usually create a static class called NetworkMessageSender that is responsible for sending various messages. I keep an enumeration of type byte that holds the possible network messages.

I always send the byte indicating the message type first, so that when the peer receives a byte, it knows how to respond. For example, if the peer receives a CardDealt message, it can pop off a string and a card from the incoming packets. If the card is not intended for the peer, it can simply discard the message.

Data you want to send is written to a packet writer object. When the data is ready to be sent, you call the SendData method of the LocalGamer object. Depending on how important packet receipt is, you can specify the type of transmission. I use ReliableInOrder during poker because network data is exchanged relatively infrequently. Although there is only one local network gamer, you can use a foreach loop to ensure this code will work on other platforms.

C#

private static void SendData()
{
    foreach (LocalNetworkGamer gamer in NetworkSessionManager.Session.LocalGamers)
        gamer.SendData(NetworkSessionManager.PacketWriter, SendDataOptions.ReliableInOrder);
}

Specific chunks of data are then sent using various static methods. Each piece of information is written sequentially. The card is serialized into a string format before being sent. The following chunk of code is used to send a card to a player.

C#

public static void DealCards(HoldemPlayer player)
{
    NetworkSessionManager.PacketWriter.Write((byte)NetworkMessageType.Deal);
    NetworkSessionManager.PacketWriter.Write(player.Name);
    NetworkSessionManager.PacketWriter.Write(player.Pocket.Card1.Serialize());
    NetworkSessionManager.PacketWriter.Write(player.Pocket.Card2.Serialize());
    SendData();
}

On the other side of that, whenever the screen updates, the game is constantly checking for new network data. The following code is part of a method that is called from the game screen’s Update loop.

C#

private void UpdateNetworkSession()
{
    NetworkSessionManager.Update();

    foreach (LocalNetworkGamer localGamer in
        NetworkSessionManager.Session.LocalGamers)
    {
        while (localGamer.IsDataAvailable)
        {
            NetworkGamer sender;
            localGamer.ReceiveData(NetworkSessionManager.PacketReader,
                out sender);

            // Interpret the first piece of information, the message.
            NetworkMessageType message = (NetworkMessageType)NetworkSessionManager.PacketReader.ReadByte();

            // Determine what to read and what to do based on this message type
            switch (message)
            {
                // major snippage
                case NetworkMessageType.Deal: // Happens when a card is dealt
                {
                    string playerName = NetworkSessionManager.PacketReader.ReadString();
                    string card1 = NetworkSessionManager.PacketReader.ReadString();
                    string card2 = NetworkSessionManager.PacketReader.ReadString();

                 _gameplayManager.Players[playerName].Pocket.Set(PlayerPocket.FIRST_CARD_INDEX, new
                    Card(card1));
                 _gameplayManager.Players[playerName].Pocket.Set(PlayerPocket.SECOND_CARD_INDEX, new
                    Card(card2));
                }
                break;
            }
        }
    }
}

There is a whole bunch of similar code that underlies how the game executes. When a message needs to be sent, the NetworkMessageSender class is used. To determine what happens when a message is received, we look at that ginormous switch statement that gets called in the screen update loop.

Remember that the host is also a peer and it will receive the very same messages it sends (unless you specify otherwise). Be careful not to double-process messages if they are sent by the host. In some cases you will need to check that the current device is or is not the host. In the sample download, this is achieved just by checking a Boolean value that is set early on in the game.

Conclusion

Building Poker for the Zune, from the ground up, is no small feat! Networked Zune games are far simpler when you have a much more limited set of possible data and messages that could be sent. For example, networked Pong, Battleship or Tetris would be pretty easy compared to poker. Turn-based games on the Zune also provide an interesting challenge in terms of what happens when a Zune drops from the network session.

This is just a small dip into networked Zune game development. For a deep dive, check out my book, Zune Game Development using XNA 3.0, also available on Apress.com as an eBook. The final chapter is a sprawling 120 pages covering how to build Crazy Eights for the Zune from the ground up.

About The Author

Dan Waters is an Academic Developer Evangelist at Microsoft, based in Tampa, FL. When he’s not out showing the latest and greatest MS technology to students and faculty, he’s spending time with his wife and young daughter or rocking out on one of his (far too numerous) guitars. Follow Dan on Twitter or check out his blog.

Read the full article →

Glimmering with effects

May 1, 2009

clip_image002

Ever see a website with some amazing effects but no clue how they got them?  Chances are they used a framework like jQuery.  Glimmer is a WPF-based Windows application that allows you to easily create interactive elements on your web pages by harnessing the power of the jQuery library. Without having to hand-craft your JavaScript code, you can use Glimmer’s wizards to generate jQuery scripts for common interactive scenarios. Glimmer also has an advanced mode, providing a design surface for creating jQuery effects based on your existing HTML and CSS.

Feel free to blog/tweet if so inclined! You can use screenshots of Glimmer from this post or the attached banner. Also, you can embed the video about Glimmer using this HTML:

<object data="data:application/x-silverlight-2," type="application/x-silverlight-2" width="304" height="228">
<param name="source" value="http://channel9.msdn.com/App_Themes/default/VideoPlayer2009_02_24.xap" />
<param name="initParams" value="m=http://mschannel9.vo.msecnd.net/o9/mix/labs/glimmer/glimmer.wmv,autostart=false,autohide=true,showembed=true, thumbnail=http://mschannel9.vo.msecnd.net/o9/mix/labs/glimmer/glimmerVideo.jpg, postid=0" />
<param name="background" value="#00FFFFFF" />
<a href="http://go.microsoft.com/fwlink/?LinkID=124807" style="text-decoration: none;">
<img src="http://go.microsoft.com/fwlink/?LinkId=108181" alt="Get Microsoft Silverlight" style="border-style: none"/>
</a>
</object>

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, “Courier New”, courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

And, if you end up using Glimmer, let us know your feedback. If you deploy any Glimmer generated code/scripts, let us know so we can add it to the Sites Using Glimmer wiki.

Read the full article →

Developing for Window 7 – Taskbar

April 14, 2009

image_3CF291E8[1] Yochay Kiriaty has a blog post about developing for the Windows 7 task bar.

Yochay goes one by one on the demos.  The included demos are:

  • Web Browser
  • IM Client
  • Document Reader
  • Main Demo

The main demos demonstrates how to handle a multitude of basic functionality.

The samples and .Net libraries so you can develop against it can be found over at http://code.msdn.microsoft.com/Windows7Taskbar/Release/ProjectReleases.aspx

Read the full article →