Freigeben über


Dieser Artikel wurde maschinell übersetzt.

Neue Benutzeroberflächentechnologien

Farbscrolling für XNA

Charles Petzold

Downloaden des Codebeispiels

image: Charles PetzoldEines der ersten Windows-Programme, die ich für die Publikation habe, COLORSCR (“ Farbe Bildlauf ”) aufgerufen wurde, und es wurde in der -Ausgabe Mai 1987 Microsoft Systems Journal , dem Vorgänger in diesem Magazin.

Im Laufe der Jahre habe ich häufig es aufschlussreich, Schreiben Sie dieses Programm für die anderen APIs und Frameworks gefunden. Obwohl das Programm einfach ist – Sie drei Bildlaufleisten oder die Schieberegler für die Rot-, Grün- und Blau-Werte zum Erstellen einer benutzerdefinierten Farbe bearbeiten – Sie wichtige Aufgaben, wie das Layout und die Ereignisbehandlung umfasst. In Funktionen ist auch das Programm nicht unbedingt eine einfache, bedeutungslosen Demo. Wenn Sie jemals eine Farbauswahl Dialogfeld erstellen gefunden, wäre dieses Programm ein guter Ausgangspunkt.

In diesem Artikel möchte ich Ihnen zeigen, wie ein mit XNA Framework gemäß der Implementierung in Windows Telefon 7 Farbe Scroll-Programm zu schreiben. Abbildung 1 , ist das Ergebnis angezeigt.

image: The Xnacolorscroll Program

Abbildung 1 Die Xnacolorscroll-Programm

XNA ist Microsoft .NET Framework-basierten verwalteten Code für die Programmierung von Spielen, aber wenn Sie starten, durchsucht die Namespaces von Microsoft.XNA.Framework wird nicht auffindbar keine Bildlaufleisten oder Schieberegler oder sogar Schaltflächen zwischen den Klassen! XNA ist einfach nicht diese Art des Frameworks. Auf Wunsch einen Schieberegler in Ihrem Programm müssen Sie speziell für diesen Auftrag erstellt werden.

Zeigt Ihnen, wie ein Bildlauf Farbe XNA-Programm zu schreiben, ist lediglich eine akademische Übung jedoch nicht. Meine Absicht ist tatsächlich wesentlich breitere.

Wie Sie wissen, Windows Telefon 7 unterstützt Silverlight und XNA und in der Regel für eine bestimmte Anwendung die Wahl zwischen den beiden offensichtlich ist. Jedoch können Sie feststellen, dass die grafischen Anforderungen Ihrer Anwendung einfach zu viel für Silverlight jedoch zur gleichen Zeit, die Sie möglicherweise zum XNA stattdessen verwenden, da bekannte Amenities, z. B. Schaltflächen und Schieberegler fehlen zögern.

Meine Antwort lautet: Führen Sie nicht leider. Einfache Steuerelemente im XNA schreiben ist einfacher, als Sie wahrscheinlich denken.

Sie können in diesem Artikel auch eine Einführung in die Programmierung für Windows Presentation Foundation (WPF) und Silverlight-Programmierer XNA berücksichtigen. Ich habe mich bestimmte Konzepte daher XNA-Farbe Scroll-Programm ist eine Feier der Synergie sowie von WPF und Silverlight, die diesem Auftrag anwenden.

Der herunterladbare Quellcode ist in einer Visual Studio-Projektmappe XnaColorScroll aufgerufen. Diese Lösung enthält ein Projekt XnaColorScroll für Windows Telefon 7 und eine Bibliothek mit dem Namen Petzold.Xna.Controls mit den vier XNA “ Steuerelementen ”, die ich für dieses Programm erstellt. (Natürlich muss beim Laden der Projektmappe in Visual Studio installiert Windows Telefon-Entwicklungstools sein.) Können Sie diese Steuerelemente zu stehlen und ergänzen Sie mit Ihrer eigenen für eigene Steuerelemente XNA-Bibliothek.

Spiele und Komponenten

Ebenso wie die Hauptklasse von WPF, Silverlight oder Windows Forms-Programm eine Klasse, die vom Fenster, Formular oder Page abgeleitet wird ist, ist die Hauptklasse eines Programms XNA vom Spiel abgeleitet. Ein XNA-Programm verwendet dieses Spiel Ableitung zum Zeichnen von Bitmaps, Text und 3D-Grafik auf dem Bildschirm.

