Wednesday, June 25, 2008

The Touch List

This has been a busy month for me, as the number of posts clearly shows. After publishing the article on animating WTL child view transitions on Code Project, I decided to investigate how to implement a "touch" list on Windows Mobile. This kind of controls are all the rage right now, thanks to devices such as the Apple iPhone, or the HTC Touch Diamond. Many other device manufacturers are also implementing their own versions of these lists because they are easy to use and are "finger-friendly". Nowadays the trend seems to be towards using your own fingers and not the stylus.

So what does a "touch" list have to do? I would say it has to:
  • Scroll smoothly;
  • Follow your finger when you drag, scrolling the list;
  • Automatically scroll the list when you finish dragging it.

Let's look at each one of these requirements.

Smooth Scrolling
The native Windows CE list controls don't scroll very smoothly. In fact, they usually scroll taking the item height as the scrolling quantum. On some ocasions, you will even see a full list refresh when you request a new page. This is not an acceptable behavior for a touch list.

A touch list scrolls one pixel at a time if needed be, clipping the items that are partially visible.

Drag Scrolling
This feature is also not implemented in none of the native list controls. If you click an item and drag the stylus, the list will not scroll to follow it. The underlying item will be selected, or some other custom behavior will occur, but the list will not scroll.

A touch list follows your finger or stylus and scrolls to keep the selected item in sync.

Autoscrolling
This is the coolest feature of a touch list that makes it behave like a flywheel: you nudge it and it keeps turning until the spindle friction dissipates all energy and the wheel stops. I have yet to see if the standard implementations support some kind of list "inertia" where successive quick drags accelerate the scrolling speed. Of course, this is not implemented in any of the native lists.

My Proposal
After considering all of the above, I wrote a sample implementation of a touch list (download here). The sample displays your contacts list (the FileAs property) and allows you to scroll the list up and down. It follows your finger and autoscrolls if you drag it quickly.

The implementation is far from complete and you will see lots of things changing in the next few days as I implement item states, mutiple columns, horizontal scrolling and some other cool features. Ah, this is WTL 8.0, of course!

Friday, June 06, 2008

Animating Child View Transitions - The article

I have just posted a new article on Code Project with the last version the the child view transition animation code. You can read the article here.

Tuesday, May 27, 2008

An alternative to the SHMENUBAR resource

The SHMENUBAR resource is a pain. A real pain. Why is there no support for this on the VS 2005 / 2008 resource editor? This resource is actually quite powerful when it comes to defining the WM application menu and fine-tuning its appearance. But when you need to change something, you need to remember the string table IDs, the toolbar button options and all that.

Most WM applications I have seen so far use a popup menu attached to each of the menu bar buttons. If this is your case, you can forget about the SHMENUBAR resource and use the menu editor. Create a menu with two items and their popups on the resource editor. If you are using WTL, go to your CMainFrame::OnCreate method and instead of the simple

CreateSimpleCEMenuBar();

write:

CreateSimpleCEMenuBar(IDR_MAINFRAME, SHCMBF_HMENU);

The IDR_MAINFRAME is your main menu ID. And that's all you need.

If you are using straight API calls, when calling the SHCreateMenuBar API, make sure that the dwFlags member of the SHMENUBARINFO contains the SHCMBF_HMENU flag and that nToolbarId contains your menu ID.

Monday, May 26, 2008

The tamed tree view

On my last post I described a strange behavior of the tree view control when it is used as a WTL child view and when it is scrolled into view using the SlideView sample application that I have been developing to illustrate child view animations. The solution for this problem was, as I suspected, to host the tree view control in another window and making this window the frame's child view. All animations work correctly now when the tree view control is showed up.

In this latest version of the sample, I extended the use of the CSelectionBar control (some call it the header bar control) in order to select which animation to perform (using the left menu). Now the code also supports switching views without any animation (select 'None').

This control will be updated to allow userd to display arbitrary windows instead of a standard popup menu and also will allow the inclusion of other controls in the toolbar (like an edit control or a combobox).

