Nachdem wir einen Featurerequest bekommen habe, dieser schnell und einfach einzubauen war bzw. ich das sowieso schon längst machen wollte, gibts jetzt eine neue Version.

Neue Features:

  • Man kann einstellen das die Aufzeichnung (Scrolling) weiterläuft auch wenn das Gerät nicht bewegt wird.
  • Eine Wasseraage mit grafischer Anzeige (TrackBar) und Ausgabe der X und Y Koordinaten.

English:

After we got a feature request, it was easy and fast to build in respectively I wanted this feature as well for a long time, we have a new version.

New features:

  • you can set it to keep the data scrolling even if no angle change was done.
  • a level with gafical output (TrackBar) and outupt of X and Y coordinates.

ShockTester

Pano2VR is a tool to create panoramas for QuicktimeVR or Flash. You can embed the Flash in your surface application and completly control it with multitouch by using the Pano2VR Flash Javascript API.

Unfortunatly, the only way to embed your Flash is the Shockwave ActiveX.  So we need to put it in a WindowsFormsHost wich has some side effects with Z-Order and contact detection. The WindowsFormsHost always renders on top. So contacts on our window will not be recognized. You can however use the core layer of surface and wire up a ContactTarget with the window handle of the FormsHost.

However, I used a different approach. I put a transparent(*) window on top of the window that has the windowsformshost. That window can be used to recognize the contacts. If you had any UI controls, that would need to be placed on top of the flash, that would also be the place to do it. So this would also solve the Z-Order issue.

I also put the Active X in my own usercontrol for convinience reasons. The usercontrol then supplies all the function calls for loading, paning, tilting and zooming. The functions inside the flash are called with the activex’s CallFunction method. You also need to make sure to set the “externalinterface=1″ flashvar when loading the movie. Otherwise the function calls will throw a COMException.

In the overlaywindow I initialize an Affine2DManipulationProcessor to track the contacts on it’s surface. The deltas will then be used to call the Flash’s functions and thats it.

* Well, not really transparent, since then the contacts just fall throug and the contact events will not raise. But a white background with an opacity of 0.01

Schon oft gesehen in Beispielen zu Image Interop ist folgender Code:

 

BitmapSource bitmap = System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap(source.GetHbitmap(), IntPtr.Zero, Int32Rect.Empty, System.Windows.Media.Imaging.BitmapSizeOptions.FromEmptyOptions());

Das funktioniert soweit auch hat aber einen entscheidenden Fehler, auf den man schnell kommt, wenn man sich die MSDN Dokumentation anschaut.

Der Handle der von GetHBitmap zurückgeliefert wird, muss nämlich manuell wieder freigegeben werden. Und zwar mit der DeleteObject Methode:

[System.Runtime.InteropServices.DllImport("gdi32.dll")]
public static extern bool DeleteObject(IntPtr hObject);

 

 

 

Hallo, ich habe gestern versucht von einem USB-Stick zu installieren der mit NTFS Formatiert ist.

Im „boot“ Verzeichnis der Vista Installations CD ist die „bootsect.exe“, mit dieser wird der Boot Sektor auf dem Stick erzeugt der Befehl lautet. Der Befehl wird im Befehlsfenster (cmd.exe) ausgefuehrt.
bootsect /nt60 G:
Damit der Befehl so ausgeführt werden kann, muss man im Verzeichnis „boot“ stehen.

G ist der Laufwerksbuchstabe des USB Stick -> Bitte verwenden sie den Laufwerksbuchstaben den der USB Stick auf ihrem Computer hat.

Hier die komplette Anleitung in Englisch.

Control.Invoke gibt es in der schönen neuen WPF Welt leider nicht mehr. Darum ein kurzer Post ohne viel Erklärung wie man das in WPF Anwendungen löst.

private void SetPicture(BitmapSource newImageFromThread)
{
   if (Camera.Dispatcher.CheckAccess())
  
{
     
// The calling thread owns the dispatcher, and hence the UI element  
     
Camera.Source = newImageFromThread;
   }
  
else
  
{
      newImageFromThread.Freeze();
     
// Invokation required
    
Camera.Dispatcher.Invoke(DispatcherPriority.Normal, (Action)delegate(){ Camera.Source =newImageFromThread; });
}}

Der eigentliche Spass war jedoch das BitmapSource. Dieses ist leider nicht MultiThread fähig, deswegen muß man BitmapSource.Freeze(); aufrufen! Hoffe das erspart euch irgendwann ein wenig suchen ;)

Erste Tests der WordPress Application für den Blackberry. Ich befürchte das es mit der Localization noch nicht ganz klappt, aber vom ersten Eindruck schaut das Tool schon sehr gut aus. Blogbeitrag und Downloadlink von Blackberrycool:

http://www.blackberrycool.com/2009/07/open-source-wordpress-application-for-blackberry-now-in-public-beta/