Mit deren Hilfe Sie Ihr Programm in diskrete funktionalen Einheiten, XNA unterstützt das Konzept der für eine Komponente organisieren die vielleicht am nächsten ist stammt, XNA auf ein Steuerelement. Komponenten werden in zwei Varianten: GameComponent Ableitungen und DrawableGameComponent Ableitungen. DrawableGameComponent selbst abgeleitet von GameComponent und die Differenz vorschlagen. Ich werde beiden Basisklassen in dieser Übung verwenden.

Die Spiel-Klasse definiert eine Eigenschaft mit dem Namen des Typs GameComponentCollection Komponenten. Alle Komponenten, die ein Spiel, müssen dieser Auflistung hinzugefügt werden. Dadurch wird sichergestellt, dass die Komponente ruft das Spiel selbst ruft die gleichen Aufrufe an verschiedenen überschriebenen Methoden ab. Ein DrawableGameComponent zeichnet sich über den Inhalt des Spiels zeichnet.

Die Analyse des Programms XnaColorScroll Let’s zu beginnen, nicht mit dem Spiel Ableitung, jedoch mit GameComponent-Ableitungen. Abbildung 2 zeigt dem Quellcode für eine Komponente TextBlock aufgerufen, und es ist in fast genauso wie eine WPF- oder Silverlight-TextBlock verwendet.

Abbildung 2 der TextBlock Game-Komponenten

public class TextBlock : DrawableGameComponent
{
  SpriteBatch spriteBatch;
  Vector2 textOrigin;

  public TextBlock(Game game) : base (game)
  {
    // Initialize properties
    this.Color = Color.Black;
  }

  public string Text { set; get; }
  public SpriteFont Font { set; get; }
  public Color Color { set; get; }
  public Vector2 Position { set; get; }
  public HorizontalAlignment HorizontalAlignment { set; get; }
  public VerticalAlignment VerticalAlignment { set; get; }

  public Vector2 Size
  {
    get
    {
      if (String.IsNullOrEmpty(this.Text) || this.Font == null)
          return Vector2.Zero;

      return this.Font.MeasureString(this.Text);
    }
  }

  protected override void LoadContent()
  {
    spriteBatch = new SpriteBatch(this.GraphicsDevice);
    base.LoadContent();
  }

  public override void Update(GameTime gameTime)
  {
    if (!String.IsNullOrEmpty(Text) && Font != null)
    {
      Vector2 textSize = this.Size;
      float xOrigin = (int)this.HorizontalAlignment * textSize.X / 2;
      float yOrigin = (int)this.VerticalAlignment * textSize.Y / 2;
      textOrigin = new Vector2((int)xOrigin, (int)yOrigin);
    }
    base.Update(gameTime);
  }

  public override void Draw(GameTime gameTime)
  {
    if (!String.IsNullOrEmpty(Text) && Font != null)
    {
      spriteBatch.Begin();
      spriteBatch.DrawString(this.Font, this.Text, this.Position, this.Color,
                            0, textOrigin, 1, SpriteEffects.None, 0);
      spriteBatch.End();
    }
    base.Draw(gameTime);
  }
}

Beachten Sie die öffentlichen Eigenschaften, die nach den Konstruktor in Abbildung 2 . Diese Werte geben dem Text selbst und Schriftart, Farbe oder Position von Text relativ zum Bildschirm an. Zwei zusätzliche Eigenschaften HorizontalAlignment und VerticalAlignment, ermöglichen diese Position auf der Seite oder in der Mitte der Textzeichenfolge zu verweisen. In XnaColorScroll sind diese Eigenschaften für das Zentrieren von Text relativ zu den Schiebereglern bereit.

Die Klasse enthält auch eine nur Get-Size-Eigenschaft, die die Größe des gerenderten Textes mit dieser bestimmten Schriftart zurückgibt. (Die Vector2 XNA-Struktur wird häufig für die Darstellung von zweidimensionalen Positionen und Größen sowie Vektoren verwendet.)