Thursday, May 22, 2008

The misbehaved tree view

Following up on the WTL child view animation code I have been working on, I have noticed that when the tree view child window is selected into view (see the sample application), the animation never works as expected. In fact, the tree does not seem to correctly repaint while it is being moved, contrary to the form and list view. After selecting the tree view it also fails to correctly repaint when you open another application and return to the sample (use the Memory applet).

This problem became more apparent when I decided to adapt a very old piece of code to WTL 8.0: the selection tool bar (what you see on top of the PPC File Explorer). Being a toolbar, it must coexist with the child view within the same frame, so the scrolling code had to be adapted.

I will post the solution for this problem when I find it. Most likely I will have to host the tree in another window...

Monday, May 19, 2008

Animating Child View Transitions - II

Now that I undestood how to animate child views in a Windows Mobile WTL 8.0 applicaction (see Animating Child View Transitions), it's time to remove all the animation code from the sample's main frame and move it into specialized classes. Child view animations are performed by the CChildViewAnimate mix-in class (see the sample project). To use it, you merely add it to your main frame's inheritance list:


class CMainFrame :
public CFrameWindowImpl<CMainFrame>,
public CUpdateUI<CMainFrame>,
public CChildViewAnimate<CMainFrame>,
public CMessageFilter,
public CIdleHandler


Next, change the main frame's PreTranslateMessage method to this:


if(CFrameWindowImpl<CMainFrame>::PreTranslateMessage(pMsg))
return TRUE;

return ChildPreTranslateMessage(pMsg);


The call to ChildPreTranslateMessage ensures that the active child view class has a chance to do some custom message translation work. To enable this, you must derive all you child view classes from CChildView, like this:


class CSlideFormView :
public CDialogImpl<CSlideFormView>,
public CChildView<CSlideFormView>


If you need to do custom message translation, you must override the PreTranslateMessage:


virtual BOOL PreTranslateMessage(MSG* pMsg)
{
if(!::IsWindow(m_hWnd))
return FALSE;
return CWindow::IsDialogMessage(pMsg);
}


Note the IsWindow test: it is there to avoid having this method called when the child window is already destroyed.

Friday, May 09, 2008

ATL ASSERT on exit

If you tried the sample code I posted yesterday, you might have seen an elusive ATLASSERT dialog box (in Debug mode, of course). When the assertion fires, it happens when the application is closing and the dialog box is very briefly displayed and then closes. You never get to see what caused the assertion in the first place nor do you get a chance to break into the debugger.

To handle this situation, I changed the ATLASSERT macro definition the following way:

extern void AssertBreakpoint();
#define ATLASSERT(expr) { if(!(expr)) AssertBreakpoint(); \

_ASSERTE(expr); }

When the assertion is triggered, the code first calls the AssertBreakpoint function that is there just for you to place a debugger breakpoint. I implemented it with the following rocket-science code:

void AssertBreakpoint() { int a = 3; }

Now you can run the application and you will be sure that you know where the assertion fired. Why? When the debugger stops on your breakpoint you can immediately check the stack and look at the offending code. In my case the assertion was being fired in the CSlideFormView::PreTranslateMessage method. The form view HWND was already destroyed when the

return CWindow::IsDialogMessage(pMsg);

line was executed and this function validates m_hWnd in debug mode.

So if you find yourself in such a situation, use this technique because by defining your own version of ATLASSERT you essentially "infect" all the ATL and WTL code with your custom implementation. All your ATLASSERT are belong to me.

Thursday, May 08, 2008

Animating Child View Transitions

On my last post I promised to start writing the OLE DB client code to replace the ATL Consumer Templates on mobile and embedded devices. Whenever I write a library, I always look for an interesting application to use the library. In this case there is an obvious candidate: a replacement for the SQL Compact "Query Analyzer".

