Dieser Artikel wurde maschinell übersetzt.

Windows Phone

Schreiben Sie eine Kompass-Anwendung für Windows Phone

Donn Morse

Als ein Writerresponsible für die Sensor-Plattform-Dokumentation für Windows 8 möchte ich sehen, wie viele Entwickler wie möglich unsere neue Plattform verabschieden.Und weil Metro-Stil-Anwendungen mithilfe von XAML und c# geschrieben werden können, ist der Windows Phone-Entwickler ein idealer Kandidat für diese Migration.Windows Phone Entwickler haben bereits e.­Rience mit XAML und einige haben auch Erfahrung mit Sensoren (weil der Beschleunigungssensor, Kompass, Kreiselkompaß und GPS-Sensoren ausgesetzt sind in der neuesten Version Windows Phone).

Um mich besser zu verstehen, Windows Phone Entwickler und ihre Entwicklungsplattform zu helfen, habe ich beschlossen, einen einfachen Kompass app letzten Herbst schreiben.Nachdem ich es geschrieben habe, ich eine kostenlose Version zum Windows Phone Marktplatz mit der App Hub vorgelegt.Seit Annahme wurde von den Windows Phone Benutzern aus so weit entfernt wie Schweiz und Malaysia die app heruntergeladen.

Dieser Artikel behandelt die Entwicklung der Anwendung.

Die Kompass-Anwendung

Die Kompass-Anwendung verwendet den Kompass oder Magnetometer, um das Windows Phone-Gerät gebaut.Diese app bietet eine Überschrift in Bezug auf den geographischen Norden sowie eine wechselseitige Überschrift, die nützlich, beim Navigieren in einem Boot oder Orientierungslauf in einer abgelegenen Gegend mit einer Karte sein kann.Darüber hinaus erlaubt die app wechseln von einer numerischen Überschrift (z. B. "090" Grad) um eine alpha-Überschrift (z.B. "E" für East).Die app erlaubt auch dem Benutzer die aktuelle Überschrift zu sperren.Dies ist nützlich, wenn Benutzer benötigen den Zeiger stationär zu bleiben, so dass sie ein Lager auf einem bestimmten Wahrzeichen oder Verweis auf eine Karte oder ein Diagramm kann.

Abbildung 1 zeigt die Anwendung läuft auf einem Samsung-Fokus.Das Bild links zeigt eine numerische Position und das Bild rechts zeigt eine alpha-Überschrift.

The Running App, Showing a Numeric Heading (Left) and an Alpha Heading (Right)Abbildung 1 die Running App, zeigt eine numerische Position (links) und ein Alpha-Rubrik (rechts)

Gestaltung der Benutzeroberflächenautomatisierungs

Als Entwickler zum Schreiben von Anwendungen für den PC gewöhnt, fühlte ich zunächst begrenzt durch den reduzierten Bildschirmimmobilien am Telefon.Jedoch war dies kein Showstopper.Ich musste nur ein wenig mehr Gedanken geben — und sorgfältiger Überlegung — die Features in meiner app in Bezug auf die neuen Bildschirmabmessungen des.Meine Kompass-app verfügt über zwei Bildschirme: ein Kalibrierungsbildschirm und der Hauptnavigation-Bildschirm.

Kalibrierungsbildschirm der Kompass oder Magnetometer, installiert auf einem Windows Phone Gerät erfordert Kalibrierung, nachdem das Gerät eingeschaltet ist.Darüber hinaus möglicherweise diese Sensoren regelmäßige Neukalibrierung erforderlich.Die Plattform unterstützt, mit denen Sie programmgesteuert ermitteln, wenn Kalibrierung erforderlich ist, eine HeadingAccuracy-Eigenschaft, die Sie verwenden können, um die aktuelle Kalibrierung zu erkennen.Darüber hinaus unterstützt die Plattform ein kalibrieren-Ereignis, das ausgelöst wird, wenn der Kompass Kalibrierung erforderlich ist.

Meine app behandelt das Kalibrieren-Ereignis, das, wiederum ein Kalibrierungsbildschirm (CalibrationStackPanel), das den Benutzer das Gerät manuell kalibrieren zeigt, indem das Telefon in einer Bewegung Abbildung 8 fegen auffordert.Der Benutzer des Telefons fegt, die aktuelle Richtigkeit wird angezeigt in der CalibrationTextBlock mit roter Schrift bis die gewünschte Genauigkeit erreicht ist, wie in Abbildung 2.Sobald die zurückgegebene Genauigkeit kleiner oder gleich 10° ist, die numerischen Werte werden gelöscht und ein grünes "Complete!" erscheint.