TextBlock-Komponente überschreibt Update sowohl Draw-Methode ist für eine Komponente zeichenbaren normal und für Game Ableitungen auch normal. Diese beiden Methoden bilden die des Programms “ Spiel Schleife ” und diese aufgerufen, mit der gleichen Geschwindigkeit als Videoanzeige an – 30 Mal pro Sekunde für Telefon 7. Sie können von der Draw-Methode wie z. B. eine WM_PAINT-Nachricht oder eine Überschreibung OnPaint vorstellen, abgesehen davon, dass Sie für jeden Bildschirmaktualisierung aufgerufen wird. Das Update-Methode aufgerufen wird, bevor jede Draw aufzurufen und ist vorgesehen für die Durchführung der erforderlichen Berechnungen und als Vorbereitung für die Draw-Methode verwendet werden.

TextBlock geschrieben hat viel Platz für die Leistungsverbesserungen. Es könnte z. B. Zwischenspeichern den Wert der Size-Eigenschaft oder nur das Feld TextOrigin neu berechnen, bei jeder Änderung eine Eigenschaft, die dazu beiträgt. Diese Verbesserungen können Priorität in Anspruch nehmen, wenn Sie schon einmal feststellen, dass die Anwendung gering geworden ist, da alle Update- und zeichnen Aufrufe in der Anwendung dauert länger als 0.03 Sekunden ausgeführt werden.

Komponenten und untergeordnete Komponenten

Wie Sie sehen können, in Abbildung 1 hat XnaColorScroll sechs TextBlock-Komponenten aber auch drei Schieberegler, die Benutzer wahrscheinlich etwas schwieriger werden.

Vor sehr vielen Jahren ich haben möglicherweise versucht den gesamten Schieberegler in einer einzelnen Klasse codieren. Meine Erfahrung in WPF und Silverlight Steuerelementvorlagen erkennen jedoch ich, dass der Schieberegler Steuerelement am besten möglicherweise Zusammenstellen eines Thumb-Steuerelements und RepeatButton-Steuerelemente erstellt werden. Es scheint, können Sie versuchen, eine XNA Slider-Komponente aus ähnlichen untergeordnete Komponenten zu erstellen.

Eine Spiel Klasse fügt untergeordnete Komponenten auf sich selbst durch seine Komponenten-Eigenschaft des Typs GameComponentCollection hinzugefügt. Die große Frage nun sieht folgendermaßen aus: Verfügt die GameComponent selbst eine Komponenten-Eigenschaft für die untergeordneten Komponenten?

Leider ist die Antwort nicht. Allerdings eine Komponente hat Zugriff auf die übergeordnete Game-Klasse, und wenn die Komponente eine eigene untergeordnete Komponenten instanziieren muss, können diese zusätzlichen Komponenten in die gleiche Sammlung der Komponenten der Game-Klasse hinzufügen. Dazu in der richtigen Reihenfolge, und Sie müssen nicht selbst mit der Eigenschaft DrawOrder experimentieren, um – durch DrawableGameComponent definiert, mit der Reihenfolge, in der Komponenten gerendert werden, können. Standardmäßig ist die Draw-Methode in der Klasse Spiel dann alle Zeichnen Methoden in den Komponenten zunächst aufgerufen, in der Auflistung der Komponenten angezeigt werden.

Also let’s beginnen. Wie TextBlock wird Sie von DrawableGameComponent Thumb-Klasse abgeleitet. Die gesamte Thumb-Klasse außer für die Touch-Verarbeitung wird im Abbildung 3 angezeigt. Thumb definiert die gleichen drei Ereignisse als WPF und Silverlight-Thumb-Steuerelemente.

Abbildung 3 Thumb-Klasse die meisten

public class Thumb : DrawableGameComponent
{
  SpriteBatch spriteBatch;
  Texture2D tinyTexture;
  int?
touchId;

  public event EventHandler<DragEventArgs> DragStarted;
  public event EventHandler<DragEventArgs> DragDelta;
  public event EventHandler<DragEventArgs> DragCompleted;

  public Thumb(Game game) : base(game)
  {
    // Initialize properties
    this.Color = Color.White;
  }

  public Rectangle Position { set; get; }
  public Color Color { set; get; }

  protected override void LoadContent()
  {
    spriteBatch = new SpriteBatch(this.GraphicsDevice);
    tinyTexture = new Texture2D(this.GraphicsDevice, 1, 1);
    tinyTexture.SetData<Color>(new Color[] { Color.White });

    base.LoadContent();
  }

  ...
public override void Draw(GameTime gameTime)
  {
    spriteBatch.Begin();
    spriteBatch.Draw(tinyTexture, this.Position, this.Color);
    spriteBatch.End();

    base.Draw(gameTime);
  }
}