Instead of writing a dull imitation of the existing tabbed interface, I looked for ways to make a WTL SDI application dynamically change the frame's child view and there was no shortage of ideas, especially on CodeProject: Switch Views in a WTL SDI Application. The code works very well, but there is no provision for animating the child view transition. So I decided to do a little research into this issue and produced an early prototype.

The sample application flips between two views (Form and List) by horizontally scrolling the changing views. The idea is that the form view is on the left and the list view is on the right so when you switch views they animate intuitively: the form hides and the list shows by scrolling to the left and the reverse happens by scrolling to the right. This concept can be extended to vertical scrolling so the user can associate the process of navigating through the application with a map.

There were some challenges I had to overcome to implement this. To make animations smoother, I thought about rendering both views (the old that is going out and the new that is coming in) in a big bitmap and then just paint the bitmap in the frame's client area. Interestingly, there is no documented way to render a hidden window to a memory DC so there was no way to render the new view in the bitmap. You can overcome this if you have full control of the new window's paint cycle, but if you use Windows controls like the list view you are out of luck. I even tried forcing a WM_PAINT message with the memory HDC on the WPARAM, but the list would not render the header... So now I only render to a bitmap the old view and scroll in the new view using MoveWindow.

Another issue I had to take care of is the scrolling speed. The speed of ScrollDC increases as the area to scroll diminishes, so you get a scrolling procedure that gets faster and faster. To make it work at the same apparent speed, I had to time the first scroll and then use the system timer to compensate for faster execution times when the scrolled bitmap gets smaller.

I still need to implement the vertical scrolling and to encapsulate all of the code in a mixin class for the WTL main frame. Stay tuned.

Thursday, May 01, 2008

SQL Compact Command Parameter Sizes