The Calibration ScreenAbbildung 2 Kalibrierungsbildschirm

Der entsprechende Code, der die Kalibrierung unterstützt findet sich in dem Modul MainPage.xaml.cs innerhalb der Compass_Current­ValueChanged-Ereignishandler, wie in Abbildung 3.

Abbildung 3 den Kompass kalibrieren

...
else
{
 if (HeadingAccuracy <= 10)
 {
  CalibrationTextBlock.Foreground = 
    new SolidColorBrush(Colors.Green);
  CalibrationTextBlock.Text = "Complete!";
 }
 else
 {
  CalibrationTextBlock.Foreground = 
    new SolidColorBrush(Colors.Red);
  CalibrationTextBlock.Text = 
    HeadingAccuracy.ToString("0.0");
 }
}

Sobald die gewünschte Genauigkeit erreicht ist, wird der Benutzer aufgefordert, die Taste "Fertig", drücken die Kalibrierungsbildschirm verbirgt und zeigt die app primären Bildschirm.

Den primären Bildschirm dieser Bildschirm zeigt eine numerische oder alpha-Überschrift und reziproker Wert. Darüber hinaus macht es das Gesicht der Kompass, der in Bezug auf den geographischen Norden orientiert hat. Schließlich der primären Bildschirm zeigt die vier steuert (Tasten oder), mit denen den Benutzer die Ausgabe als verändern sowie Sperre den Überschrift Wert und Kompass Gesicht.

Abbildung 4 zeigt meine Bewerbung primären Bildschirm, MainPage.xaml in Visual Studio angezeigt wird.

The App’s Primary Screen in Visual Studio
Abbildung 4 die App den primären Bildschirm in WinForms

Die meisten Elemente der Benutzeroberfläche in den primären Bildschirm sind einfache TextBlock und Button-Steuerelemente. Die Textblöcke identifizieren die Überschrift und dessen reziproker Wert. Die Schaltflächen ermöglichen den Benutzer, die Ausgabe zu steuern. Das Kompass Gesicht ist jedoch ein wenig komplizierter.

Das Kompass-Gesicht Kompass Gesicht besteht aus drei Komponenten: ein Hintergrundbild, ein Vordergrundbild und eine größere angrenzenden Ellipse in dem Vordergrund und Hintergrund Bilder drehen. Das Hintergrundbild enthält die Buchstaben, die vier Punkte auf einen Kompass, eine horizontale und eine vertikale Linie entspricht. Das Vordergrundbild erstellt den geraucht-Glass-Effekt.

Das Hintergrundbild In das XAML, das Hintergrundbild wird benannt CompassFace (diese Variable Name später in den Code, der die Kompass Fläche dreht verwiesen wird):

<Image Height="263" HorizontalAlignment="Left" Margin="91,266,0,0"
  Name="CompassFace" VerticalAlignment="Top" Width="263"  
  Source="/Compass71;component/compass.png" Stretch="None" />

Das Vordergrundbild der Vordergrund des Kompass Gesicht, EllipseGlass, in der XAML selbst definiert ist. Die geraucht-Glas-Effekt wird mit einem linearen Farbverlauf Pinsel erstellt. Ich habe diese Ellipse mit Microsoft Expression Blend 4. Das Expression Blend-Tool ist kompatibel mit Visual Studio und Laden der Anwendung XAML und erweitert die Benutzeroberfläche durch die Grafik anpassen. Abbildung 5 die Expression Blend Editor zeigt, wie es beim Erstellen der schattierten Ellipse.

Creating a Shaded Ellipse in Expression Blend
Abbildung 5 eine schattierte Ellipse in Expression Blend erstellen

Nachdem ich die Ellipse in Expression Blend bearbeiten, wurde das XAML in meinem Visual Studio-Projekt mit den folgenden XML-Code aktualisiert:

<Ellipse Height="263"  Width="263" x:Name="EllipseGlass" 
  Margin="91,266,102,239" Stroke="Black" StrokeThickness="1">
  <Ellipse.Fill>
    <LinearGradientBrush EndPoint="1,0.5" StartPoint="0,0.5">
    <GradientStop Color="#A5000000" Offset="0" />
    <GradientStop Color="#BFFFFFFF" Offset="1" />
    </LinearGradientBrush>
  </Ellipse.Fill>

Beachten Sie, dass die Abmessungen des EllipseGlass (263 x 263 Pixel) eine genaue Übereinstimmung der Dimensionen des compass.png. Beachten Sie auch, dass die zu verwendenden Objektnamen, EllipseGlass, später im Code verwiesen wird, die die Drehung des Kompass Gesichts führt.

Der Kompass-Gesicht-Grenze Kompass Gesicht dreht sich innerhalb eines größeren, weißen Ellipse mit einem roten Rand. Diese Ellipse in XAML definiert und mit dem Namen EllipseBorder:

<Ellipse Height="385" HorizontalAlignment="Left" Margin="31,0,0,176"
  Name="EllipseBorder" Stroke="#FFF80D0D" StrokeThickness="2"
  VerticalAlignment="Bottom" Width="385" Fill="White" />

Der Code hinter der Benutzeroberfläche

Der Code befindet sich in der Datei MainPage.xaml.cs im Codedownload und es greift auf die von der Anwendung benötigte Namespaces, initialisiert den Sensor, ein Berichtintervalls und behandelt die verschiedenen Anwendungsfunktionen der: Kalibrierung, rotierende Kompass Gesicht, Umschalten zwischen numerischen und Alpha ausgeben und so weiter.

Zugriff auf den Kompass in Your Code der erste Schritt beim Schreiben eine Kompass-Anwendung (oder einer beliebigen Anwendung, die einer der Sensoren Telefon zugreift) ist der Sensor-Objekte durch den Namespace Microsoft.Devices.Sensors zu Ihrem Recht. Dies geschieht mit folgendem using-Direktive in MainPage.xaml.cs:

using Microsoft.Devices.Sensors;

Diese mithilfe der Richtlinie erscheint in der Datei kann ich eine Kompass-Variable, die gibt mir den programmatischen Zugriff auf das eigentliche Gerät in das Telefon zu erstellen:

namespace Compass71
{
  public partial class MainPage : PhoneApplicationPage
  {
    Compass compass = new Compass();

Ich werde diese Variable verwenden, starten Sie den Kompass, Hör, Abrufen der aktuellen Rubrik Genauigkeit, das Berichtsintervall festlegen und so weiter.

Starten des Kompasses und Einrichten der Bericht-Frequenz sobald ich die Kompass Variable erstellen, kann ich beginnen, Aufrufen von Methoden und Festlegen von Eigenschaften für das Objekt. Die erste Methode, die ich aufgerufen ist die Start-Methode, die mir erlaubt, empfangen Daten vom Sensor. Nachdem ich den Kompass starten, ich das Berichtsintervall festlegen – die Zeit zwischen Sensor Aktuelles — bis 400 ms (Beachten Sie, dass die TimeBetweenUpdates-Eigenschaft ein Vielfaches von 20 ms erfordert):

compass.TimeBetweenUpdates = 
  TimeSpan.FromMilliseconds(400);  // Must be multiple of 20
compass.Start();

Der Wert 400 ms gewählt von Versuch und Irrtum. Das Standardintervall Bericht ist extrem kurz. Wenn Sie versuchen, die Anwendung auf diesen Standardwert ausgeführt, wird das Kompass Gesicht so häufig gedreht, dass es scheint instabil sein.

Über die Kompass-Ereignishandler die Kompass-app unterstützt zwei Ereignishandler: eine, die die Kalibrierung Seite zeigt (Kalibrierung­StackPanel), und ein anderes, das macht die aktuelle Position und dreht das Kompass Gesicht.

Definition und Festlegung der Kalibrierung-Ereignishandler der Kalibrierung-Ereignishandler enthält relativ wenige Codezeilen. Dieser Code angezeigt, Abbildung 6, erfüllt zwei Hauptaufgaben: Es zeigt zunächst, Kalibrierungsbildschirm, die in der MainPage.xaml; definiert ist Zweitens wird eine boolesche Variable Kalibrierung auf True.

Abbildung 6 des Kalibrierung-Ereignishandlers

void compass_Calibrate(object sender, 
  CalibrationEventArgs e)
{
  try
  {
    Dispatcher.BeginInvoke(() => 
    { calibrationStackPanel.Visibility =
      Visibility.Visible; 
    });
    calibrating = true;
  }
  catch (Exception ex)
  {
    MessageBox.Show(ex.Message.ToString(), 
       "Error!", MessageBoxButton.OK);
  }
}

Da dieser Ereignishandler aus einem Hintergrundthread aufgerufen wird, es nicht direkten Zugang zu den UI-Thread. Also, um den Kalibrierungsbildschirm anzuzeigen, muss ich die BeginInvoke-Methode für das Dispatcher-Objekt aufrufen.

Die boolesche Variable Kalibrierung wird innerhalb des Codes für den Wert ausgelöstes Ereignis-Handler (Compass_CurrentValueChanged) untersucht. Wenn diese Variable true ist, ich den Kompass zu ignorieren und Kalibrierungsbildschirm mit den jüngsten Kalibrierungsdaten aktualisieren. Wenn die Variable false ist, ich aktualisieren die Kompass Lesungen und Rotationen des Kompass Gesichts durchführen.

Dieser Ereignishandler wird in der MainPage-Konstruktor mit der folgenden Codezeile hergestellt:

compass.Calibrate += new EventHandler<CalibrationEventArgs>(compass_Calibrate);

Definition und Festlegung der Value-Changed-Handler (Compass_CurrentValueChanged) der Wert geändert-Ereignishandler aufgerufen wird jedes Mal eine neue Lektüre aus der Kompass kommt. Und, abhängig vom Zustand der Kalibrierung variabel, entweder aktualisiert Kalibrierungsbildschirm oder den primären Bildschirm aktualisiert.

Wenn er den primären Bildschirm aktualisiert, führt der Ereignishandler die folgenden Aufgaben:

  • Es berechnet die wahren und wechselseitige Überschriften in Bezug auf den geographischen Norden.
  • Es dreht sich das Kompass Gesicht.
  • Er macht die aktuellen und wechselseitige Überschriften.

Datenverarbeitung der Rubriken der folgende Code wird veranschaulicht, wie der Ereignishandler die Überschrift in Bezug auf wahr Norden mithilfe der TrueHeading-Eigenschaft des SensorReading-Objekts abgerufen:

 

TrueHeading = e.SensorReading.TrueHeading;
  if ((180 <= TrueHeading) && (TrueHeading <= 360))
    ReciprocalHeading = TrueHeading - 180;
  Else
    ReciprocalHeading = TrueHeading + 180;

Abbildung 7 veranschaulicht, wie der Ereignishandler die aktuellen und wechselseitige Rubriken aktualisiert.

Abbildung 7 Aktualisieren von Strom und gegenseitige Überschriften

if (!Alphabetic) // Render numeric heading
{
  HeadingTextBlock.Text = TrueHeading.ToString();
  RecipTextBlock.Text = ReciprocalHeading.ToString();
}
else // Render alpha heading
{
  if (((337 <= TrueHeading) && (TrueHeading < 360)) ||
    ((0 <= TrueHeading) && (TrueHeading < 22)))
  {
    HeadingTextBlock.Text = "N";
    RecipTextBlock.Text = "S";
  }
  else if ((22 <= TrueHeading) && (TrueHeading < 67))
  {
    HeadingTextBlock.Text = "NE";
    RecipTextBlock.Text = "SW";
  }
  else if ((67 <= TrueHeading) && (TrueHeading < 112))
  {
    HeadingTextBlock.Text = "E";
    RecipTextBlock.Text = "W";
  }
  else if ((112 <= TrueHeading) && (TrueHeading < 152))
  {
    HeadingTextBlock.Text = "SE";
    RecipTextBlock.Text = "NW";
  }
  else if ((152 <= TrueHeading) && (TrueHeading < 202))
  {
    HeadingTextBlock.Text = "S";
    RecipTextBlock.Text = "N";
  }
  else if ((202 <= TrueHeading) && (TrueHeading < 247))
  {
    HeadingTextBlock.Text = "SW";
    RecipTextBlock.Text = "NE";
  }
  else if ((247 <= TrueHeading) && (TrueHeading < 292))
  {
    HeadingTextBlock.Text = "W";
    RecipTextBlock.Text = "E";
  }
  else if ((292 <= TrueHeading) && (TrueHeading < 337))
  {
    HeadingTextBlock.Text = "NW";
    RecipTextBlock.Text = "SE";
  }
}

Drehen den Kompass-Gesicht der folgende Codeausschnitt veranschaulicht, wie die app die zwei Ellipsen dreht, die Hintergrund und Vordergrund des Kompass Gesichts darstellen:

CompassFace.RenderTransformOrigin = new Point(0.5, 0.5);
EllipseGlass.RenderTransformOrigin = new Point(0.5, 0.5);
transform.Angle = 360 - TrueHeading;
CompassFace.RenderTransform = transform;
EllipseGlass.RenderTransform = transform;

Die Variable CompassFace entspricht das Hintergrundbild, das die vier Punkte der Himmelsrichtungen (N, E, W und S) und die horizontale und vertikale Linie enthält. Die Variable EllipseGlass entspricht die geraucht-Glas-Schicht.

Bevor ich eine Drehungstransformation anwenden können, muss ich sicherstellen, dass die Transformation auf die beiden Objekte zentriert wird, die ich drehen werde. Dies erfolgt durch Aufrufen der RenderTransformOrigin-Methode für jedes Objekt und liefern die Koordinaten (0.5, 0.5). (Weitere Informationen über diese Methode und ihre Anwendung finden Sie in der MSDN Library-Seite, "UIElement.RenderTransformOrigin-Eigenschaft" bei bit.ly/KIn8Zh.)

Sobald ich die Transformation zentriert haben, kann ich den Winkel zu berechnen und die Drehung durchführen. Ich berechnen Sie den Winkel durch Subtraktion der aktuellen Überschrift von 360. (Das ist die Überschrift erhielt ich nur im Ereignishandler.) Dieser neue Winkel mit der RenderTransform-Eigenschaft anwenden

Sperren und Entsperren des Kompass das Sperren und entsperren­Ing Feature war gedacht für jemanden im Freien, die app mit (ob in einem Boot oder Wandern auf einem Pfad mit Karte in der hand) navigiert wird. Dieses Feature ist einfach; Ruft die Stop-Methode auf dem Kompass, die Überschrift zu sperren und dann ruft Sie die Start-Methode zum Abrufen von Überschrift fortsetzen.

Die Stop-Methode wird aufgerufen, wenn der Benutzer LockButton drückt:

private void LockButton_Click(object sender, 
  RoutedEventArgs e)
{
  try
  {
    compass.Stop();
  }
  catch (Exception ex)
  {
    MessageBox.Show(ex.Message.ToString(), 
      "Error!", MessageBoxButton.OK);
  }
}

Die Start-Methode wird aufgerufen, wenn der Benutzer UnlockButton drückt:

private void UnlockButton_Click(object sender, 
  RoutedEventArgs e)
{
  try
  {
    compass.Start();
    compass.TimeBetweenUpdates =
      TimeSpan.FromMilliseconds(400);  
      // Must be multiple of 20
  }
  catch (Exception ex)
  {
    MessageBox.Show(ex.Message.ToString(), 
      "Error!", MessageBoxButton.OK);
  }
}

Beachten Sie, dass zusätzlich zum Neustarten des Kompasses, ich das Berichtsintervall zurücksetzen, bis 400 ms konsistentes Verhalten sicherzustellen.

Toggling zwischen numerischen und Alpha-Überschriften der Code, der zwischen Alpha und numerischen Überschriften zwischen wird gesteuert durch eine einzelne Boolean-Variable mit dem Namen alphabetisch, die festgelegt ist, wenn ein Benutzer, AlphaButton oder NumericButton drückt. Wenn der Benutzer AlphaButton drückt, wird diese Variable auf True festgelegt; Wenn der Benutzer NumericButton drückt, wird es auf False festgelegt.

Es folgt der Code für das Click-Ereignis von AlphaButton:

private void AlphaButton_Click(
    object sender, RoutedEventArgs e)
  {
    try
    {
      Alphabetic = true;
    }
    catch (Exception ex)
    {
      MessageBox.Show(
         ex.Message.ToString(), "Error!",
        MessageBoxButton.OK);
    }
  }

Der Code innerhalb des Ereignishandlers Compass_CurrentValueChanged untersucht alphabetische um festzustellen, ob es die numerischen oder alpha-Überschriften machen sollte.

Unterstützung der Licht und dunkel Sichtbarkeit Themes nachdem ich die app erstellt und es den App-Hub für die Zertifizierung übermittelt, ich war überrascht, um Benachrichtigungen zu erhalten, die er es unterlassen hatte, weil bestimmte Elemente der Benutzeroberfläche verschwand, wenn das Thema Licht Sichtbarkeit getestet wurde. (Ich hatte bisher ausschließlich mit dem dunklen Thema ausgeführt und habe es versäumt, das leichte Design getestet.)

Um dieses Problem zu beheben, fügte ich Code auf der MainPage-Konstruktor, der das aktuelle Thema abruft und dann setzt die Vordergrundfarbe der Benutzeroberflächenelemente (Textblöcke und Schaltflächen) mit dem bestimmten Thema zu arbeiten. Wenn das Licht Design festgelegt ist, sind die Vordergrundfarben Elemente legen Sie auf schwarz und rot. Wenn das dunkle Thema festgelegt ist, werden die Vordergrundfarben der Elemente zu dunklen und hellen Grau festgelegt. Abbildung 8 dieser Code zeigt.

Abbildung 8 Koordination Themen und Farben

Visibility isLight = (Visibility)Resources["PhoneLightThemeVisibility"]; // For light theme
if (isLight == System.Windows.Visibility.Visible) // Light theme enabled
{
  // Constructor technique
  SolidColorBrush scb = new SolidColorBrush(Colors.Black);
  SolidColorBrush scb2 = new SolidColorBrush(Colors.Red);
  RecipLabelTextBlock.Foreground = scb;
  HeadingLabelTextBlock.Foreground = scb;
  RecipTextBlock.Foreground = scb2;
  HeadingTextBlock.Foreground = scb2;
  LockButton.Foreground = scb;
  UnlockButton.Foreground = scb;
  AlphaButton.Foreground = scb;
  NumericButton.Foreground = scb;
}
else // Dark color scheme is selected—set text colors accordingly
{
  // Constructor technique
  SolidColorBrush scb = new SolidColorBrush(Colors.DarkGray);
  SolidColorBrush scb2 = new SolidColorBrush(Colors.LightGray);
  RecipLabelTextBlock.Foreground = scb;
  HeadingLabelTextBlock.Foreground = scb;
  RecipTextBlock.Foreground = scb2;
  HeadingTextBlock.Foreground = scb2;
  LockButton.Foreground = scb;
  UnlockButton.Foreground = scb;
  AlphaButton.Foreground = scb;
  NumericButton.Foreground = scb;
}

Spaß und wertvolle

Die Schaffung dieser APP war eine Menge Spaß, und es war auch wertvoll. Mit einem Sensor in der Windows Phone-Plattform gearbeitet, habe ich jetzt ein besseres Verständnis der Unterschiede zwischen dieser Plattform und der Sensor-Unterstützung in Windows 8. Aber was mich am meisten beeindruckte, waren die Ähnlichkeiten. Meine Vermutung ist, dass wenn Sie ein Windows Phone-Entwickler sind, der jederzeit mit dem Sensor-Namespace verbracht hat, wirst du die Migration auf Windows 8 außergewöhnlich einfach zu finden. Und Windows 8 finden Sie zusätzliche Sensoren wie Neigungsmesser, Bildausrichtungssensor und einfache Orientierung Sensor. (Der Bildausrichtungssensor ist eine Zusammenfügung mehrerer Sensoren, die eine Quaternion zurückgibt, oder Rotationsmatrix, die Sie verwenden können, um komplexe Spiele zu steuern. Der einfache Orientierung Sensor können Sie erkennen, ob Ihr Gerät im Hochformat oder Querformat-Modus als auch hinterrücks oder mein.)

Die Entwicklungschancen der alle diese Sensoren sind spannend und ich freuen uns auf die phantasievolle Weise, die unsere kreativen Entwickler-Community können sie verwenden setzen.

Donn Morse ist ein leitender Programmier Autor im Windows-Team bei Microsoft, die seit mehreren Jahren auf die Sensor-Plattform, von der Anwendungsseite des Treibers hat. Er ist begeistert und fasziniert, Sensoren und deren Verwendung.

Unser Dank gilt dem folgenden technischen Experten für die Durchsicht dieses Artikels: Jason Scott