In der Komponente TextBlock Abbildung 2 stellt die Position-Eigenschaft einen Typ Vector2;in der Bildgröße die Position-Eigenschaft ist ein Rectangle-Objekt und nicht nur den Speicherort der Ziehpunkt, sondern auch die rechteckige Größe definiert. The Thumb visuals consist entirely of a white 1 x 1 pixel bitmap that’s displayed at the location and size indicated by the Position property. (Mit einzelnen Pixel Bitmaps, die zu einer bestimmten Größe gestreckt ist eine meiner bevorzugten XNA Programmiertechniken.)

Der Ziehpunkt Fingereingabe verarbeitet jedoch selbst zu verschieben. Slider-Komponente ist verantwortlich für die Behandlung von DragDelta das Thumb-Ereignisse und eine neue Position-Eigenschaft.

Neben den Ziehpunkt enthält mein Slider auch zwei RepeatButton-Komponenten auf jeder Seite der Ziehpunkt. Wie die WPF und Silverlight RepeatButton-Steuerelemente generieren dieser Komponenten einer Reihe von auf Ereignisse klicken, wenn Sie Ihren Finger auf Sie gedrückt halten.

In meinem XNA-Schieberegler RepeatButton-Komponenten einen bestimmten Bereich des Bildschirms belegt aber eigentlich nicht sichtbar sind. (Die Dünne vertikale Laufleiste entlang der Seitenmitte wird vom Schieberegler selbst gezeichnet.) Dies bedeutet, dass RepeatButton von GameComponent statt DrawableGameComponent abgeleitet werden kann. Abbildung 4 zeigt das gesamte RepeatButton-Steuerelement, außer für die Verarbeitung Touch.

Abbildung 4 Nutzung der RepeatButton-Klasse

public class RepeatButton : GameComponent
{
  static readonly TimeSpan REPEAT_DELAY = TimeSpan.FromMilliseconds(500);
  static readonly TimeSpan REPEAT_TIME = TimeSpan.FromMilliseconds(100);

  int?
touchId;
  bool delayExceeded;
  TimeSpan clickTime; 

  public event EventHandler Click;

  public RepeatButton(Game game) : base(game)
  {
  }

  public Rectangle Position { set; get; }

  ...
}

Zu diesem Zeitpunkt können wir nun Slider-Komponente zu erstellen. Um es relativ einfach gehalten, ich mich in Hochformat eingeschränkt. Schieberegler verfügt über die üblichen öffentlichen Eigenschaften, Minimum, Maximum und Value, u. a. – und definiert auch das ValueChanged-Ereignis. In seiner Initialize-Überschreibung Slider erstellt die drei untergeordneten Komponenten (und speichert Sie als Felder), wird von die Ereignishandlern und Komponentenauflistung ihrer übergeordneten Klasse Spiel über Game-Eigenschaft hinzugefügt:

public override void Initialize()
{
  thumb = new Thumb(this.Game);
  thumb.DragDelta += OnThumbDragDelta;
  this.Game.Components.Add(thumb);

  btnDecrease = new RepeatButton(this.Game);
  btnDecrease.Click += OnRepeatButtonClick;
  this.Game.Components.Add(btnDecrease);

  btnIncrease = new RepeatButton(this.Game);
  btnIncrease.Click += OnRepeatButtonClick;
  this.Game.Components.Add(btnIncrease);

  base.Initialize();
}

XNA Game-Ableitungen und GameComponent Ableitungen haben drei Situationen, in denen die Initialisierung durchführen – Konstruktor der Klasse, die eine Überschreibung der Initialize-Methode und Überschreiben der Methode LoadContent – und es möglicherweise werden etwas verwirrend, verwenden. Wie der Name schon sagt, LoadContent eignet sich hervorragend zum Laden von Inhalten (wie z. B. Schriftarten oder Bitmaps) und sollte für alle Initialisierungen, die auf das Vorhandensein des Objekts GraphicsDevice verwendet werden.