First tests with WordPress Application for Blackberry. As far as I see there may be some problems with localization, but my first impressions are quite positive. Blog post and downloadlink:

http://www.blackberrycool.com/2009/07/open-source-wordpress-application-for-blackberry-now-in-public-beta/

I’ll keep you informed!

There are already a lot of useful WPF UI controls that, with a few easy adjustments, can be used within a Surface application. Basically you only need to adjust mouse events to contact events.

In this blog post I cover how you can make 2 controls Surface ready, provide a quick walkthrough and the resulting code.

First is the WPF Book control from Mitsu Furuta that is available at Codeplex (http://www.codeplex.com/wpfbookcontrol) and is described in a blog post at http://blogs.msdn.com/mitsu/archive/2007/04/18/wpf-book-control.aspx .

The second are the 3D tools found under http://3dtools.codeplex.com/ .

WPF Book Control

To port the book control I used the Project WPFMitsuControls  and renamed it to SFMitsuControl.

First thing to do is to add the necessary references Microsoft.Surface and Microsoft.Surface.Presentation.

The book is based on a WPF ItemsControl and the pages are WPF ContentControl’s. To make them Surface enabled we need to change them to the corresponding Surface controls. After importing the namespace with xmlns:s=”http://schemas.microsoft.com/surface/2008″, we make the following changes:

<ItemsControl will be changed into <s:SurfaceItemsControl and

<ContentControl will be changed to <s:SurfaceContentControl

Don’t forget to change the code behind in Book.cs and BookPage.cs to inherit from the corresponding base classes.

This enables us to the ContactDown, ContactChanged and ContactUp events that we will use to replace the corresponding mouse events of the BookPage. We also need to change the MouseDown on the BookPages inside the book control.  And that’s it! The code is pretty much the same as with the mouse events. You only need to make small adjustments like capturing the contact instead of the mouse.

The resulting code can be downloaded here: Surface Book Control

I took the demo app as is and only made a surface window and changed the UserControl to SurfaceUserControl. I did not bother to make the Usercontrols completely Surface enabled.

3D Tools

The second thing I cover are the 3D Tools. I will go over updating the trackball and Trackport3D.

We could just do the same with the trackball that we already did with the book control, but there is one thing that would be bothering. The trackball is moved with the left mouse button and zooming is done with the right mouse button. Of course we can’t zoom like this on a Surface. We don’t have a right button and on top of that it would be totally not cool! We will use multitouch zoom to accomplish this.

Luckily, MS gave as the ManipulationProcessor class that will greatly reduce the effort to interpret touch gestures.

Again, we start by adding the references Microsoft.Surface and Microsoft.Surface.Presentation.

The first control we change will be the Trackball. We need to add a local variable for our manipulation processor:

private Affine2DManipulationProcessor manipulationProcessor;

And then change the initialization of the events and init the processor when the EventSource Property gets updated.

this.manipulationProcessor = new Affine2DManipulationProcessor(

                            Affine2DManipulations.TranslateX |

                            Affine2DManipulations.TranslateY |

                            Affine2DManipulations.Scale,

                            _eventSource, false);

 

                manipulationProcessor.Affine2DManipulationDelta += new EventHandler<Affine2DOperationDeltaEventArgs>(manipulationProcessor_Affine2DManipulationDelta);

 

                input.PreviewContactDown += new ContactEventHandler(input_PreviewContactDown);

                input.PreviewContactUp += new ContactEventHandler(input_PreviewContactUp);

This creates a new manipulation processor that allows us to translate and scale. We hook up to the Affine2DManipulationDelta event that tells us the scale and translate deltas that we will use to update our transform object.

We also hook up to the ContactDown and ContactUp events. When a contact is recognized in the ContactDown event handler, we capture it and tell our manipulation processor to track the contact. From now on, any change to the contact will go through our processor, and results in a delta in scale or translation. The processor does all the hard work here and we only need to look at the deltas, to see our change. The delta event handler looks like this now:

if (e.ScaleDelta != 0.0)

            {

                _previousPosition2D.X = e.ManipulationOrigin.X – e.Delta.X;

                _previousPosition2D.Y = e.ManipulationOrigin.Y – e.Delta.Y;

                _previousPosition3D = ProjectToTrackball(EventSource.ActualWidth, EventSource.ActualHeight, _previousPosition2D);

                Track(e.ManipulationOrigin);

            }

 

            Zoom(e.ScaleDelta);

It’s pretty simple and just reuses the Track and Zoom function we already have.

We also need to update our Trackport3D UserControl to a SurfaceUserControl. And we need to change how the Trackport3D uses the trackball. The old one used a border control to capture the mouse events. Since we need a contact enabled control to capture the events, we will use a SurfaceContentControl to achieve this.

And that’s it for the trackball control. The resulting code can be found here: Surface 3D Tools

Conclusion

As you can see, it’s very easy to build upon available WPF controls for your Surface application. The changes are straight forward and the ManipulationProcessor gives you a great way to easily implement touch gestures.