This is not a native issue, but one of the things I learned from the SQL Compact sessions from the last MVP Summit (and I think is not under my NDA, so I can talk about it) is the fact that you can speed up your SqlCeCommand (yes, I'm talking managed code here) by explicitly setting the parameter sizes. This was a bit of a surprise for me because with OLE DB you have no such niceties - when you create a command parameter, you must correctly specify the command parameter size, otherwise you just may see your accessor writing in very strange places...

Coming up: I'm starting to write the native alternative to the ATL OLE DB Consumer Templates for devices. This is going to be a lot of fun...

Thursday, April 24, 2008

MFC: The new Phoenix?

So if you think MFC was dead, think again.

Jessica Liu posted on the Visual C++ Team Blog about the new MFC samples for everything from Office 2007 applications to Visual Studio-like user interfaces. So, is native code dead?

Nope.

Windows XP SP3

If you are an MSDN subscriber, go get XP SP3. It's now available on MSDN subscriptions!

Friday, April 11, 2008

Off to Seattle!

Tomorrow I'm off in a crazy trip to Seattle for the 2008 MVP Summit. If you want to meet me, I'll (try to) be here:

Party with Palermo

Hopefully, I will try to blog about what I can disclose about the Summit and any info I get there.

Friday, April 04, 2008

WTL Helper and VS 2008

My good friend Cristiano Severini has figured out a way to adapt Sergey Solezhentsev's WTL Helper to VS 2008 with a little help from me (I helped him match the VS 2005 typelibs to 2008 because I have both installed side by side). Here's how he did it: WTL Helper and VS 2008.

Crino ROCKS!

Wednesday, April 02, 2008

Smartphone keyboard handling with GAPI

Here's the scenario: you are working on a DirectDraw full screen application and you require full control of the device keyboard. Things have worked nicely with the Pocket PC and even with the WM5 Smartphone, but when you move to WM6 your keyboard is gone. You do get the WM_KEYDOWN and WM_KEYUP messages, but most of them only report the dreaded VK_PROCESSKEY and ImmGetVirtualKey() does not seem to help at all. What can you do?

I found a solution for this problem that solves most of the issues above, but also uncovers some other issues. The solution is to call ImmAssociateContext() on your main window passing NULL as the HIMC parameter. This will remove the input context association from the window, and you get the keyboard back. But...

... now you have to handle the keyboard mappings yourself. That's the price you pay. On some devices this means having a mixed keyboard (numbers and alpha keys) so you must internally implement a keyboard map in order to make it work as the user expects. To make matters worse, the keyboard map is device dependent so you are in for a bit of work. Finally, I have found that on some devices you don't get all the keys, especially the special keys for mail and contacts. These devices seem to have these keys wired to launch the matching applications and not even GAPI seems to release them...

Monday, March 24, 2008

Smartphone display timeout

How do you prevent a Smartphone (sorry, a Windows Mobile 6 Standard) device from falling asleep? I tried everything, including sending null keys:

keybd_event(VK_NONAME, 0, KEYEVENTF_SILENT, 0);

This nasty little trick works but also forces your backlight to the maximum and you may not want it. What I really want to do is mimick going to the Power Management applet and setting the "Display time out" to "Never". With this setting, your Smartphone device will never go to sleep. So how do you achieve this? It's actually quite easy.

The display time out value is stored on the device registry under:

HKEY_CURRENT_USER\ControlPanel\Power

All you have to do is set the Display value (DWORD) to -1 and make the system know that the value changed. How do you break the news? Simple again:

PostMessage(HWND_BROADCAST, WM_WININICHANGE, 0, 0);

If you use this in your application to avoid the device from falling asleep (I also call SystemIdleTimerReset and SHIdleTimerReset every few seconds), please remember to set the value back to the original value.

Insomnia rules!

Monday, March 17, 2008

Windows Mobile Remote Control - Published

You can now get the latest version of the Windows Mobile Remote Controller application here. This code adds compression to the screen data transport so it becomes a bit faster. Enjoy!

Friday, March 07, 2008

My first hours with VS 2008

My first few hours of work with VS 2008 have been a pure joy. This new beast performs like a champ and has no apparent quarrels with Vista. Upgrading the Data Port Console solution to the 2008 format was a breeze and I was even rewarded with a C# compilation error that had gone unnoticed in VS 2005. The whole product feels much more robust and reliable under Vista and the visuals are also nicer. So far, it has been a great experience. Highly recommended!

Don't worry - if I have anything to gripe about, you will know it.

Wednesday, March 05, 2008

Installing VS 2008

I finally decided to install VS 2008 this morning. Why so late? I have been very busy and my customers use mainly VS 2005 so I had no urgency to install VS 2008. Now that it has been officially launched I will surely get more and more requests to migrate the products to .NET 3.5 so VS 2008 is a requirement.

Installation went as smothly as possible except for a mysterious shutdown at the end. I was not present, so I cannot tell you what happened but I suspect that the Vodafone 3G card is playing tricks on me. Again.

After installing, I looked at the C drive to check for free space and was appalled to see that it was below 50%. After installing Vista SP1, my C drive used space magically shrunk and has been growing very fast ever since. The culprit? System restore points! After clearing them I got back to post SP1 install conditions. Cool, my disk is back.

Tuesday, March 04, 2008

Raffael's Blog

Now, here is an ultra-cool blog: Mobile Development! Thank you Chris for the heads-up.

WMDC woes

It's almost a year now since I started using Vista Ultimate. The new OS came on the ASUS VX2 I bought last year and I have found that the overall experience has been very positive. There are a few minor snags like the apparent sluggishness in the couple of minutes after Windows boots and WMDC. This is my major gripe with Vista - I never know when one of my WM5 or WM6 devices will connect or not. One of the quick and dirty solutions I have found is to uninstall the device network adapter, disconnect the device and reconnect. To do this, go to the Control Panel, open the System applet and select the Device Manager link. Under the "Network adapters" tree node, locate the Windows Mobile device and uninstall it. Remove the device and connect it again. WMDC should recognize the device again.

There is an alternative that I have not tested yet and was pointed to me by Mark Arteaga on the PocketPC FAQ site. Anyway this should be an easier experience, especially for people like me who need to connect to everything, from Pocket PC 2003 devices to the latest WM6 devices throwing in a few bizzare Windows CE 5 GPS devices in between...