Ich bevorzuge die Komponenten erstellen und diese der Auflistung Komponenten während der Initialize hinzufügen zu überschreiben, wie im vorherigen Codeausschnitt gezeigt. In XnaColorScroll die Spiel abgeleitete Klasse erstellt auch sechs TextBlock-Komponenten, und überschreiben Sie die drei Schieberegler für Komponenten in seiner Initialize. Wenn am Ende die Initialize-Methode in der Basisklasse aufgerufen wird, werden die Initialize-Methoden für die untergeordneten Komponenten bezeichnet. Die Initialize-Methode jedes Slider erstellt dann den Ziehpunkt und die zwei RepeatButton-Komponenten. Dieses Schema wird sichergestellt, dass diese Komponenten eine ordnungsgemäße Reihenfolge für das Rendern von Komponentenauflistung hinzugefügt werden.

Touch-Eingabe verarbeiten

Die wichtigsten Funktionen von Benutzereingaben in den meisten Windows-Telefon 7-Programmen ist multi-touch und XNA bildet hier keine Ausnahme. (Tastatureingaben ist auch XNA-Programmen zur Verfügung stehen und Programme können auch das Telefon Accelerometer als Eingabegerät verwenden.)

Ein XNA-Programm erhält die Fingereingabe während der Update-Überschreibung. Es gibt keine Touch-Ereignisse. Alle Note input abgefragt wird und über die TouchPanel-Klasse zugegriffen werden kann. Die statische Methode, TouchPanel.GetState bietet Low-Level-Fingereingabe, die aus, die angibt, Pressed "," Moved "und" freigegeben-Aktivität mit Position Informationen und Integer-IDs zur Unterscheidung mehrerer Finger TouchLocation-Objekten besteht. Die TouchPanel.ReadGesture-Methode (die ich in diesem Programm nicht verwenden) stellt auf höherer Ebene Stiftbewegung Unterstützung bereit.

Wenn ich zuerst arbeiten mit Komponenten Spiel gestartet, dachte ich, dass jede Komponente konnte Fingereingabe eigenständig zu erhalten, nutzen, was er benötigt und der Rest wird ignoriert. Dies scheint nicht sehr gut funktionieren;Es war, als die Spiel-Klasse und die Komponenten wurden alle Fingereingabe konkurrieren statt wie Kinder höflich freigeben.

Ich habe entschieden, ein anderes System für die Verarbeitung der Fingereingabe zu arbeiten. Nur die Spiel-Klasse ruft TouchPanel.GetState. Dann, jedes Objekt über eine Methode zum untergeordneten Komponenten übergeben wird TouchLocation rufe ich ProcessTouch. Dadurch werden die Komponenten zum ersten Dibs für die Eingabe zu erhalten. Verwenden Sie eine Komponente, die von einer TouchLocation Objekt aus den ProcessTouch-Methode und die weitere Verarbeitung für diesen bestimmten TouchLocation Objekt enden true zurückgibt. (Rückgabe von True aus ProcessTouch ist wie die Handled-Eigenschaft des RoutedEventArgs auf True in WPF oder Silverlight festlegen.)

In XnaColorScroll die Update-Methode in der Klasse in main Spiel aufrufen TouchPanel.GetState erhalten die Berührung eingegeben und ruft dann die Methode ProcessTouch in jeder Slider-Komponente, wie hier gezeigt:

TouchCollection touches = TouchPanel.GetState();

foreach (TouchLocation touch in touches)
{
  for (int primary = 0; primary < 3; primary++)
    if (sliders[primary].ProcessTouch(gameTime, touch))
      break;
}

Beachten Sie, wie die weitere Verarbeitung der einzelnen TouchLocation Objekt beendet wird, bei jedem ProcessTouch true zurückgibt.

Anschließend ruft die ProcessTouch-Methode in jedem Schieberegler-Steuerelement ProcessTouch Methoden in der Thumb-Komponente und die zwei RepeatButton-Komponenten:

public bool ProcessTouch(GameTime gameTime, TouchLocation touch)
{
  if (btnIncrease.ProcessTouch(gameTime, touch))
    return true;

  if (btnDecrease.ProcessTouch(gameTime, touch))
    return true;

  if (thumb.ProcessTouch(gameTime, touch))
    return true;

  return false;
}

Wenn keines dieser Komponenten (oder der Game-Klasse selbst), eine eigene Verarbeitung Touch gewünscht, würde es zunächst ProcessTouch in jedes untergeordneten Elements aufrufen. Objekte, die von den untergeordneten Elementen nicht verarbeiteten blieb TouchLocation kann dann für die Verwendung der Klasse untersucht werden. Dieses Schema ermöglicht wirksam, die visuell oberste Kinder erste Zugriff auf Eingabe-, berühren, die oft genau Ihren Wünschen entspricht. Ähnlich wie die weitergeleitete Ereignisbehandlung in WPF und Silverlight implementiert ist.

