Sunday, September 20, 2009

View transitions

Now that I managed to get some decent finger feedback from the list, it's time to get back to the CrypSafe prototype and add some view transitions. The code I'm using is based on an article I published last year on CodeProject: Animating View Transitions on Windows Mobile. Please read it before continuing as what you will see here is an extension of what I wrote there.

Essentially this article explored the ability to do some fashionable (read iPhone-like) view transitions using child views implemented as regular Win32 controls (such as a tree view, a list view or even a dialog). The view transitions were implemented using a very simple mechanism:
  • Capture the existing view as a bitmap;
  • Remove the from the frame container;
  • Paint the view bitmap on the frame client area;
  • Create the new child view window off screen;
  • Enter a loop where the bitmap is scrolled to the requested direction a few pixels;
  • Every time the bitmap is scrolled, move the new child window to the contiguous position thus creating the illusion that both windows are moving in lockstep.
That was a bit crude but worked. One of the lessons I learned from writing this article is that, generally, you cannot force an arbitrary window to paint itself to a memory DC. This would be very useful for some advanced visual effects. By reading the docs you might even be tempted (as I was) to send a WM_PAINT message to the hidden window with your memory DC in the WPARAM and expect it to paint there, but that just doesn't work for all windows. That's why I had to use MoveWindow for the animation.

Now that we are rendering the touch windows and lists directly on a memory DC, there is a better chance to improve on the original algorithm and implement a smoother view transition algorithm. This is what you will find in the sample code (see below).

The major change I made to the code was to CChildViewBase where you can now see a GetBitmap virtual method. If this method returns NULL, then the child view is not able to render itself on a bitmap and the old brute-force method will be used. If, on the other hand, the child view is able to render itself to a bitmap it must do so here. Note how this is implemented in the CCrypSafeView class: the painting engine is called directly and a new HBITMAP is returned for the child view manager to paint.

The results are here for you to see: acceptable on some devices, way too fast on others and slower on older devices. What we need to do here is quite simple: use the same kinematics equations to control the view transition motion and leave nothing to chance.

Comments and suggestions are welcome!

Sample code: (349 KB)


vincent said...


some remarks, oledbclient project is still using complete path instead of relative ones and get a missing header :

Error 1 fatal error C1083: Cannot open include file: 'BlobStream.h': No such file or directory c:\downloads\CrypSafe05\OleDbClient\Rowset.cpp 5

João Paulo Figueira said...

Yikes! Sorry! I will correct that in the next post.

vincent said...

I have tested and I am not really convinced at all. Transitions are eithier too fast or inexistent.
And I think that previous scrolling behavior was better ...

João Paulo Figueira said...

I will change the view transition behavior in order to bring it under control. As for the scrolling behavior, I also have mixed feelings. On some (older) devices it does work well, but on my HTC Touch Pro I still see some "fluctuations". I will go back to the timed approach (maybe consider both).

Thank you for your input!

vincent said...

I suppose you already read this :

very interesting

João Paulo Figueira said...

Indeed. My work here is getting more irrelevant each passing day.