Tag Archives: Tips

Kostenlose Lernvideos zum Windows Phone 7

Eigentlich ist es halb so wild, für das Windows Phone 7 Anwendungen zu entwickeln. Ein paar Grundlagen C# (oder Visual Basic), der sichere Umgang mit Expression Blend und Kenntnis der wenigen aber vorhandenen Stolperfallen reichen aus. Doch die eine oder andere Anwendung zeigt, dass diese Dinge nicht jedem von Anfang an geläufig sind. Und mir erging es am Anfang nicht besser und so musste ich beim Erlernen der Besonderheiten einiges Lehrgeld zahlen.

Um anderen diesen Einstieg zu erleichtern und die typischen Fehler vermeiden zu helfen gibt es die Erkenntnisse daraus als Lernvideo auf einer DVD (oder online).

Einen großen Teil der Lerninhalte gibt es aber auch kostenlos. Teils beim Verlag video2brain und teils als App im Marketplace. Außerdem finden sich bei Vimeo noch Teile der DVD und einiges mehr. Hier mal ein kleiner Auszug und eine mögliche Reihenfolge für den Einstieg:

  • Einen Einstieg in die schnelle Anwendungsentwicklung und das Prototyping bietet „Windows Phone 7 Fundamentals (Teil 1 von 5) – Prototyping“.
  • Wer sich eher mit Animationen beschäftigen möchte, findet in „Windows Phone 7: Bewegung kommt ins Spiel” alles wichtige dazu.
  • Den Umgang mit grafischen Elementen und deren Wiederverwendung zeigt „Windows Phone 7: Ressourcen als Styleguide für Visual Studio und Expression Blend“.
  • Die Nutzung Telefon spezifischer Funktionen erklärt „Windows Phone 7: Spezielle Aufgaben für das Telefon (Launcher und Chooser)“.
  • Wer das Mikrofon nutzen oder auch das Zusammenspiel vom Silverlight mit XNA sehen will, der findet eine Anleitung in „Windows Phone 7 Fundamentals (Teil 5 von 5) – XNA und Mikrofon“.
  • Mehrprachigkeit darf natürlich auch nicht vergessen werden und so führt „Windows Phone 7 Fundamentals (Teil 4 von 5) – Mehrsprachigkeit“ in dieses Thema ein.
  • Das ist aber noch nicht genug und so gibt es ergänzend dazu noch drei weitere Videos als App im Marketplace:

  • Den Umgang mit den sehr mächtigen Verhalten zeigt „Lernvideo Verhalten (Behaviors)“.
  • „Lernvideo Softwarearchitektur (MVVM)” erklärt, wie eine Windows Phone 7 App grundsätzlich nach dem MVVM Muster aufgebaut sein könnte.
  • Eine der größten Stolperfallen ist das Tombstoning (also das Unter- oder Abbrechen von Anwendungen). Wie damit umgegangen werden kann zeigt „Lernvideo Tombstoning“.
  • Weitere Videos zu Expression Blend inkl. SketchFlow finden sich unter http://vimeo.com/album/149180. Eine Schritt-für-Schritt-Anleitung der Datendienste auf Basis von WCF findet sich unter http://vimeo.com/album/271975. Und obwohl diese Videos sich auf Silverlight für den Webbrowser beziehen, kann das Meiste daraus auch für das Windows Phone 7 genutzt werden.

    Über eine – hoffentlich motivierende – Rückmeldung zu den Videos und Vorschläge für weitere Inhalte würde ich mich sehr freuen…

    Buchtipp: 2500 Gramm WPF (und ein bisschen Silverlight)

    Microsoft propagiert die Windows Presentation Foundation (kurz WPF) als Standard für Anwendungsoberflächen. Außerdem ist WPF nicht nur ein zentraler Bestandteil des .NET-Kontinuums sondern gilt auch noch als Mutter allen Silverlights: Der Codename von Silverlight war nicht umsonst WPF/E (E für Embedded). Und ich kann mich noch gut daran erinnern, dass ich zum Lernen von Silverlight mangels entsprechender Quellen noch auf WPF-Literatur zurückgreifen musste (was mittlerweile aber glücklicherweise nicht mehr notwendig ist).

    Doch erst kürzlich musste ich mal wieder WPF machen und dafür mein Wissen wieder auf den aktuellen Stand bringen. Da kam mir „Das umfassende Handbuch“ zu WPF von Thomas Claudius Huber sehr gelegen: Auch weil ich den Autor ohnehin schätze und bereits einen hervorragenden Vortrag von ihm gesehen habe. Als das Buch dann eintraf, war der Schock groß: Rund 2500 Gramm Papier wurden geliefert. Doch ich hatte nur wenige Tage Zeit, diese fast 1500 Seiten zur Vorbereitung auf meinen WPF-Einsatz aufzuarbeiten. Bereits nach den ersten Seiten entspannte ich mich aber wieder. Das Buch liest sich einfach hervorragend (mal abgesehen von den physischen Problemen mit einem 2,5kg Buch – ganz besonders im Zug oder Flugzeug eine eher leidvolle Erfahrung). Es hat eindeutig Vorteile, ein gutes Original in der Sprache des Autors und keine Sinn entstellende Übersetzung zu lesen.

    Der Inhalt ist rund und in der Tat sehr umfassend: Von allgemeinen Erklärungen der WPF über XAML, Layout, Dependency Properties, Commands und Datenbindung geht es bis hin zu 3D-Grafik, Medienintegration, Text und Drucken. Auch XAML Browser Applications (XBAP) und Interoperabilität mit Windows Forms werden behandelt. Dabei ist der Inhalt nie zu grundlegend und somit sowohl für ambitionierte Ein- und Umsteiger als auch für Fortgeschrittene geeignet, die ihr Wissen sortieren und Lücken schließen wollen.

    Dem Autor gelingt es gut, einfach Themen auch einfach und auf den Punkt zu erklären. Einzig bei komplizierten Sachverhalten würde ich mir ein wenig einfachere Erläuterungen untermalt von grafischen Darstellungen (Diagramme und Abbildungen) wünschen: Ein Bild sagt einfache mehr als tausend Worte. Außerdem hätte sich dadurch die beängstigende Textmenge vielleicht ein wenig reduzieren lassen. Der WPF-Klassiker von Adam Nathan (ich kenne jedoch nur die Ausgabe zu WPF 3.0) macht das unterstützt durch mehrfarbigen Druck besser, beschränkt sich mit rund 800 Seiten aber auch nur auf das Wesentliche.

    Ich kann Thomas Buch jedem WPF-Interessierten und -Entwickler empfehlen. Ganz nebenbei habe ich Nützliches über die Konzepte von Silverlight erfahren und die Unterschiede zwischen WPF und Silverlight kennen gelernt. Jetzt bin ich sehr auf Thomas neues Buchprojekt zu Silverlight gespannt.

    „Windows Presentation Foundation: Das umfassende Handbuch“
    Autor: Thomas Claudius Huber
    Preis: ca. Euro 50,-
    ISBN: 3836215381
    Erscheinungsdatum: Galileo Computing, 28. Juni 2010
    Link: http://www.amazon.de/exec/obidos/ASIN/3836215381/wolter-21

    Next Generation User Interfaces How-To: Gesten

    Der „X-Y-Positions-Anzeiger für ein Bildschirmsystem“, kurz Maus, ist das Standardeingabegerät für grafische Benutzungsschnittstellen (GUI) geworden. Doch dabei kann mit der Maus weit mehr erreicht werden, als einfach nur das Ziehen und Klicken in Anwendungen. Die Kombination der verschiedenen Maustastenzustände und der Mausposition erlaubt ein Benutzererlebnis ähnlich zur Wii ganz ohne weitere Hardware (weiter unten mehr zur Wii).

    image Einfache Maus-Interaktionen wie Drücken, Bewegen und Loslassen der Maus ergeben in Kombination nicht nur Benutzereingaben wie „Drag and Drop“ sondern können auch als Geste für das Durchschneiden eines Objektes am Bildschirm dienen. Für die Flash-Welt liefert der Düsseldorfer David Ochmann unter http://davidochmann.de/#/info?p=462 eine Bibliothek namens DoGestures für ActionScript 2 und 3, die das Verwenden von Mausgesten erleichtert.

    Zur Nutzung von DoGesture in Flash muss dessen Klassenpfad erst einmal verfügbar gemacht werden. Dies geschieht über das Menü „Datei -> Einstellungen für das Veröffentlichen“, dann im Register Flash über die Einstellungen für ActionScript. Dort wird der Quellpfad hinzugefügt.

    Als nächstes wird nur noch der folgende Code benötigt, um die Klassen per Import bekannt zu machen, die Geste zu erzeugen und auf deren Ereignis zu warten sowie eine passende Ereignisbehandlung durchzuführen:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    
    // Mache Klassen verfügbar
    import de.davidochmann.utilities.dogesture.DoGesture;
    import de.davidochmann.utilities.dogesture.events.GestureEvent;
     
    // Erzeuge Geste (der ausführliche Weg)
    var movedown:DoGesture = new DoGesture(stage);
     
    // Lausche dem Ereignis, dass die Geste stattfand
    movedown.addEventListener(GestureEvent.GESTURE_COMPLETE, movedownCompleteHandler);
    // Wie lange darf das Ausführen der Geste dauern
    movedown.setTimeout(1000); 
    // Definiere die notwendigen Bewegungen für die Geste
    movedown.add( 0, 50);
    // Starte das Warten auf die Geste
    movedown.start(); 
     
    // Ereignismethode
    function movedownCompleteHandler(e:GestureEvent):void
    {
    	// Was soll nun passieren...
    	trace("Geste wurde durchgeführt!");
    }

    image Microsoft Surface ist ein Tisch aus dem Jahre 2007. Er zeichnet sich durch eine berührungsempfindliche Oberfläche aus, der u. a. per Mulit-Touch und durch mehrere Nutzer gleichzeitig bedient werden kann.

    Der Maus droht seit ihrer Erfindung 1 963 durch Douglas C. Engelbart und William English Konkurrenz durch die Eingabe mit dem Finger oder anderen Körperteilen. Im Falle von Single-Touch, dient der eine Finger in der Tat auch meist eher als Mausersatz und das sogar mit ganz massiven Nachteilen: Der Finger verdeckt die Informationen am Bildschirm und führt bei der Arbeit an senkrechten Flächen zu schnell ermüdenden Armen – ähnlich wie bei der Arbeit an einer Schultafel führt.

    Sobald mehrere Berührungspunkte möglich sind, lassen sich neue intuitive Gesten jenseits der Mausbedienung formulieren. Bekannt sind das Drehen und Skalieren von Inhalten mit zwei Fingern.

    Silverlight bietet bereits seit Version 3 Multi-Touch. Dabei beschränkt sich Silverlight abhängig von der Abspielplattform auf die einzelnen Berührungspunkte. Gesten müssen selber erkannt und verarbeitet werden. Ein Beispiel inkl. Quellcode findet sich unter http://www.microsoft.com/downloads/details.aspx?displaylang=en&FamilyID=4b281bde-9b01-4890-b3d4-b3b45ca2c2e4.

    image Für eine einfache Touch-Anwednung in Silverlight benötigen wir ein beliebiges sichtbares Objekt, dass in diesem Beispiel mit monster benannt ist. Alles Weitere geschieht dann in der Code-Behind-Datei. Als erstes wird dort ein Transofrmations-Objekt für die Verschiebung des Monsters angelegt und das Ereignis für Berührungen angemeldet (Touch.FrameReported). In der Ereignismethode wird ab nun bei jedem Touch-Ereignis das Monster genau zu der Position der Berührung bewegt.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    
    using System.Windows.Controls;
    using System.Windows.Input;
    using System.Windows.Media;
     
    namespace SilverTouch
    {
        public partial class MainPage : UserControl
        {
     
            public MainPage()
            {
                // Required to initialize variables
                InitializeComponent();
     
                Loaded += new System.Windows.RoutedEventHandler(MainPage_Loaded);
            }
     
            private void MainPage_Loaded(object sender, System.Windows.RoutedEventArgs e)
            {
                // Erzeuge Transformationsobjekt für Verschiebung
                CompositeTransform transform = new CompositeTransform();
                monster.RenderTransform = transform;
     
                // Lausche auf Touch-Ereignis
                Touch.FrameReported += new System.Windows.Input.TouchFrameEventHandler(Touch_FrameReported);
            }
     
            private void Touch_FrameReported(object sender, System.Windows.Input.TouchFrameEventArgs e)
            {
                // Ermittle Tranformationsobjekt 
                CompositeTransform transform = monster.RenderTransform as CompositeTransform;
                // Ermittle primären Berührungspunkt
                TouchPoint tp = e.GetPrimaryTouchPoint(monster);
                // Verschiebe Objekt zum Berührungspunkt
                transform.TranslateX += tp.Position.X - (monster.ActualWidth / 2);
                transform.TranslateY += tp.Position.Y - (monster.ActualHeight / 2);
            }
        }
    }

    imageAuf dem Windows Phone Series 7 nutzt Silverlight für die Oberflächenelemente Manipulationsereignisse (u. a. ManipulationDelta). Diese teilen mit, inwiefern Skaliert oder Verschoben wurde. Um das Ereignis zu erhalten, kann in Expression Blend 4 oder Visual Studio 2010 bei einem Windows Phone Projekt ein Oberflächenelement mit einem Manipulationsereignis versehen werden.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    
    <phoneNavigation:PhoneApplicationPage 
        x:Class="SilverPhone.MainPage"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:phoneNavigation="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone.Controls.Navigation"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        mc:Ignorable="d" d:DesignWidth="480" d:DesignHeight="800"
        FontFamily="{StaticResource PhoneFontFamilyNormal}"
        FontSize="{StaticResource PhoneFontSizeNormal}"
        Foreground="{StaticResource PhoneForegroundBrush}">
     
        <Grid x:Name="LayoutRoot" Background="{StaticResource PhoneBackgroundBrush}">
            <Grid.RowDefinitions>
                <RowDefinition Height="Auto"/>
                <RowDefinition Height="*"/>
            </Grid.RowDefinitions>
     
            <!--TitleGrid is the name of the application and page title-->
            <Grid x:Name="TitleGrid" Grid.Row="0">
                <TextBlock x:Name="textBlockPageTitle" Style="{StaticResource PhoneTextPageTitle1Style}"><Run Text="MY "/><Run Text="TOUCH "/><Run Text="APPLICATION"/></TextBlock>
                <TextBlock Text="touch me" x:Name="textBlockListTitle" Style="{StaticResource PhoneTextPageTitle2Style}"/>
            </Grid>
     
            <Grid x:Name="ContentGrid" Grid.Row="1">
                <Image x:Name="monster" ManipulationDelta="Main_ManipulationDelta" Source="Assets/monster.png" HorizontalAlignment="Center" VerticalAlignment="Center" Width="240" Height="342"/>
            </Grid>
     
        </Grid>
     
    </phoneNavigation:PhoneApplicationPage>

    In der zugehörigen Code-Behind-Datei muss dann zum einen ein Tranformationsobjekt für eine Skalierung oder Verschiebung angelegt und in der Ereignismethode für das Manipulationsereignis eine Transformation durchgeführt werden.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    
    using System.Windows.Input;
    using System.Windows.Media;
    using Microsoft.Phone.Controls;
     
    namespace SilverPhone
    {
        public partial class MainPage : PhoneApplicationPage
        {
     
            public MainPage()
            {
                // Required to initialize variables
                InitializeComponent();
     
                Loaded += new System.Windows.RoutedEventHandler(MainPage_Loaded);
            }
     
            private void MainPage_Loaded(object sender, System.Windows.RoutedEventArgs e)
            {
                // Erzeuge Transformationsobjekt für Verschiebung
                CompositeTransform transform = new CompositeTransform();
                monster.RenderTransform = transform;
            }
     
            // Ereignismethode
            private void Main_ManipulationDelta(object sender, ManipulationDeltaEventArgs e)
            {
                // Ermittle Tranformationsobjekt 
                CompositeTransform transform = monster.RenderTransform as CompositeTransform;
     
                // Verschiebe Objekt bzgl. der durchgeführten Manipulation
                transform.TranslateX += e.DeltaManipulation.Translation.X;
                transform.TranslateY += e.DeltaManipulation.Translation.Y;
            }
        }
    }

    Für Flash griff man bisher auf Zusatzprogramme zurück, die die notwendigen Daten – meist per TUIO (http://www.tuio.org/) – direkt an Flash übermittelten. Mit Flash Player 10.1 und AIR 2 hält Multi-Touch nun aber auch Einzug in die Flash-Welt. Abhängig von der Abspielplattform verstehen Flash und AIR einzelne Berührungspunkte und Gesten (gerade unter Mac OS ist das noch recht eingeschränkt, siehe auch http://www.adobe.com/devnet/flash/articles/multitouch_gestures.html).

    1
    2
    3
    4
    5
    6
    
    if (!Multitouch.supportsGestureEvents) {
    	Alert.show(&quot;Gesten werden nicht unterstützt&quot;, &quot;Hinweis&quot;);
    } else {
    	// Stelle sicher, Gesten zu nutzen
    	Multitouch.inputMode = MultitouchInputMode.GESTURE;
    }

    Je nach Plattform werden unterschiedliche Gesten unterstützt (Multitouch.supportedGestures). Diese müssten sonst selbst aus den Berührungspunkten ermittelt werden.

    Mit dem Flex 4 SDK und AIR 2 kann jedes interaktive Oberflächenelement Gesten nutzen. In den zugehörigen Ereignismethoden werden dann abschließend die Werte der Gesten verwendet.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    
    <?xml version="1.0" encoding="utf-8"?>
    <s:WindowedApplication xmlns:fx="http://ns.adobe.com/mxml/2009" 
    			 xmlns:s="library://ns.adobe.com/flex/spark" 
    			 xmlns:mx="library://ns.adobe.com/flex/mx"
    			 creationComplete="windowedapplication_creationCompleteHandler(event)">
     
    	<fx:Script>
    		<![CDATA[
     
    			import mx.controls.Alert;
    			import mx.events.FlexEvent;
     
    			protected function windowedapplication_creationCompleteHandler(event:FlexEvent):void
    			{
    				if (!Multitouch.supportsGestureEvents) {
    					Alert.show("Gesten werden nicht unterstützt!", "Hinweis");
    				} else {
    					// Stelle sicher, Gesten zu nutzen
    					Multitouch.inputMode = MultitouchInputMode.GESTURE;
    				}
    			}
     
    			protected function image_gestureZoomHandler(event:TransformGestureEvent):void
    			{
    				// Skaliere Objekt
    				(event.currentTarget as InteractiveObject).scaleX *= event.scaleX;
    				(event.currentTarget as InteractiveObject).scaleY *= event.scaleY;
    			}
     
    			protected function image_gesturePanHandler(event:TransformGestureEvent):void
    			{
    				// Verschiebe Objekt
    				(event.currentTarget as InteractiveObject).x += event.offsetX;
    				(event.currentTarget as InteractiveObject).y += event.offsetY;
    			}
     
    			protected function image_gestureRotateHandler(event:TransformGestureEvent):void
    			{
    				// Drehe Objekt
    				(event.currentTarget as InteractiveObject).rotation += event.rotation;
    			}
     
    		]]>
    	</fx:Script>
     
    	<mx:Image x="20" y="20" source="assets/monster.png" 
    			  gesturePan="image_gesturePanHandler(event)"
    			  gestureZoom="image_gestureZoomHandler(event)"
    			  gestureRotate="image_gestureRotateHandler(event)"
    			  />
     
    </s:WindowedApplication>

    image Silverlight bietet seit Version 2 mit dem InkPresenter eine weitere Eingabemöglichkeit: Diesmal mit dem Stift. Der InkPresenter zeichnet die einzelnen Punkte der Stift- oder Mausbewegung auf. Sofern verfügbar sogar drucksensitiv.

     

    image In Expression Blend (oder auch mit Visual Studio) fügen Sie das Steuerlement InkPresenter ein und geben diesem einen Hintergrund (Background) hinzu, da andernfalls keine Eingaben erkannt werden. Klar, dass natürlich auch die Größen- und Positionsangaben passen müssen – in diesem Beispiel sind keine expliziten Angaben vorgenommen worden, da auf diese Weise die komplette Fläche ausgefüllt wird. Für die eigentliche Aufzeichnung der Stifteingabe nutzen wir das Drücken der linken Maustaste (MouseLeftButtonDown), das Bewegen der Maus (MouseMove) und die Nachricht, wenn der Bezug zur Maus wieder verloren wird (LostMouseCapture). Die zugehörigen Ereignismethoden landen in der zugehörigen Code-Behind-Datei:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    
    using System;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Documents;
    using System.Windows.Ink;
    using System.Windows.Input;
    using System.Windows.Media;
    using System.Windows.Media.Animation;
    using System.Windows.Shapes;
     
    namespace SilverPen
    {
    	public partial class MainPage : UserControl
    	{
     
    		private Stroke currentStroke;
     
    		public MainPage()
    		{
    			// Required to initialize variables
    			InitializeComponent();			
    		}
     
    		private void inkPresenter_MouseLeftButtonDown(object sender, System.Windows.Input.MouseButtonEventArgs e)
    		{
                // Starte mit der Aufzeichnung
    			inkPresenter.CaptureMouse();
                // Merke die Punkte
    			StylusPointCollection stylusPointCollection = new StylusPointCollection();
                // Füge die ersten Punkte hinzu
                stylusPointCollection.Add(e.StylusDevice.GetStylusPoints(inkPresenter));
                // Erstelle aus den Punkten einen Strich
    			currentStroke = new Stroke(stylusPointCollection);
                // Zeichne den Strich (dieser wird später weiter aktualisiert)
    			inkPresenter.Strokes.Add(currentStroke);
    		}
     
    		private void inkPresenter_LostMouseCapture(object sender, System.Windows.Input.MouseEventArgs e)
    		{
                // Beende die Aufzeichnung
    			currentStroke = null;
    			inkPresenter.ReleaseMouseCapture();
    		}
     
    		private void inkPresenter_MouseMove(object sender, System.Windows.Input.MouseEventArgs e)
    		{
    			// Füge dem aktuellen Strich neue Punkte hinzu
        		if (currentStroke != null) {
            		currentStroke.StylusPoints.Add(e.StylusDevice.GetStylusPoints(inkPresenter));
    			}
    		}
     
    	}
    }

    Natürlich könnte das Aussehen des gezeichneten Striches (Stroke) über dessen Attribute variiert und zum Beispiel mit dem Druck des Stiftes kombiniert werden:

    1
    
    currentStroke.DrawingAttributes.Height = e.StylusDevice.GetStylusPoints(inkPresenter)[0].PressureFactor * 100;

    Wenn man das wie im Beispiel unter http://msdn.microsoft.com/en-us/magazine/cc721604.aspx#id0090072 weitertreibt, dann ist sogar eine Handschriftenerkennung im Browser möglich.