Das Thumb- sowohl die RepeatButton sind Fingereingabe möchte, wenn innerhalb des Bereichs, der durch die Komponente Position Rechteck angegebenen zuerst ein Finger davon betroffen ist. Die Komponente zeichnet “ dann ”, Finger durch Speichern der Touch-ID. Alle anderen Fingereingabe mit ID auf diese bestimmte Komponente gehört, bis zur Veröffentlichung der Finger.

Weitergeben von Ereignissen

Die Touch-Verarbeitung der Bildgröße und RepeatButton-Komponenten ist in Wirklichkeit die Crux des Schieberegler-Steuerelements, aber das ist etwas Sie selbst untersuchen können, wenn Sie sich interessieren. Wenn die Thumb-Komponente Finger Bewegung auf die Formularoberfläche erkennt, generiert er DragDelta Ereignisse;auslösende RepeatButton-Komponente tippen oder anhaltende drückt erkennt, klicken Sie auf Ereignisse.

Diese Ereignisse werden von der übergeordneten Slider-Komponente, die seine Value-Eigenschaft entsprechend angepasst, behandelt sowohl das ValueChanged-Ereignis aus den Schieberegler für die auslöst. Der Schieberegler ist auch verantwortlich für die Position-Eigenschaften der Ziehpunkt und die zwei RepeatButton-Komponenten, die basierend auf den neuen Wert festlegen.

Die Spiel-Klasse behandelt ValueChanged-Ereignisse aus den drei Slider-Komponenten in einem einzigen Ereignishandler, damit die Methode einfach neue Werte für die drei TextBlock-Komponenten und eine neue Farbe festgelegt:

void OnSliderValueChanged(object sender, EventArgs args)
{
  txtblkValues[0].Text = sliders[0].Value.ToString("X2");
  txtblkValues[1].Text = sliders[1].Value.ToString("X2");
  txtblkValues[2].Text = sliders[2].Value.ToString("X2");

  selectedColor = new Color(sliders[0].Value, 
                            sliders[1].Value, 
                            sliders[2].Value);
}

Die Überschreibung Zeichnen bleiben mit nur zwei Aufträge in der Klasse Spiel: Zeichnen Sie das schwarze Rechteck, das als Hintergrund der Komponenten dient zu, und zeichnen Sie das Rechteck mit einem neuen SelectedColor auf der rechten Seite. Beide Projekte umfassen eine 1 x 1-Pixel-Bitmap gedehnt, um die Hälfte der Bildschirmgröße.

Besser als Silverlight?

Vor kurzem darüber hinaus habe ich eine Silverlight-Version des Programms Farbe Bildlauf für Telefon 7, und habe ich entdeckt, dass das Programm nur mir einen Schieberegler gleichzeitig bearbeiten dürfen. Wenn Sie das Programm XnaColorScroll an einem Telefon bereitstellen, können Sie alle drei Schieberegler-Steuerelemente jedoch unabhängig voneinander ändern. Ich finde diese Differenz sehr interessant. Es zeigt wieder wie High-Level-Schnittstellen, wie z. B. Silverlight unser Leben viel einfacher machen können, aber oft etwas anderes geopfert werden muss. Ich glaube, das Konzept TANSTAAFL aufgerufen wird: Ain't gibt es keine solche als eine Gratiszugabe ein.

XNA ist in einigen Hinsicht, dass er uns an die Joker-West erinnern könnte also auf niedriger Ebene. Aber mit ein wenig bei Verwenden von Komponenten (z. B. Komponenten, die von anderen Komponenten erstellt wurden) imitiert Routingereignis Behandlung, sogar XNA kann und tamed versucht, wie Silverlight scheint – vielleicht sogar noch besser.

Charles Petzold schreibt seit langem redaktionelle Beiträge für das MSDN Magazine*.*Sein neues Buch “ Programming Windows Telefon 7 ” (Microsoft Press, 2010), steht als kostenloser Download unter bit.ly/cpebookpdf-.

Dank an den folgenden technischen Experten für die Überprüfung der in diesem Artikel: Shawn Hargreaves