Tuesday, August 25, 2009

Touch Improvements

The last version of the touch window and touch lists still needed improvements, notably on scrolling smoothness and clicking accuracy. In this post I'm presenting new versions of both classes where I tried to address these issues. The bottom line is that clicking feels much better but scrolling is still a bit jagged. I have to say that in order to get a game-like smooth screen scrolling one would have to choose something like DirectDraw because GDI was not made for this. Anyway, you will be the judge.

First I changed how the window scrolls by removing the timer. How do you force the window to scroll without a timer? Well, it's kind of easy: set up a scrolling mechanism that determines the next position based on the current time (I showed how to do that with the kinematic equations), set up a cutoff point (time and / or position) and just invalidate the whole window after painting. If you just invalidate the window, you allow all other messages to be processed and when the message queue is empty, the OS will send you a WM_PAINT message. If the window is still scrolling, you calculate the new position (based on the current time), paint the window and if the motion has not stopped, you invalidate the window again. This way you get a more natural way of scrolling the window and you know that you will get the best screen update frequency that GDI can muster. Note that in order to implement this in a generic way, I had to implement the OnPaint handler in CTouchWindow. This class delegates to its children through the "static virtual" Paint method.

In this process I had to update the way the kinematic equations are calculated due to some rounding errors I found on QVGA devices. To solve the issue, I changed the main equation back to the more classical form but reduced the timer precision from millisecond to hundredths of a second (divided by 10 in order to get smaller number from multiplication). The rounding error seems to be gone. I have also added a double criteria to test if the motion did end: now the code tests for both time limit and end point.

To help with both scrolling and clicking, I added a new class named CTouchGesture that essentially handles all the data coming from the stylus (mouse) messages and helps CTouchWindow determine if the last gesture was a click or a "flick". Note that for flicking, the class adds up all the partial moves (compensating for changes in direction) and reports an "average" flick speed (total displacement and time) instead of the last move.

Clicking the items is now a bit more reliable because the code tests for clicking eligibility. If the window is moving and you click it, there will not be an OnClick call: you will only get one if the window is still to begin with.

I hope that these modifications did improve the code and the user experience, but with my limited assortment of devices I cannot have a good judgment on that. So please tell me what you think!

Sample code: AppStart01.zip (161 KB)


Steven Pence said...

Looks good. I have a touch list of my own design that I wish behaved as realistically as yours. Then again, I've focused more on finger usability that realistic physics.

Good work.

João Paulo Figueira said...

I believe that finger usability is what's lacking here - it could be improved. I am working on this right now...