<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://blogs.msdn.com/utility/FeedStylesheets/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/"><channel><title>Anson Tsao's Blog</title><link>http://blogs.msdn.com/b/ansont/</link><description>On programming, user interfaces and data visualizations</description><dc:language>en-US</dc:language><generator>Telligent Evolution Platform Developer Build (Build: 5.6.50428.7875)</generator><item><title>Microsoft Surface Toolkit for Windows Touch Beta Release!</title><link>http://blogs.msdn.com/b/ansont/archive/2010/04/12/microsoft-surface-toolkit-for-windows-touch-beta-release.aspx</link><pubDate>Mon, 12 Apr 2010 22:27:25 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9994720</guid><dc:creator>AnsonT</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/ansont/rsscomments.aspx?WeblogPostID=9994720</wfw:commentRss><comments>http://blogs.msdn.com/b/ansont/archive/2010/04/12/microsoft-surface-toolkit-for-windows-touch-beta-release.aspx#comments</comments><description>&lt;p&gt;Our friends over at Surface just released the &lt;a href="http://blogs.msdn.com/surface/archive/2010/04/12/launch-microsoft-surface-toolkit-for-windows-touch-beta.aspx" target="_blank"&gt;beta toolkit&lt;/a&gt; built on WPF4. &lt;/p&gt; &lt;p&gt;The toolkit is usable with any multi-touch enabled Windows 7 display, as well as the Multipoint SDK via the custom TouchDevice from my previous blog &lt;a href="http://blogs.msdn.com/ansont/archive/2010/01/30/custom-touch-devices.aspx" target="_blank"&gt;entry&lt;/a&gt;.&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9994720" width="1" height="1"&gt;</description></item><item><title>Custom Touch Devices</title><link>http://blogs.msdn.com/b/ansont/archive/2010/01/30/custom-touch-devices.aspx</link><pubDate>Sat, 30 Jan 2010 17:08:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9955649</guid><dc:creator>AnsonT</dc:creator><slash:comments>1</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/ansont/rsscomments.aspx?WeblogPostID=9955649</wfw:commentRss><comments>http://blogs.msdn.com/b/ansont/archive/2010/01/30/custom-touch-devices.aspx#comments</comments><description>&lt;p&gt;WPF4 allows applications to implement custom touch devices. We added this functionality to allow Surface SDK to be built on WPF multi-touch APIs directly. As we announced at PDC09, the next version of the Surface SDK will implement WPF multi-touch devices with the input from the Surface vision system.&lt;/p&gt;&lt;p&gt;A few weeks ago, Microsoft &lt;a mce_href="http://www.microsoft.com/multipoint/mouse-sdk/" href="http://www.microsoft.com/multipoint/mouse-sdk/"&gt;Multipoint SDK&lt;/a&gt;&amp;nbsp;version 1.5 was released. Multipoint SDK supports using up-to 25 USB mice as input devices on the same PC. While the original intent of the Multipoint SDK is to allow multiple students to collaborate and share a single PC, the multiple mice support is perfect for simulating multi-touch input.&lt;/p&gt;&lt;p&gt;In this post, I will explain how to implement custom touch devices in WPF4 and use the Multipoint SDK integration as an example.&lt;/p&gt;&lt;h3&gt;TouchDevice&lt;/h3&gt;&lt;p&gt;TouchDevice is an abstract class in the System.Windows.Input namespace. An instance of TouchDevice represents one touch contact. To add a new type of touch input to WPF, you need to derive from TouchDevice, override the methods to provide current positions of the touch points, and notify the input system of state changes via the ReportDown/Move/Up and Activate/Deactivate methods on TouchDevice.&lt;/p&gt;&lt;h5&gt;Deriving from TouchDevice and TouchPoint&lt;/h5&gt;&lt;p&gt;TouchDevice constructor takes an integer device ID as parameter. Device IDs should be unique for your set of touch devices, it is not enforced by the system. For developers, it is sufficient to use the instance of the TouchDevice as a key, and it is guaranteed to be valid and consistent during an interaction cycle.&lt;/p&gt;&lt;p&gt;TouchDevice has 2 public abstract methods that you have to override to provide the position of the touch contact.&lt;/p&gt;&lt;p&gt;&lt;b&gt;TouchPoint GetTouchPoint(IInputElement relativeTo)&lt;/b&gt; method returns the current position of the touch contact relative to the coordinate system of ‘relativeTo’ element.&lt;/p&gt;&lt;p&gt;To calculate the transformation from the top-level window coordinate system to the ‘relativeTo’ element’s system, you can calculate the transformation via the Visual.TransformToDescendant() method and Transform() the toucd point accordingly.&lt;/p&gt;&lt;p&gt;&lt;b&gt;TouchPointCollection GetIntermediateTouchPoints(IInputElement relativeTo) &lt;/b&gt;method returns a collection of intermediate touch points that was collected but not reported since the last touch event. This is used to aggregate a sequence of high frequency touch positions and not overwhelm the system with individual Touch events. For most applications, it’s sufficient to return an empty collection and call ReportMove() on every detected touch movements.&lt;/p&gt;&lt;p&gt;You can provide additional information about your touch contact by deriving from TouchPoint. For example, Surface also associates elliptical bounds and tag ID with TouchPoint, these attributes are not available via the Windows touch device drivers. &lt;/p&gt;&lt;h5&gt;&lt;/h5&gt;&lt;h4&gt;Updating TouchDevice States&lt;/h4&gt;&lt;p&gt;Each TouchDevice needs to be associated with a PresentationSource which is typically the active top level window. Next you have to Activate() the device. To report touch point activity, you will be using ReportDown(), ReportMove() and ReportUp() methods. You need to make sure that each Activate() is accompanied by an Deactivate() call, and each ReportDown() has a corresporting ReportUp(), otherwise the input system will throw an exception.&lt;/p&gt;&lt;p&gt;&lt;a mce_href="http://blogs.msdn.com/blogfiles/ansont/WindowsLiveWriter/CustomTouchDevices_13C7A/image_4.png" href="http://blogs.msdn.com/blogfiles/ansont/WindowsLiveWriter/CustomTouchDevices_13C7A/image_4.png"&gt;&lt;img style="BORDER-RIGHT-WIDTH: 0px; DISPLAY: inline; BORDER-TOP-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; BORDER-LEFT-WIDTH: 0px" title="image" border="0" alt="image" width="131" height="327" mce_src="http://blogs.msdn.com/blogfiles/ansont/WindowsLiveWriter/CustomTouchDevices_13C7A/image_thumb_1.png" src="http://blogs.msdn.com/blogfiles/ansont/WindowsLiveWriter/CustomTouchDevices_13C7A/image_thumb_1.png"&gt;&lt;/a&gt; &lt;/p&gt;&lt;h3&gt;Use multiple mice for multi-touch input&lt;/h3&gt;&lt;p&gt;In this example we will be using the MultiPoint SDK to provide multi-touch input. The full source code is here.&lt;/p&gt;&lt;p&gt;First, we need to reference the MultiPoint assembly from the SDK&lt;/p&gt;&lt;p&gt;&lt;a mce_href="http://blogs.msdn.com/blogfiles/ansont/WindowsLiveWriter/CustomTouchDevices_13C7A/image_6.png" href="http://blogs.msdn.com/blogfiles/ansont/WindowsLiveWriter/CustomTouchDevices_13C7A/image_6.png"&gt;&lt;img style="BORDER-RIGHT-WIDTH: 0px; DISPLAY: inline; BORDER-TOP-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; BORDER-LEFT-WIDTH: 0px" title="image" border="0" alt="image" width="242" height="164" mce_src="http://blogs.msdn.com/blogfiles/ansont/WindowsLiveWriter/CustomTouchDevices_13C7A/image_thumb_2.png" src="http://blogs.msdn.com/blogfiles/ansont/WindowsLiveWriter/CustomTouchDevices_13C7A/image_thumb_2.png"&gt;&lt;/a&gt; &lt;/p&gt;&lt;p&gt;We will create a MultipointTouchWindow that receives the Multipoint events, and translate into the touch events. With modifications to the Multipoint SDK, we can provide multi-touch event more efficiently, but we will have to wait for a future release of the SDK.&lt;/p&gt;&lt;div id="codeSnippetWrapper"&gt;&lt;div style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: #f4f4f4; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px" id="codeSnippet"&gt;&lt;pre style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: white; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"&gt;&lt;span style="COLOR: #0000ff"&gt;public&lt;/span&gt; &lt;span style="COLOR: #0000ff"&gt;class&lt;/span&gt; MultipointTouchWindow : Window, IMultipointMouseEvents &lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: #f4f4f4; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"&gt;{&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: white; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"&gt;    &lt;span style="COLOR: #0000ff"&gt;public&lt;/span&gt; MultipointTouchWindow() &lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: #f4f4f4; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"&gt;    {&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: white; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"&gt;        Loaded += HandleLoaded;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: #f4f4f4; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"&gt;    }&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: white; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"&gt;&amp;nbsp;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: #f4f4f4; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"&gt;    &lt;span style="COLOR: #0000ff"&gt;private&lt;/span&gt; &lt;span style="COLOR: #0000ff"&gt;void&lt;/span&gt; HandleLoaded(&lt;span style="COLOR: #0000ff"&gt;object&lt;/span&gt; sender, RoutedEventArgs args)&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: white; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"&gt;    {&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: #f4f4f4; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"&gt;        MultipointSdk.Instance.Initialize(&lt;span style="COLOR: #0000ff"&gt;this&lt;/span&gt;);&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: white; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"&gt;        MultipointSdk.Instance.DeviceArrivalEvent += HandleMultipointDeviceArrival;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: #f4f4f4; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"&gt;        &lt;span style="COLOR: #0000ff"&gt;foreach&lt;/span&gt; (var device &lt;span style="COLOR: #0000ff"&gt;in&lt;/span&gt; MultipointSdk.Instance.MouseDeviceList)&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: white; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"&gt;            device.DeviceVisual.CursorColor = NextColor();&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: #f4f4f4; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"&gt;    }&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: white; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"&gt;&amp;nbsp;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: #f4f4f4; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"&gt;&amp;nbsp;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;The window class has to implement the IMultipointMouseEvents interface for the Multipoint SDK to provide mouse events. Default implementations of the events in the interface is sufficient.&lt;/p&gt;&lt;p&gt;The Multipoint SDK instance is initialized after the WPF window is loaded, and the corresponding HWD has been created.&lt;/p&gt;&lt;p&gt;We also assign different colors to the cursor associated with the each mouse device. NextColor() is a simple utility method that returns a different color every time it’s called.&lt;/p&gt;&lt;p&gt;Multipoint works best with full screen windows. In WPF you need to set the WindowState to Maximized and WindowStyle to None.&lt;/p&gt;&lt;p&gt;Next we hook up the preview Multipoint mouse events&lt;/p&gt;&lt;div id="codeSnippetWrapper"&gt;&lt;div style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: #f4f4f4; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px" id="codeSnippet"&gt;&lt;pre style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: white; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"&gt;&lt;span style="COLOR: #0000ff"&gt;static&lt;/span&gt; MultipointTouchWindow()&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: #f4f4f4; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"&gt;{&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: white; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"&gt;    EventManager.RegisterClassHandler(&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: #f4f4f4; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"&gt;                &lt;span style="COLOR: #0000ff"&gt;typeof&lt;/span&gt;(UIElement), &lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: white; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"&gt;                MultipointMouseEvents.MultipointPreviewMouseDownEvent,&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: #f4f4f4; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"&gt;                (RoutedEventHandler)HandleMultipointMouseDown, &lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: white; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"&gt;                &lt;span style="COLOR: #0000ff"&gt;false&lt;/span&gt; );&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: #f4f4f4; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"&gt;    EventManager.RegisterClassHandler(&lt;span style="COLOR: #0000ff"&gt;typeof&lt;/span&gt;(UIElement), &lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: white; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"&gt;                MultipointMouseEvents.MultipointPreviewMouseMoveEvent,&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: #f4f4f4; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"&gt;                (RoutedEventHandler)HandleMultipointMouseMove, &lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: white; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"&gt;                &lt;span style="COLOR: #0000ff"&gt;false&lt;/span&gt;);&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: #f4f4f4; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"&gt;    EventManager.RegisterClassHandler(&lt;span style="COLOR: #0000ff"&gt;typeof&lt;/span&gt;(UIElement), &lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: white; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"&gt;                MultipointMouseEvents.MultipointPreviewMouseUpEvent,&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: #f4f4f4; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"&gt;                (RoutedEventHandler)HandleMultipointMouseUp, &lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: white; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"&gt;                &lt;span style="COLOR: #0000ff"&gt;false&lt;/span&gt;);&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: #f4f4f4; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"&gt;}&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;The handlers of these events simply delegate to static methods of the MultipointTouchDevice that we’ll discuss next.&lt;/p&gt;&lt;h4&gt;MultipointTouchDevice&lt;/h4&gt;&lt;p&gt;MultipointTouchDevice derives from TouchDevice. It maintains a static mapping of Multipoint device Ids to their corresponding TouchDevice instances. As we handle Multipoint mouse events, we retrieve the corresponding MultipointTouchDevice and updates its state.&lt;/p&gt;&lt;div id="codeSnippetWrapper"&gt;&lt;div style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: #f4f4f4; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px" id="codeSnippet"&gt;&lt;pre style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: white; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"&gt;&lt;span style="COLOR: #0000ff"&gt;public&lt;/span&gt; &lt;span style="COLOR: #0000ff"&gt;static&lt;/span&gt; &lt;span style="COLOR: #0000ff"&gt;void&lt;/span&gt; MouseDown(MultipointMouseEventArgs e)&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: #f4f4f4; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"&gt; {            &lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: white; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"&gt;     var device = GetDevice(e);&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: #f4f4f4; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"&gt;     device.SetActiveSource(PresentationSource.FromVisual(e.CurrentWindow));&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: white; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"&gt;     device.Position = GetPosition(e);&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: #f4f4f4; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"&gt;     device.Activate();&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: white; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"&gt;     device.ReportDown();&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: #f4f4f4; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"&gt;&amp;nbsp;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: white; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"&gt; }&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;The MouseMove and MouseUp methods are equally simple, first updating the device’s position, then calling ReportMove() or ReportUp(). We deactivate the device after the a mouse up event.&lt;/p&gt;&lt;p&gt;MultipointTouchDevice.Position is a simple property of the current position in Window coordinate system. GetPosition() is a helper function that retrieves the position from MultipointMouseEventArgs.&lt;/p&gt;&lt;div id="codeSnippetWrapper"&gt;&lt;div style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: #f4f4f4; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px" id="codeSnippet"&gt;&lt;pre style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: white; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"&gt;&lt;span style="COLOR: #0000ff"&gt;public&lt;/span&gt; &lt;span style="COLOR: #0000ff"&gt;override&lt;/span&gt; TouchPoint GetTouchPoint(IInputElement relativeTo)&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: #f4f4f4; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"&gt;{&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: white; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"&gt;    Point pt = Position;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: #f4f4f4; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"&gt;    &lt;span style="COLOR: #0000ff"&gt;if&lt;/span&gt; (relativeTo != &lt;span style="COLOR: #0000ff"&gt;null&lt;/span&gt;)&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: white; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"&gt;    {&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: #f4f4f4; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"&gt;        pt = &lt;span style="COLOR: #0000ff"&gt;this&lt;/span&gt;.ActiveSource.RootVisual.&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: white; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"&gt;             TransformToDescendant((Visual)relativeTo).&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: #f4f4f4; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"&gt;             Transform(Position);&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: white; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"&gt;    }&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: #f4f4f4; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"&gt;&amp;nbsp;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: white; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"&gt;    var rect = &lt;span style="COLOR: #0000ff"&gt;new&lt;/span&gt; Rect(pt, &lt;span style="COLOR: #0000ff"&gt;new&lt;/span&gt; Size(1.0, 1.0));&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: #f4f4f4; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"&gt;&amp;nbsp;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: white; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"&gt;    &lt;span style="COLOR: #0000ff"&gt;return&lt;/span&gt; &lt;span style="COLOR: #0000ff"&gt;new&lt;/span&gt; TouchPoint(&lt;span style="COLOR: #0000ff"&gt;this&lt;/span&gt;, pt, rect, TouchAction.Move);&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: #f4f4f4; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"&gt;}&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;The GetTouchPoint() implementation simply transform the Position to the appropriate coordinate system, and return the point as having a 1.0 by 1.0 pixel size.&lt;/p&gt;&lt;iframe style="PADDING-BOTTOM: 0px; BACKGROUND-COLOR: #fcfcfc; PADDING-LEFT: 0px; WIDTH: 98px; PADDING-RIGHT: 0px; HEIGHT: 115px; PADDING-TOP: 0px" title="Preview" marginheight="0" frameborder="0" marginwidth="0" scrolling="no" mce_src="http://cid-0d695ca64e3fb0c5.skydrive.live.com/embedicon.aspx/Public/MultiPointDevice.zip" src="http://cid-0d695ca64e3fb0c5.skydrive.live.com/embedicon.aspx/Public/MultiPointDevice.zip"&gt;&lt;/iframe&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9955649" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/b/ansont/archive/tags/WPF/">WPF</category><category domain="http://blogs.msdn.com/b/ansont/archive/tags/Multitouch/">Multitouch</category></item><item><title>Pictionaire: Multi-touch table that integrates physical and digital objects from Microsoft Research</title><link>http://blogs.msdn.com/b/ansont/archive/2010/01/30/pictionaire-multi-touch-table-that-integrates-physical-and-digital-objects-from-microsoft-research.aspx</link><pubDate>Sat, 30 Jan 2010 13:55:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9955754</guid><dc:creator>AnsonT</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/ansont/rsscomments.aspx?WeblogPostID=9955754</wfw:commentRss><comments>http://blogs.msdn.com/b/ansont/archive/2010/01/30/pictionaire-multi-touch-table-that-integrates-physical-and-digital-objects-from-microsoft-research.aspx#comments</comments><description>&lt;P&gt;Another interesting MSR multi-touch project: &lt;A href="http://research.microsoft.com/en-us/um/people/awilson/publications/HartmannCSCW2010/HartmannCSCW2010.html" target=_blank mce_href="http://research.microsoft.com/en-us/um/people/awilson/publications/HartmannCSCW2010/HartmannCSCW2010.html"&gt;Pictionaire&lt;/A&gt; This research project combines computer object recognition and Surface style multitouch interactions for collaboration.&lt;/P&gt;
&lt;P&gt;It’s based on a modified version of the &lt;A href="http://www.microsoft.com/surface/Pages/Product/Platform.aspx" target=_blank mce_href="http://www.microsoft.com/surface/Pages/Product/Platform.aspx"&gt;Surface SDK&lt;/A&gt;&lt;/P&gt;
&lt;P&gt;
&lt;OBJECT id=flashObj codeBase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=9,0,47,0" classid=clsid:D27CDB6E-AE6D-11cf-96B8-444553540000 width=486 height=412&gt;&lt;PARAM NAME="_cx" VALUE="12858"&gt;&lt;PARAM NAME="_cy" VALUE="10900"&gt;&lt;PARAM NAME="FlashVars" VALUE=""&gt;&lt;PARAM NAME="Movie" VALUE="http://c.brightcove.com/services/viewer/federated_f9/2227271001?isVid=1&amp;amp;publisherID=981571807"&gt;&lt;PARAM NAME="Src" VALUE="http://c.brightcove.com/services/viewer/federated_f9/2227271001?isVid=1&amp;amp;publisherID=981571807"&gt;&lt;PARAM NAME="WMode" VALUE="Window"&gt;&lt;PARAM NAME="Play" VALUE="-1"&gt;&lt;PARAM NAME="Loop" VALUE="-1"&gt;&lt;PARAM NAME="Quality" VALUE="High"&gt;&lt;PARAM NAME="SAlign" VALUE=""&gt;&lt;PARAM NAME="Menu" VALUE="-1"&gt;&lt;PARAM NAME="Base" VALUE="http://admin.brightcove.com"&gt;&lt;PARAM NAME="AllowScriptAccess" VALUE="always"&gt;&lt;PARAM NAME="Scale" VALUE="ShowAll"&gt;&lt;PARAM NAME="DeviceFont" VALUE="0"&gt;&lt;PARAM NAME="EmbedMovie" VALUE="0"&gt;&lt;PARAM NAME="BGColor" VALUE="FFFFFF"&gt;&lt;PARAM NAME="SWRemote" VALUE=""&gt;&lt;PARAM NAME="MovieData" VALUE=""&gt;&lt;PARAM NAME="SeamlessTabbing" VALUE="0"&gt;&lt;PARAM NAME="Profile" VALUE="0"&gt;&lt;PARAM NAME="ProfileAddress" VALUE=""&gt;&lt;PARAM NAME="ProfilePort" VALUE="0"&gt;&lt;PARAM NAME="AllowNetworking" VALUE="all"&gt;&lt;PARAM NAME="AllowFullScreen" VALUE="true"&gt;
&lt;embed src="http://c.brightcove.com/services/viewer/federated_f9/2227271001?isVid=1&amp;amp;publisherID=981571807" mce_src="http://c.brightcove.com/services/viewer/federated_f9/2227271001?isVid=1&amp;amp;publisherID=981571807" bgcolor="#FFFFFF" flashVars="videoId=62714844001&amp;playerID=2227271001&amp;domain=embed&amp;" base="http://admin.brightcove.com" name="flashObj" width="486" height="412" seamlesstabbing="false" type="application/x-shockwave-flash" allowFullScreen="true" swLiveConnect="true" allowScriptAccess="always" pluginspage="http://www.macromedia.com/shockwave/download/index.cgi?P1_Prod_Version=ShockwaveFlash"&gt;&lt;/embed&gt;&lt;/OBJECT&gt;&lt;/P&gt;
&lt;P&gt;
&lt;OBJECT width=425 height=349&gt;&lt;PARAM NAME="movie" VALUE="http://www.youtube.com/v/qIASBXG3-Sk&amp;amp;rel=0&amp;amp;border=1&amp;amp;color1=0xe8e8e8&amp;amp;color2=0xe8e8e8&amp;amp;hl=en_US&amp;amp;feature=player_embedded&amp;amp;fs=1"&gt;&lt;PARAM NAME="allowFullScreen" VALUE="true"&gt;&lt;PARAM NAME="allowScriptAccess" VALUE="always"&gt;
&lt;embed src="http://www.youtube.com/v/qIASBXG3-Sk&amp;amp;rel=0&amp;amp;border=1&amp;amp;color1=0xe8e8e8&amp;amp;color2=0xe8e8e8&amp;amp;hl=en_US&amp;amp;feature=player_embedded&amp;amp;fs=1" mce_src="http://www.youtube.com/v/qIASBXG3-Sk&amp;amp;rel=0&amp;amp;border=1&amp;amp;color1=0xe8e8e8&amp;amp;color2=0xe8e8e8&amp;amp;hl=en_US&amp;amp;feature=player_embedded&amp;amp;fs=1" type="application/x-shockwave-flash" allowfullscreen="true" allowScriptAccess="always" width="425" height="349"&gt;&lt;/embed&gt;&lt;/OBJECT&gt;&lt;/P&gt;
&lt;P mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;It is really easy to add custom touch devices in WPF4 (I’ll write about that in the next post). I'm hoping to see a lot more experimentations around new multi-touch input methods in the community.&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9955754" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/b/ansont/archive/tags/WPF/">WPF</category><category domain="http://blogs.msdn.com/b/ansont/archive/tags/Multitouch/">Multitouch</category><category domain="http://blogs.msdn.com/b/ansont/archive/tags/Collaboration/">Collaboration</category><category domain="http://blogs.msdn.com/b/ansont/archive/tags/Surface+SDK/">Surface SDK</category></item><item><title>Multi-touch in WPF 4 Part 3 – Manipulation Events</title><link>http://blogs.msdn.com/b/ansont/archive/2010/01/11/multi-touch-in-wpf-4-part-3-manipulation-events.aspx</link><pubDate>Mon, 11 Jan 2010 08:03:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9946412</guid><dc:creator>AnsonT</dc:creator><slash:comments>8</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/ansont/rsscomments.aspx?WeblogPostID=9946412</wfw:commentRss><comments>http://blogs.msdn.com/b/ansont/archive/2010/01/11/multi-touch-in-wpf-4-part-3-manipulation-events.aspx#comments</comments><description>&lt;P&gt;One of the most common usage of multi-touch input is for panning, zooming and rotation. With WPF4, the easiest way to implement these gestures is by using the Manipulation events on UIElements. Manipulation events also support simple inertial physics for a more fluid user experience.&lt;/P&gt;
&lt;P&gt;You may well wonder why we call these ‘manipulation’ events rather than gestures like Win32’s WM_GESTURE messages. With manipulation events, we interpret the multi-touch input to simulate directly manipulating the on screen elements, as if you are using your fingers to move, rotate and stretch physical objects. Manipulation events reports translation, rotation and scaling transformations simultaneously, whereas with WM_GESTURES, you can only get one of these transformations components at one time. Thus with WM_GESTURE, you cannot pan and zoom at the same time.&lt;/P&gt;
&lt;P&gt;There are typically 2 ways of using manipulation events: 1) to interpret the events for panning/zooming/rotating content such as maps and images, 2) to interpret these events for manipulating onscreen elements such as organizing a deck of cards, moving puzzle pieces etc. Depending on your scenario, you will decide which elements to enable manipulation on and which element you use as the manipulation container.&lt;/P&gt;
&lt;H4&gt;Manipulation Events&lt;/H4&gt;
&lt;P&gt;Manipulation events on the UIElement is a state machine for the interaction sequence.&lt;/P&gt;
&lt;P&gt;&lt;A href="http://blogs.msdn.com/blogfiles/ansont/WindowsLiveWriter/MultitouchinWPF4Part3ManipulationEvents_80D9/image_4.png" mce_href="http://blogs.msdn.com/blogfiles/ansont/WindowsLiveWriter/MultitouchinWPF4Part3ManipulationEvents_80D9/image_4.png"&gt;&lt;IMG style="BORDER-RIGHT-WIDTH: 0px; DISPLAY: inline; BORDER-TOP-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; BORDER-LEFT-WIDTH: 0px" title=image border=0 alt=image src="http://blogs.msdn.com/blogfiles/ansont/WindowsLiveWriter/MultitouchinWPF4Part3ManipulationEvents_80D9/image_thumb_1.png" width=351 height=524 mce_src="http://blogs.msdn.com/blogfiles/ansont/WindowsLiveWriter/MultitouchinWPF4Part3ManipulationEvents_80D9/image_thumb_1.png"&gt;&lt;/A&gt; &lt;/P&gt;
&lt;H4&gt;Getting Started&lt;/H4&gt;
&lt;P&gt;There are 3 simple concepts that you need to understand to get started with manipulations.&lt;/P&gt;
&lt;P&gt;First, you need to enable the &lt;STRONG&gt;IsManipulationEnabled &lt;/STRONG&gt;boolean property on elements that are to be manipulated. Setting this property to true on an UIElement will start hit-testing of touch events on the element and raising manipulation events when you drag the element with one or more touch contacts.&lt;/P&gt;
&lt;P&gt;Second, you need to handle the &lt;STRONG&gt;ManipulationStarting&lt;/STRONG&gt; event and specify the ManipulationContainer for the interaction. The ManipulationStarting event is a routed event that is raised from an UIElement with IsManipulationEnabled set to true. This event is raised after the first touch down on the UIElement and before any other manipulation events. This event is used to configure the manipulation processing logic.&lt;/P&gt;
&lt;P&gt;The ManipulationContainer is an element that act as the frame of reference for the manipulation transformation calculations. You can imagine that the manipulation container is the physical surface that the manipulated elements are moving against. The manipulation container cannot be changed during the interaction sequence between ManipulationStarting and ManipulationCompleted.&lt;/P&gt;
&lt;P&gt;Last, you need to handle at least the &lt;STRONG&gt;ManipulationDelta&lt;/STRONG&gt; event to respond to the transformations calculated from the finger movements. The ManipulationDelta event reports pan, zoom, and rotate as separate components to the transformation. The transformation is reported both as delta since the last event (DeltaManipulation) and since the the start of the manipulation (CumulativeManipulation).&lt;/P&gt;
&lt;H4&gt;Basic example&lt;/H4&gt;
&lt;P&gt;In this example, we enable multi-touch manipulation of a red rectangle element on a canvas. You can move the rectangle with 1 finger and rotate and zoom with 2 or more fingers. The following XAML snippet shows hooking the manipulation events and enabling manipulation on the rectangle.&lt;/P&gt;&lt;PRE style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: #f4f4f4; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 96.35%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; HEIGHT: 96px; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px" id=codeSnippet&gt;&lt;SPAN style="COLOR: #0000ff"&gt;&amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #800000"&gt;Canvas&lt;/SPAN&gt; &lt;SPAN style="COLOR: #ff0000"&gt;x:Name&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;="_canvas"&lt;/SPAN&gt;        &lt;BR&gt;        &lt;SPAN style="COLOR: #ff0000"&gt;ManipulationStarting&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;="_canvas_ManipulationStarting"&lt;/SPAN&gt;        &lt;BR&gt;        &lt;SPAN style="COLOR: #ff0000"&gt;ManipulationDelta&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;="_canvas_ManipulationDelta"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;&amp;gt;&lt;/SPAN&gt;    &lt;BR&gt;    &lt;SPAN style="COLOR: #0000ff"&gt;&amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #800000"&gt;Rectangle&lt;/SPAN&gt; &lt;SPAN style="COLOR: #ff0000"&gt;IsManipulationEnabled&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;="True"&lt;/SPAN&gt;               &lt;BR&gt;               &lt;SPAN style="COLOR: #ff0000"&gt;Fill&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;="Red"&lt;/SPAN&gt; &lt;SPAN style="COLOR: #ff0000"&gt;Width&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;="100"&lt;/SPAN&gt; &lt;SPAN style="COLOR: #ff0000"&gt;Height&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;="100"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;/&amp;gt;&lt;/SPAN&gt;&lt;BR&gt;&lt;SPAN style="COLOR: #0000ff"&gt;&amp;lt;/&lt;/SPAN&gt;&lt;SPAN style="COLOR: #800000"&gt;Canvas&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;&amp;gt;&lt;/SPAN&gt;&lt;/PRE&gt;
&lt;P&gt;We will be applying render transformation on the rectangle, the transformation is relative to the canvas so we will use the canvas as the manipulation container.&lt;/P&gt;
&lt;DIV id=codeSnippetWrapper&gt;&lt;PRE style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: #f4f4f4; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px" id=codeSnippet&gt;&lt;SPAN style="COLOR: #0000ff"&gt;private&lt;/SPAN&gt; &lt;SPAN style="COLOR: #0000ff"&gt;void&lt;/SPAN&gt; _canvas_ManipulationStarting(&lt;SPAN style="COLOR: #0000ff"&gt;object&lt;/SPAN&gt; sender, &lt;BR&gt;                              ManipulationStartingEventArgs e)&lt;BR&gt;{&lt;BR&gt;    e.ManipulationContainer = _canvas;&lt;BR&gt;    e.Handled = &lt;SPAN style="COLOR: #0000ff"&gt;true&lt;/SPAN&gt;;&lt;BR&gt;}&lt;/PRE&gt;&lt;BR&gt;&lt;/DIV&gt;
&lt;P&gt;We handle the ManipulationDelta event to apply the render transformation to the rectangle. First we retrieve the rectangle as the original source of the manipulation event. Then we extract the current render transformation as a MatrixTransform.&lt;/P&gt;
&lt;P&gt;To calculate the effects of the manipulation, we apply the scale, rotation and translation transformation components from the event argument to the current render transform. In matrix calculations, the order of transformation (multiplication) is important. We need to apply scaling and rotation first centered at the manipulation origin before moving the rectangle based on the translation component.&lt;/P&gt;
&lt;DIV id=codeSnippetWrapper&gt;&lt;PRE style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: #f4f4f4; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px" id=codeSnippet&gt;&lt;P&gt;&lt;SPAN style="COLOR: #0000ff"&gt;private&lt;/SPAN&gt; &lt;SPAN style="COLOR: #0000ff"&gt;void&lt;/SPAN&gt; _canvas_ManipulationDelta(&lt;SPAN style="COLOR: #0000ff"&gt;object&lt;/SPAN&gt; sender,&lt;BR&gt;                                 ManipulationDeltaEventArgs e)&lt;BR&gt;{&lt;BR&gt;&lt;BR&gt;    var element = e.OriginalSource &lt;SPAN style="COLOR: #0000ff"&gt;as&lt;/SPAN&gt; UIElement;&lt;BR&gt;&lt;BR&gt;    var transformation = element.RenderTransform &lt;BR&gt;                                         &lt;SPAN style="COLOR: #0000ff"&gt;as&lt;/SPAN&gt; MatrixTransform;&lt;BR&gt;    var matrix = transformation == &lt;SPAN style="COLOR: #0000ff"&gt;null&lt;/SPAN&gt; ? Matrix.Identity : &lt;BR&gt;                                   transformation.Matrix;&lt;BR&gt;    &lt;BR&gt;    matrix.ScaleAt(e.DeltaManipulation.Scale.X, &lt;BR&gt;                   e.DeltaManipulation.Scale.Y,&lt;BR&gt;                   e.ManipulationOrigin.X, &lt;BR&gt;                   e.ManipulationOrigin.Y);&lt;BR&gt;    &lt;BR&gt;    matrix.RotateAt(e.DeltaManipulation.Rotation,&lt;BR&gt;                    e.ManipulationOrigin.X,&lt;BR&gt;                    e.ManipulationOrigin.Y);&lt;BR&gt;    &lt;BR&gt;    matrix.Translate(e.DeltaManipulation.Translation.X, &lt;BR&gt;                     e.DeltaManipulation.Translation.Y);&lt;BR&gt;    &lt;BR&gt;    element.RenderTransform = &lt;SPAN style="COLOR: #0000ff"&gt;new&lt;/SPAN&gt; MatrixTransform(matrix);&lt;BR&gt;    e.Handled = &lt;SPAN style="COLOR: #0000ff"&gt;true&lt;/SPAN&gt;;&lt;BR&gt;}&lt;/P&gt;&lt;/PRE&gt;&lt;BR&gt;&lt;/DIV&gt;
&lt;P&gt;&lt;STRONG&gt;That’s it! &lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;In the next parts of the series, I’ll talk about inertial movement and single finger rotation with manipulation pivot.&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9946412" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/b/ansont/archive/tags/WPF/">WPF</category><category domain="http://blogs.msdn.com/b/ansont/archive/tags/Multitouch/">Multitouch</category></item><item><title>Multi-touch in WPF 4 - Part 2</title><link>http://blogs.msdn.com/b/ansont/archive/2009/12/11/wpf4-multitouch-part-2.aspx</link><pubDate>Fri, 11 Dec 2009 19:09:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9935843</guid><dc:creator>AnsonT</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/ansont/rsscomments.aspx?WeblogPostID=9935843</wfw:commentRss><comments>http://blogs.msdn.com/b/ansont/archive/2009/12/11/wpf4-multitouch-part-2.aspx#comments</comments><description>&lt;h4&gt;Raw Touch Events&lt;/h4&gt;&lt;p&gt;Touch events are the equivalent of mouse events for multi-touch input. In WPF4, we’ve added touch events to UIElement, UIElement3D and ContentElements. Multi-touch events follow the same patterns as mouse events, with TouchDown, TouchMove and TouchUp, the Preview variants and TouchEnter and TouchLeave. Multi-touch events in WPF are hit-tested and routed through the element tree just like other input events. This is different from the low-level application wide touch event support that is in SL3, I’ll discuss that later.&lt;/p&gt;&lt;p&gt;(For Microsoft Surface SDK developers, TouchDevice corresponds to the Contact class, and Touch events correspond to Contact events).&lt;/p&gt;&lt;p mce_keep="true"&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;a mce_href="http://blogs.msdn.com/blogfiles/ansont/WindowsLiveWriter/MultitouchinWPF4Part2_A1E3/image_2.png" href="http://blogs.msdn.com/blogfiles/ansont/WindowsLiveWriter/MultitouchinWPF4Part2_A1E3/image_2.png"&gt;&lt;img style="BORDER-BOTTOM: 0px; BORDER-LEFT: 0px; DISPLAY: inline; BORDER-TOP: 0px; BORDER-RIGHT: 0px" title="image" border="0" alt="image" width="429" height="803" mce_src="http://blogs.msdn.com/blogfiles/ansont/WindowsLiveWriter/MultitouchinWPF4Part2_A1E3/image_thumb.png" src="http://blogs.msdn.com/blogfiles/ansont/WindowsLiveWriter/MultitouchinWPF4Part2_A1E3/image_thumb.png"&gt;&lt;/a&gt; &lt;/p&gt;&lt;p&gt;Each touch contact (finger) is associated with a different TouchDevice. You can use the instance or the Id of the TouchDevice to keep track of the contact between TouchDown and TouchUp events. &lt;/p&gt;&lt;p&gt;WPF also supports the notion of multiple capture for touch events. When an input device is captured to an element, all the input events from that device are routed from that element regardless of whether the input is directly over the element, no hit-testing need to be performed. With multi-touch events, each element can capture multiple TouchDevices and multiple elements can capture simultaneously. This feature allow WPF to support multiple simultaneous active controls, and one of the main differences between the WPF and the native Win32 touch support.&lt;/p&gt;&lt;p&gt;The following is a simple example of handling multi-touch events. In this example, we place a shape on a canvas under each finger, and track the shapes while the fingers are moving. &lt;/p&gt;&lt;p mce_keep="true"&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;First we hook up the touch event handlers on the canvas&lt;/p&gt;&lt;div class="csharpcode"&gt;&lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;Canvas&lt;/span&gt; &lt;span class="attr"&gt;x:Name&lt;/span&gt;&lt;span class="kwrd"&gt;="_canvas"&lt;/span&gt;                    &lt;span class="attr"&gt;Background&lt;/span&gt;&lt;span class="kwrd"&gt;="LightYellow"&lt;/span&gt;                   &lt;span class="attr"&gt;TouchDown&lt;/span&gt;&lt;span class="kwrd"&gt;="_canvas_TouchDown"&lt;/span&gt;         &lt;span class="attr"&gt;TouchMove&lt;/span&gt;&lt;span class="kwrd"&gt;="_canvas_TouchMove"&lt;/span&gt;         &lt;span class="attr"&gt;TouchUp&lt;/span&gt;&lt;span class="kwrd"&gt;="_canvas_TouchUp"&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;   &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;Canvas&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;style type="text/css"&gt;.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; }&lt;/style&gt;&lt;/div&gt;&lt;style type="text/css"&gt;.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; }&lt;/style&gt;&lt;p mce_keep="true"&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;The TouchDown handler creates a shape for the particular touch device, adds the shape to the canvas, moves it under the finger position and stashes it away in a dictionary for later.&lt;/p&gt;&lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; _canvas_TouchDown(&lt;span class="kwrd"&gt;object&lt;/span&gt; sender, TouchEventArgs e) {     &lt;span class="rem"&gt;// New Shape for Touch Device &lt;/span&gt;    var shape = CreateSomeShape();     &lt;span class="rem"&gt;// Get Touch Point relative to _canvas coordinates &lt;/span&gt;    var origin = e.GetTouchPoint(_canvas);    &lt;span class="rem"&gt;// Move the shape to the touch point &lt;/span&gt;    shape.RenderTransform = &lt;span class="kwrd"&gt;new&lt;/span&gt; TranslateTransform                 (origin.Position.X-shape.RenderSize.Width/2,                   origin.Position.Y-shape.RenderSize.Height/2);     &lt;span class="rem"&gt;// Stash away the shape &lt;/span&gt;    _shapes[e.TouchDevice] = shape;     &lt;span class="rem"&gt;// Add the shape to the canvas &lt;/span&gt;    _canvas.Children.Add(shape);     _canvas.InvalidateVisual();     &lt;span class="rem"&gt;// Capture the touch device &lt;/span&gt;    _canvas.CaptureTouch(e.TouchDevice); } &lt;/pre&gt;&lt;style type="text/css"&gt;.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; }&lt;/style&gt;&lt;p&gt;The TouchMove handler retrieves the shape associated with the touch device and moves it under the current finger position&lt;/p&gt;&lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; _canvas_TouchMove(&lt;span class="kwrd"&gt;object&lt;/span&gt; sender, TouchEventArgs e) {      &lt;span class="kwrd"&gt;if&lt;/span&gt; (e.TouchDevice.Captured == _canvas)      {          &lt;span class="rem"&gt;// Retrieve the shape associated with the device &lt;/span&gt;         var shape = _shapes[e.TouchDevice];          &lt;span class="rem"&gt;// Get current touch point &lt;/span&gt;         var origin = e.GetTouchPoint(_canvas);          &lt;span class="rem"&gt;// Move the shape to the new position &lt;/span&gt;         shape.RenderTransform = &lt;span class="kwrd"&gt;new&lt;/span&gt; TranslateTransform(                   origin.Position.X - shape.RenderSize.Width / 2,                    origin.Position.Y - shape.RenderSize.Height / 2);      } }&lt;/pre&gt;&lt;style type="text/css"&gt;.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; }&lt;/style&gt;&lt;p&gt;The TouchUp handler removes the associated shape from the canvas, and removes it from the dictionary.&lt;/p&gt;&lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; _canvas_TouchUp(&lt;span class="kwrd"&gt;object&lt;/span&gt; sender, TouchEventArgs e)   {       &lt;span class="rem"&gt;// Release the captured device &lt;/span&gt;      _canvas.ReleaseTouchCapture(e.TouchDevice);       &lt;span class="rem"&gt;// Clean up the shape &lt;/span&gt;      _canvas.Children.Remove(_trails[e.TouchDevice]);       _shapes.Remove(e.TouchDevice);   }&lt;/pre&gt;&lt;style type="text/css"&gt;.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; }&lt;/style&gt;&lt;p mce_keep="true"&gt;&amp;nbsp;&lt;/p&gt;&lt;p mce_keep="true"&gt;&amp;nbsp;&lt;/p&gt;&lt;h3&gt;Multi-touch in Silverlight 3 and 4&lt;/h3&gt;&lt;p&gt;Silverlight also supports multi-touch input on Windows 7. Both Silverlight and WPF allows you to retrieve the raw window level multi-touch input via the static Touch.FrameReported event.&lt;/p&gt;&lt;p&gt;&lt;a mce_href="http://blogs.msdn.com/blogfiles/ansont/WindowsLiveWriter/MultitouchinWPF4Part2_A1E3/image_4.png" href="http://blogs.msdn.com/blogfiles/ansont/WindowsLiveWriter/MultitouchinWPF4Part2_A1E3/image_4.png"&gt;&lt;img style="BORDER-RIGHT-WIDTH: 0px; DISPLAY: inline; BORDER-TOP-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; BORDER-LEFT-WIDTH: 0px" title="image" border="0" alt="image" width="307" height="217" mce_src="http://blogs.msdn.com/blogfiles/ansont/WindowsLiveWriter/MultitouchinWPF4Part2_A1E3/image_thumb_1.png" src="http://blogs.msdn.com/blogfiles/ansont/WindowsLiveWriter/MultitouchinWPF4Part2_A1E3/image_thumb_1.png"&gt;&lt;/a&gt; &lt;/p&gt;&lt;p&gt;GetTouchPoints returns the touch device positions relative to a particular element. Touch Up/Move/Down events are identified in the Action property of the TouchPoint class.&lt;/p&gt;&lt;p&gt;GetPrimaryTouchPoint returns the position of the first finger down in this multi-touch input sequence&lt;/p&gt;&lt;p&gt;Calling SuspendMousePromotionUntilTouchUp will prevent the touch devices from raising the equivalent mouse events. This allows panning to be implemented without also invoking mouse interactions like button clicks or listbox selections.&lt;/p&gt;&lt;p&gt;To support Pan/Zoom/Rotate gestures in SL, Surface will be providing the System.Windows.Input.Manipluations.DLL (the .NET4 core manipulation and inertia processors) as a separate download in the future. This assembly is part of .NET4, and used to implement the WPF4 manipulation events.&lt;/p&gt;&lt;h4&gt;Touch User Experience&lt;/h4&gt;&lt;p&gt;There are some subtle differences in user experience when dealing with multiple touches that are not immediately obvious. Let’s take Button as an example. With mouse, the button click event is raised when the mouse button is released over the button. However, if you use multiple fingers to press a button, you only want to raise the click event when the LAST finger is lifted from the button. All of the WPF and SL controls are built based on mouse events, luckily with the availability of the Surface SDK for WPF4, you will be able to get the ‘correct’ multi-touch user experience without having to write your own controls.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9935843" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/b/ansont/archive/tags/WPF/">WPF</category><category domain="http://blogs.msdn.com/b/ansont/archive/tags/Multitouch/">Multitouch</category></item><item><title>Stunning data visualization in the AlloSphere</title><link>http://blogs.msdn.com/b/ansont/archive/2009/12/08/stunning-data-visualization-in-the-allosphere.aspx</link><pubDate>Tue, 08 Dec 2009 21:48:32 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9934283</guid><dc:creator>AnsonT</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/ansont/rsscomments.aspx?WeblogPostID=9934283</wfw:commentRss><comments>http://blogs.msdn.com/b/ansont/archive/2009/12/08/stunning-data-visualization-in-the-allosphere.aspx#comments</comments><description>&lt;p&gt;Really amazing work bringing together scientific data, 3D visualization, interactivity, and music.&lt;/p&gt; &lt;p&gt;&lt;object width="446" height="326"&gt;&lt;param name="movie" value="http://video.ted.com/assets/player/swf/EmbedPlayer.swf"&gt;&lt;/param&gt;&lt;param name="allowFullScreen" value="true" /&gt;&lt;param name="wmode" value="transparent"&gt;&lt;/param&gt;&lt;param name="bgColor" value="#ffffff"&gt;&lt;/param&gt; &lt;param name="flashvars" value="vu=http://video.ted.com/talks/dynamic/JoAnnKuchera-Morin_2009-medium.flv&amp;amp;su=http://images.ted.com/images/ted/tedindex/embed-posters/JoAnnKuchera-Morin-2009.embed_thumbnail.jpg&amp;amp;vw=432&amp;amp;vh=240&amp;amp;ap=0&amp;amp;ti=516&amp;amp;introDuration=16500&amp;amp;adDuration=4000&amp;amp;postAdDuration=2000&amp;amp;adKeys=talk=joann_kuchera_morin_tours_the_allosphere;year=2009;theme=the_creative_spark;theme=presentation_innovation;theme=speaking_at_ted2009;theme=numbers_at_play;event=TED2009;&amp;amp;preAdTag=tconf.ted/embed;tile=1;sz=512x288;" /&gt;&lt;embed src="http://video.ted.com/assets/player/swf/EmbedPlayer.swf" pluginspace="http://www.macromedia.com/go/getflashplayer" type="application/x-shockwave-flash" wmode="transparent" bgColor="#ffffff" width="446" height="326" allowFullScreen="true" flashvars="vu=http://video.ted.com/talks/dynamic/JoAnnKuchera-Morin_2009-medium.flv&amp;su=http://images.ted.com/images/ted/tedindex/embed-posters/JoAnnKuchera-Morin-2009.embed_thumbnail.jpg&amp;vw=432&amp;vh=240&amp;ap=0&amp;ti=516&amp;introDuration=16500&amp;adDuration=4000&amp;postAdDuration=2000&amp;adKeys=talk=joann_kuchera_morin_tours_the_allosphere;year=2009;theme=the_creative_spark;theme=presentation_innovation;theme=speaking_at_ted2009;theme=numbers_at_play;event=TED2009;"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9934283" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/b/ansont/archive/tags/DataViz/">DataViz</category><category domain="http://blogs.msdn.com/b/ansont/archive/tags/eScience/">eScience</category></item><item><title>Multi-touch in WPF 4 – Part 1</title><link>http://blogs.msdn.com/b/ansont/archive/2009/12/03/multi-touch-in-wpf-4-part-1.aspx</link><pubDate>Thu, 03 Dec 2009 17:26:17 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9932077</guid><dc:creator>AnsonT</dc:creator><slash:comments>1</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/ansont/rsscomments.aspx?WeblogPostID=9932077</wfw:commentRss><comments>http://blogs.msdn.com/b/ansont/archive/2009/12/03/multi-touch-in-wpf-4-part-1.aspx#comments</comments><description>&lt;p&gt;During PDC 09, I co-presented a multi-touch &lt;a href="http://microsoftpdc.com/Sessions/CL27"&gt;session&lt;/a&gt; with Robert Levy from Surface.&amp;#160; (BTW, You have got to see the &lt;a href="http://blogs.msdn.com/surface/archive/2009/11/19/surface-monster-mashup-and-real-world-objects.aspx" target="_blank"&gt;monster demo&lt;/a&gt; that Robert gave on the Surface unit.) We made a couple of significant announcements for WPF multi-touch developers.&lt;/p&gt;  &lt;p&gt;First, in post beta 2 builds of WPF, we will have built-in touch panning support for standard controls (e.g. Listbox, ListView, DataGrid, TextBox, ScrollViewer, etc.). This means that any WPF4 application will get basic touch support for panning without any additional work from the developer.&lt;/p&gt;  &lt;p&gt;Second, Robert announced that Surface will be making the Surface multi-touch controls available to all WPF developers to run on Windows 7. This is really great news for WPF developers. Now you can write fully multi-touch themed and optimized applications using the Surface controls that run anywhere. These will be available as a separate download around the time of Visual Studio 2010 release.&lt;/p&gt;  &lt;p&gt;I also presented a deep dive into the WPF 4 multi-touch APIs in a chalk talk at the Web Pavilion.&amp;#160; Unfortunately that session was not recorded. I will share the slides and samples on this blog, and in future posts I will go into more details about each of the samples.&lt;/p&gt; &lt;iframe style="padding-bottom: 0px; background-color: #fcfcfc; padding-left: 0px; width: 98px; padding-right: 0px; height: 115px; padding-top: 0px" title="Preview" marginheight="0" src="http://cid-0d695ca64e3fb0c5.skydrive.live.com/embedicon.aspx/PDC%2009/MT%20ChalkTalk%20Slides%20and%20Demo.zip" frameborder="0" marginwidth="0" scrolling="no"&gt;&lt;/iframe&gt;&lt;iframe style="padding-bottom: 0px; background-color: #fcfcfc; padding-left: 0px; width: 98px; padding-right: 0px; height: 115px; padding-top: 0px" title="Preview" marginheight="0" src="http://cid-0d695ca64e3fb0c5.skydrive.live.com/embedicon.aspx/PDC%2009/WPF4%20MultiTouch%20Deep%20Dive.pptx" frameborder="0" marginwidth="0" scrolling="no"&gt;&lt;/iframe&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9932077" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/b/ansont/archive/tags/WPF/">WPF</category><category domain="http://blogs.msdn.com/b/ansont/archive/tags/Multitouch/">Multitouch</category></item></channel></rss>