Sunday, December 06, 2009

An alternative way to create the menu bar

I don't like resources. I really don't. I can understand their usefulness for features such as string tables or embedded icons, but when it comes to the Windows Mobile menu bar definition, I just hate the whole thing. Take a good look at how the CrypSafe sample app's menu bar is defined:

ATL_IDW_MENU_BAR SHMENUBAR DISCARDABLE
BEGIN
IDR_MAINFRAME,
2,
I_IMAGENONE, ID_ACTION, TBSTATE_ENABLED, TBSTYLE_AUTOSIZE,
ID_ACTION, 0, NOMENU,
I_IMAGENONE, ID_MENU, TBSTATE_ENABLED, TBSTYLE_DROPDOWN TBSTYLE_AUTOSIZE,
ID_MENU, 0, 0,
END
Intuitive, right? Incidentally, this resource is defined in the .rc2 file and the ATL_IDW_MENU_BAR identifier is used as a default parameter of the CreateSimpleCEMenuBar method of the CFrameWindowImplBase class template. So what do you have to do in order to change the menu bar? Gasp!

There is a better way, fortunately. A way that you can encapsulate and that makes the whole process a bit more transparent.

You create a Windows Mobile menu bar by calling the SHCreateMenuBar API typically from your main window's WM_CREATE handler. As you can see the function takes a single parameter, a pointer to a SHMENUBARINFO structure where you define the menu bar. There are two ways to create a menu bar: you either specify a menu bar resource ID or you provide your own HMENU by specifying the SHCMBF_HMENU flag. This is in fact a much more palatable alternative because you can declaratively create your menu bar in a single location of your application's code. Using my beloved WTL, here's how the code would look like on the main frame's OnCreate handler:

if(m_mainMenu.CreateMenu())
{
m_mainMenu.AppendMenu(MF_BYCOMMAND MF_ENABLED MF_STRING,
ID_BACK, _T("Back"));
m_mainMenu.AppendMenu(MF_BYCOMMAND MF_ENABLED MF_STRING,
ID_MENU, _T("Menu"));

SHMENUBARINFO mbi = { 0 };
mbi.cbSize = sizeof(mbi);
mbi.hwndParent = m_hWnd;
mbi.dwFlags = SHCMBF_HMENU;
mbi.nToolBarId = (UINT)(HMENU)m_mainMenu;
mbi.hInstRes = ModuleHelper::GetResourceInstance();
mbi.nBmpId = 0;
mbi.cBmpImages = 0;
mbi.hwndMB = NULL;

BOOL bRet = ::SHCreateMenuBar(&mbi);
if(bRet != FALSE)
{
m_hWndCECommandBar = mbi.hwndMB;
SizeToMenuBar();
}
}
The m_mainMenu variable is a CMenu, of course. The advantage of this approach is that you create the main menu bar in a very explicit way and if you later want to change it you know where to find the code, and stop guessing what that crappy SHMENUBAR resource declaration means...

Tuesday, December 01, 2009

A simple header button

Now that we have a header for the application, what about adding some useful stuff to it, like buttons? The picture on the left shows the second version of the touch header in action with a "back" button that implements the same functionality as the menu bar's "Back" menu. This button should only be visible when there is somewhere to go back to, so we should be able to add it and remove it as we please.

For now, the header button is a very simple object containing up to 3 CImage objects (for the normal, depressed and disabled states). This is not a regular Windows button but instead a "sensitive area" of the header that just behaves like a button (just like what happens with regular toolbars).

The button itself is implemented in the CTouchToolbarItem class (see sample code below). It derives from CRefCount so you can use the CRefPtr smart pointer class template to manage it and forget about deleting... The class contains three CImage instances, one for each possible state (these will later be changed to smart pointers as well in order to allow for better reuse).

Buttons are set through the virtual SetupTouchHeader method in each of the child views. Instead of just setting the header text, you can now set up to two buttons (left with index zero and right with index one). The button activation messaging is very similar to a regular menu: the WM_COMMAND message is sent to the parent window (the main frame) with the command ID as the wParam parameter.

A final thought: the header belongs to the frame window and is set up by the child view when they are shown. Is this a good design? I'm wondering if these should "belong" to the child view instead and be replaced along with it, possibly with some fancy animation. What do you think?

Sample code: CrypSafe08.zip (406 KB)

Sunday, November 15, 2009

A basic header

In this post I'm adding a very simple header to the CrypSafe sample, as you can see from the picture. Graphically it is a simple gray gradient with some text printed with an embossed look. Despite of the sleek look, the implementation is quite simple, as you can see from reading the CTouchHeader class source code (see sample source below).

The header is implemented as a simple WTL header window. The WTL protocol for headers and footers is quite simple: the frame window sends an empty WM_SIZE message (both width and height are set to zero) to the header and footer signaling these to position themselves in the main frame client rectangle. The remaining space will be occupied by the child view window.

Implementing this protocol is quite simple: handle the WM_SIZE message and reposition the header at the top of the main frame:

void CTouchHeader::OnSize(UINT nType, CSize size)
{
if(size.cx == 0 && size.cy == 0)
{
CWindow wndParent(GetParent());
CRect rc;

wndParent.GetClientRect(&rc);
rc.bottom = rc.top + m_cyHeader;
MoveWindow(&rc);
}
}

The m_cyHeader variable contains the height in pixels of the header. Now, you just need to paint the header with your favorite gradient. Painting the text with the embossed look is also a simple task: you just need to paint it twice in different colors, offsetting the second painting by one or two pixels down. You get the best effect by painting first with a darker color.

As of this implementation, you don't get a very smart header control: it just paints the text it is given. However, we can make this text change according to some application context just like when you switch views. In the sample code below, the header is always present between view switches and the CChildViewManager merely asks each CChildView that is brought into view to update the header text through the virtual SetupTouchHeader function.

Now that this is in place, we can add more features to the header and make it more useful for the whole UI...

Sample code: CrypSafe07.zip (345 Kb)

Friday, November 06, 2009

HOWTO: Close Application on Minimize

This is a popular question lately: how do I close my application when the user clicks the "smart minimize button"? This button does exactly that - it minimizes your application and does not close it. Your main application window is minimized when it receives a WM_SIZE message with the SIZE_MINIMIZED constant in the wParam parameter. All you have to do is call PostMessage(WM_CLOSE) and you are done. Here's a sample WTL handler:


LRESULT CCloseOnMinFrame::OnSize(UINT /*uMsg*/,
WPARAM wParam,
LPARAM /*lParam*/,
BOOL& bHandled)
{
if(wParam == SIZE_MINIMIZED)
{
PostMessage(WM_CLOSE);
bHandled = TRUE;
return 0;
}
// Not handled here
bHandled = FALSE;
return 1;
}

Sunday, November 01, 2009

Article about Windows Mobile 6.5 Gestures

There is a new article on CodeProject about Windows Mobile 6.5 Gestures, and it's fully written in native code. Go there and have a look!

Monday, October 26, 2009

HOWTO: Implement a text ticker


Here's the answer to yet another question asked on the Windows Mobile Developer Center Forums: How to implement a text ticker. The request implied for a flicker-free implementation, so a memory bitmap is required. This bitmap is generated whenever the screen changes size (CTextTickerView::OnSize) or when the text itself changes (CTextTickerView::SetTickerText). To calculate the text size when printed with the given font, a call is made to CDC::GetTextExtent which returns both the height and the width of the text in pixels. The off-screen is then created using the screen width and the text height plus a few padding pixels (CTextTickerView::ResizeBitmap).

Scrolling of the ticker is achieved through a timer that shifts the ticker printing position every 100 ms. The ticker is painted by invalidating its own rectangle and the whole painting process is performed on CTextTickerView::OnPaint. Note how the ticker text gets painted a second time tailing the first instance in order to give a continuous feel. Also note how the x offset is incremented by the timer handler. Go and have a look at the code!

Sample code: TextTicker.zip (114 KB)

HOWTO: Show the Today or Home screen

I recently answered this question on an MSDN forum: how can I show the Today screen from my application? The answer is actually quite simple:

HWND hWndDesktop = GetDesktopWindow();
SetForegroundWindow((HWND)(((ULONG) hWndDesktop) | 0x01) );

The first line of code retrieves the "desktop" window handle (the Today screen) and in the second you set it to the foreground. Easy.

Monday, October 19, 2009

The Hold Gesture


After writing my last post, I started wondering if I could implement other useful gestures to control the touch list. So I started to wonder what kind of gestures would be needed for a real list-based application, like the CrypSafe prototype I have been working on. One of the issues that you will be confronted with is the requirement of, somehow, single out a single list item and then apply some sort of command to it. Think about deleting a list item: wouldn't it be nice that by clicking the item in a special way you would be able to do just so? There are a lot of other actions you might want to perform in a list item this way (edit, move up or down, you name it). Microsoft actually solved this issue some time ago with the "tap-and-hold" gesture, but gave it a very specific implementation with those circles rolling around the screen to denote it. Alas, I don't like it so I decided to reinvent the wheel and tweak the CTouchGesture in order to implement this gesture. It's actually quite simple: if you press an area of the screen and you don't move or release the finger for some time, a hold gesture is returned by the timer event.

To illustrate the use of this gesture, I implemented a very simple demo based on AppStart (yes, I was lazy) a so that it shows a "context toolbar" when you hold a given list item (see picture). In this case I added an "edit" and a "delete" button that you could use to change the list item. To make the whole thing a bit more fun, I added a small animation to the hold gesture where you can see the item expanding to reveal the "toolbar". Getting information about the pressed toolbar button would be a simple matter of overriding the HitTest function. Note that when the toolbar is displayed you can still flick and click because the item merely changed its size.

Here is the sample app: AppStart05.zip (268 KB)

Sunday, October 18, 2009

Ooops!

Please discard the AppStart03.zip file as the project contains a bug. The corrected version is here: AppStart04.zip (169 KB).

Minor touch improvements

In this blog post I'm returning to the touch window code to show you a couple of improvements that were needed.

First, there was the issue of stopping the list halfway through a scroll. If you start dragging the list and then stop, wait a little and then release the finger or stylus, the list would still scroll. This is not an intended (nor intuitive) behavior: the user scrolls the list up to a position and he / she wants it to stay put by stopping the finger / stylus for a fraction of a second and then releasing it.

The second issue happened when the list was "bouncing back" if you forced it to scroll down from the top (or scrolling up from the bottom). Under some occasions you could actually stop the list from scrolling back to its "rest" position leaving it in an awkward state.

To solve the first issue I changed the bulk of the code in the CTouchGesture class and turned it into a state machine with four inputs:
  1. Press - The user pressed the finger / stylus
  2. Move - The user is dragging the finger / stylus
  3. Release - The user released the finger / stylus
  4. Timer - Called every 200 ms in order to check transient conditions
Each input is implemented by a method with the same name and the novelty here is that each of the first three returns a value of GestureType (NoGesture, ClickGesture, FlickGesture). The return type is used by the CTouchWindow mouse event handlers to determine what to do (nothing, a click or a flick). When flicking through the list, the CTouchGesture returns the delta movement through the new GetDelta function.

By implementing the gesture recognition as a state machine we get a much better chance of determining and handling the harder to detect situations, such as:
  • Input noise such as when the user flicks and accidentally releases the screen for a very short period. This is now handled by the code and the state machine assumes that the previous flick is still happening.
  • Intermediate motion stop, such as when the user is flicking and stops halfway. This situation is detected by the timer event that essentially resets all displacement and time accumulators and assumes that the user wants to do nothing (this is not interpreted as a click, of course).
Finally, I changed the code a little bit so that it does not allow the list to be in an "unnatural" position. Whenever the list stops it is checked for such a situation (showing the canvas to the top or bottom when the list is larger than the window). When such a situation is detected, the list is automatically scrolled back into position.

To illustrate all of this, I turned back to the AppStart sample simply because it has a bigger list. Here it is for your viewing pleasure (or not...):

Sample code: AppStart03.zip (166 KB)

Sunday, October 11, 2009

It's not a bug...

... it's a feature! Really! I'm talking about my last post where I jumped to the conclusion that I had a bug in a particular line of code. In fact, that line of code is correct - the bug lies elsewhere. Let me explain.

As I stated before, there is no way (at least I never found a way to) use storage object with SQL Compact command parameters. To overcome this limitation the code must allocate the full size of the BLOB data on the binding buffer (which is not very efficient, but it's a viable solution). The problem with this is that the code has to know the size of the BLOB and adjust the binding buffer accordingly. If you use ADO .NET then you know how this issue is solved: the developer must create SqlCeParameters with the given maximum size of the parameter data. The whole purpose of this code is to avoid this situation and let the OLE DB library handle that chore for you.

Command parameter information is requested when you prepare a command and this is the reason why you see the dreaded 1024 constant in the code (the value is pretty arbitrary, by the way). This was the value I chose to represent the default value of the BLOB just to assume a value for it's length. The code then expects that you call SetParam for each parameter and explicitly set its size then. When the command is executed, the whole set of command parameters is looped through in order to get the size of the new binding buffer. If the new binding buffer is larger than the previous one it gets reallocated. And this is exactly where the bug was: the existing buffers were not being deleted and an obvious memory leaked was being created (the complaint reason from the reader who sent me the email message thet prompted me to look at this issue again).

To prove that the memory leak issue is gone in the new code, I set up a very simple demo project where three JPG images are inserted into a sample database table. The images are inserted using a SQL INSERT command and the code is arranged so that the images are processed in an increasing size order. This way you can actually see how the binding buffer increases.

Incidentally, the real bug was on the CCommand::BindParameters method where the m_pBuffer and m_pBindStatus arrays are allocated. These must be freed if non null before allocation.

Sample code: BigParams.zip (789 KB)

Note that the sample application expects both the sdf and jpg files on the \Storage Card\Temp directory. You can change this by editing the BigParamsFrame.cpp file.

Thursday, October 08, 2009

Command Parameter Handling

I recently got an email from an interested reader pointing out an error in the SQL command parameter handling OLE DB Client code. If you remember my previous ramblings on this issue, the OLE DB provider for SQL Compact is unable to handle BLOB SQL command parameter through storage objects. This means that you must provide some information about the BLOB before using the command, just like you have to do if you use the ADO .NET stack. Now, if you look at the CCommand::CreateParameter method you will see the error:

ULONG nParamSize = bIsLong ? 1024 : pParamInfo->ulParamSize;

Let me assure you that I was not taking any medication (or smoking funny stuff) when I wrote this line. This is a piece of code that I just did not return to so the error crept in and started to create lots of memory leaks. Solving this issue is not a simple matter of correcting this line to:

ULONG nParamSize = pParamInfo->ulParamSize;

Like I said, we must specify all the BLOB parameter sizes before we prepare the command and this means that CCommand::Prepare must also change. Instead of getting parameter information in the call to Prepare, the user will have the option of calling another method to get this information. In any case, there must be an option to provide custom command parameters. This is the topic of my next post.

Monday, September 28, 2009

Improvements

After reading Vincent's comment on my last post, I took a second look at the scrolling code and scuttled the InvalidateRect scrolling mechanism. The fact is that while on some older devices this did work in an acceptable fashion, it did not work that well on more recent models and you can actually see some "bumps" in the scrolling speed. The code now uses a timer (again) but instead of indirectly painting the window through the InvalidateRect / UpdateWindow calls, it now directly invokes the painting function. The result is a very smooth scroll on all devices I have tested the code with.

I also changed the way the ScrollLeft and ScrollRight view transitions work. Instead of painting the bitmap at full speed, I added a very small sleep period to each iteration so that each transition is performed in approximately 250 milliseconds. The first paint operation is timed and a per-iteration sleep period is calculated so that the whole process takes the quarter-second period to unfold. With this improvement, you will be able to see the view transition on all devices (especially the ones with a faster CPU and QVGA screen).

Finally, I decided to add a couple of new view transitions: Fade and Explode / Implode. The first transition uses the AlphaBlend API function to fade from the existing view to the new view (like in a Power Point presentation). I have to say that this is not a very compelling transition, but inspired me to write the second. The Explode / Implode view transition also tries to mimic one of the most famous iPhone view transitions (when you launch an application). The existing view is zoomed in while the new view fades in while also zooming in from half its original size. The Implode effect does the reverse. The result was a bit disappointing because AlphaBlend operation seems to be very greedy (you can replace it by a simple StretchBlt and compare the results). The GDI is not very good at this stuff, unfortunately...

Sample code: CrypSafe06.zip (323KB)

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: CrypSafe05.zip (349 KB)

Tuesday, September 15, 2009

Feedback

I just received a very nice email from one of you (you know who you are) reporting a bug in the OLE DB Client library, more specifically on the CDbValueRef class (file DbValue.cpp, line 758). The line must read:

*m_pLength = nStrLen * sizeof(wchar_t);

The original code did not multiply the string size with the Unicode character size, so you got a wrong byte count and a bug.

It's always very rewarding to receive emails with correction and suggestions from you (it means someone is reading this... - hehe). Thank you for all the feedback!

Sunday, September 13, 2009

Better touch

My professional life changed quite a bit recently and that's why I have not been posting as frequently as usual. I finally seem to have reached some balance and now's the time to resume my blog work.

One of the faults I found in the last version of the published code concerned finger sensitivity. This is a real issue in touch screens based on resistive technology (see a discussion about this topic on Marcus Perryman's blog). The bottom line is simple: resistive screens were made for a stylus, not for your finger. They are much more precise than capacitive screens (like the one found on the iPod Touch and iPhone), but require pressure. Capacitive screens are less precise but require only a very soft finger contact in order to operate. Resistive screens expect a very small pressure area (the tip of a stylus). An adult index finger uses up a very large area on the touch screen and the net result is noise and erratic motion messages.

You can see this in the last sample code I published: flick the list and then click it. It should stop the list but it doesn't (that's how it works on my HTC Touch Pro). What happens is that a single finger press is interpreted by the highly sensitive resistive screen as a sequence of one WM_LBUTTONDOWN message, a couple of WM_MOUSEMOVE messages and the final WM_LBUTTONUP. Inspecting the LPARAM parameter you will see that the POINT structure shows some fluctuations on the x and y coordinates. This means that a single finger press is actually equivalent to a small doodle drawn with your stylus. You will be lucky if the first and last POINT values are the same (they almost never are).

To mitigate this issue and provide better (more reliable) finger action feedback I made some adjustments to the code. The first thing I realized is that one of the sources of "position noise" was the first WM_MOUSEMOVE message. The offset between the WM_LBUTTONDOWN position and the first WM_MOUSEMOVE message seems to provide more variance than the offset to the second WM_MOUSEMOVE. To even things out a little bit I now discard the first offset and start calculating the gesture from the first WM_MOUSEMOVE message. Also, I brought back the concept of sensitivity to filter out smaller movements. Finally take a look at the code in CTouchGesture::Move method. Instead of calculating the move offset in a single if clause, I split the code into two, one for the vertical motion and the other for the horizontal motion.

The final result feels a bit better and more reliable on all the machines I have tested the code with, but the final word is yours.

Sample code: AppStart02.zip (164 KB)

Thursday, September 10, 2009

Shaken, not stirred...

The September 2009 issue of MSDN Magazine presents us with a very nice article on how to detect shaking with the HTC accelerometer. Note that the article is for managed developers, but that should be no problem for you...

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)

Wednesday, August 19, 2009

A simple application launcher

As I promised on my last post, here is the code for a very simple application launcher. It essentially lists all the applications registered in the "Programs" folder of your Windows Mobile device and launches them when the user clicks the corresponding list item.

I have to confess that I went into a bit of an ordeal in order to implement this very simple application. Quite simply because I tried to outsmart the Windows Mobile shell and to collect all the required information from the .lnk files. If you are on this same path, please read these words carefully: all has been done for you already, so don't try to reinvent the wheel.

My first pain was to get the icons from the shortcuts. You can almost do this by using ExtractIconEx, but this function will not work for some of the system DLLs, such as ceshell.dll. Why? I really don't know why, but the "Search" application icon (the magnifying glass) is impossible to get to by using this function. After asking around a bit, I was steered to the right direction by Christopher Fairbairn: use SHGetFileInfo. The only caveat is that you must use this function against the .lnk file itself, not against the target. If you do so, your icons will show up just right as you can see from the image.

The item name is taken from the shortcut file name - just remove the extension and the path. To make this easier I creted a very simple class named CFilePath that, for the time being, contains only one function: GetFileNameWithoutExtension (now where have I seen a similar function name?).

Finally, in order to execute the application, you just send the full .lnk file name to the ShellExecuteEx function and you are done with it. No need to mess around with the .lnk file format and all of its quirks.

For your viewing pleasure, here is the sample code: AppStart00.zip

Monday, August 17, 2009

Shell Shortcuts

Windows Mobile shell shortcuts have a very simple file format, something like (taken from my HTC Touch Pro):

22#:MSPIMG?pimgres.dll,-101

The number 22 is supposed to tell us how many characters there are in the string, but this example seems to be wrong. Incidentally, I have seen examples where this value is zero so apparently you can forget about it.

After the # character, you can read the associated command. In this case, you get a "shell macro" that needs to be expanded using a technique that I explained on my previous post. After the ? character there is a module name where the display icon can be found. This section is optional as well as the final section after the comma: the display icon identifier. The negative value means that this is an icon ID and you should be able to feed it directly to the ExtractIconEx API to get the icon handle.

One of the interesting things I've found while doing some research on these files is that you can add a comment section to the beginning of the file, something like:

;Pictures & Videos
22#:MSPIMG?pimgres.dll,-101


Interesting, huh?

I'm putting together a very simple application launcher that uses this knowledge to read from the Program Files directory all the existing shell shortcuts and displays them on a touch list with the right icon and name. This will be published on my next post, so stay tuned.

Wednesday, August 12, 2009

Default Windows Mobile Applications

How do you start the default Windows Mobile applications like Calendar, Contacts or Messaging from your application? I recently came across this question in the Visual Studio Smart Device Development - Native C++ Project (quite a long name, huh?) MSDN forum. The answer is quite simple and relies on a registry entry that has been around at least since Windows Mobile 2003:

HKEY_LOCAL_MACHINE\Software\Microsoft\Shell\Rai

Here you find a list of varying size containing all the default applications in your machine (both a human-readable name and the required command line). For instance, on my HTC Touch Pro the calendar is stored in the following entry:

HKEY_LOCAL_MACHINE\Software\Microsoft\Shell\Rai\:MSCALENDAR

The application's human-readable name is stored in the "0" (zero) key while the command line is stored in the "1" key. If you look up this in your device's registry you will probably find something like:

:MSPOUTLOOK calendar

Note that this requires further expansion by looking up the following entry:

HKEY_LOCAL_MACHINE\Software\Microsoft\Shell\Rai\:MSPOUTLOOK

The value of the "1" key contains "poutlook.exe" so the final command line to start the Calendar application must be "poutlook.exe calendar". Easy huh?

Monday, August 10, 2009

Item Activation

I'm still not sure how this is going to end, but right now items can be focused, selected and activated. An item gets the focus when you use the arrow keys to navigate the list and that is meant to mean the "current" item in the list. When you select an item it gets added to a selection list (in case you need to use multiple-selection lists). Note that focus does not mean selection nor selection means focus. Finally, an activated item is the one you just "pressed" or clicked.

The code I'm publishing today shows how to set the focus on a particular item (just added a highlighter to the DrawItem method) by navigating the list with the arrow keys and how it can be activated by directly clicking it or by pressing the enter key on the focused item.

I had to make some changes to the CTouchWindow class template in order to make sure that scrolling (or flicking through) the list does not get confused with a click. If you hook the application with Remote Spy you will see an interesting pattern of messages when clicking an item: WM_LBUTTONDOWN, WM_MOUSEMOVE (may occur more than once) and WM_LBUTTONUP. What's interesting is that the "mouse move" message always shows up even if it reports the same screen position as the "button down" message. Is this a bug, Microsoft? Anyway, the code already handles null movements so...

When an item is selected, the CCrypSafeView::OnItemChangedState method is called by the base class and to handle the item activation you must handle the TLN_ITEMACTIVATED code. Just take a look at the sample code to see how it is done. Note that you test nmtl.dwState for nonzero meaning activation - it is zero when the item is "deactivated".

Sample code: CrypSafe04.zip (325 KB - now includes the OleDbClient lib)

Monday, August 03, 2009

Compiling CrypSafe

Back from the sunny Algarve and ready for more work. I have to confess that during these last two weeks I barely touched my laptop, but I surely needed the rest.

Compiling the CrypSafe prototype has proven to be a bit of a challenge for some of the readers and I have received some complaints about this very subject. Here is a list of what you need to do, both with VS 2005 and VS 2008 to get the sample to compile. Please note that I'm distributing the VS 2008 solution files only but you should be able to recreate the project for VS 2005 without major issues.

Here's what you must do to compile the sample:
  1. Download WTL 8.0 or 8.1. You can get the latest version of WTL from its sourceforge page.
  2. Unzip the WTL distribution file to a directory of your choice.
  3. Under the installation directory, you will find some directories named AppWiz, AppWizCE and AppWizMobile. Navigate to each of these in turn and run the setup90.js (for Visual Studio 2008) and/or setup80.js (for Visual Studio 2005) scripts in order to install the Visual Studio application wizards. Please note that under Vista (and probably also under Windows 7) you must open a command prompt with elevated privileges because these scripts write files to the Visual Studio install directories.
  4. Now you have to open Visual Studio and let it know where to find the WTL include files. To do this, open Visual Studio and go to the Tools / Options menu and select "Projects and Solutions" item in the tree. Select the "VC++ Directories" under that item and then select the "Include files" option of the "Show directories for:" combo box. Now, for each platform listed on the left combo box, you must enter your WTL include directory in the list below.
  5. Now you can open the CrypSafe solution in Visual Studio and try to compile it. If it still fails, please make sure you correct each project's "Additional Include Directories" property under the project's Configuration Properties / C++ / General option.
If you still find errors while compiling, please let me know through a comment to this post.

Tuesday, July 21, 2009

And now for something completely different...

I just spotted a native code pearl on Todo PocketPC: Nitrogen 1.1 a native code media player for Windows Mobile 5. The interesting thing about this application is that it comes with full source code (licensed under the GNU GPL v3). The media player looks very good and I will be giving it a spin (I really don't like any of the media players bundled with my HTC Touch Pro).

Saturday, July 11, 2009

Kinematics

How do you make the touch list behave like a real physical object? What's the secret behind making the list bounce smoothly back to its original position? How do you decelerate it when you quickly flick through it like if it had some sort of "friction"? In short: how do you make it work like an iPhone list? The answer is simple: kinematics, the study of motion.

In this post I'm adding some kinematic effects to the list to make it work like if it had both weight and some "springs" to attach it to the extremes of the window. These "springs" will make the list bounce back when the list is either showing its first or last element and you force it to scroll down or up (respectively). Also, when scrolling through very large lists, you want them to slow down in a realistic fashion, like a real object would.

There are a lot of changes to the base CTouchWindow class in order to include these kinematic additions. Interestingly, some parts of the code actually became simpler. This base class is used to implement the touch list that only performs vertical scrolling, but it must also accommodate for a possible horizontal scrolling. To make the kinematics implementation easier, I created a helper class named CTouchMotion that is used to calculate the list position as a function of time. You initialize each instance (vertical and horizontal) with the desired acceleration (in pixels per squared second), initial speed (in pixels per second), the initial and final positions of the motion (the final position is redundant, me thinks) and the total motion time. The x and y positions of the motion (just y for the touch list) are calculated by the GetPosition function that takes the time offset (since the beginning of the motion) as milliseconds. The function just computes the classical x = 0.5 * a * t * t + vi * t + xi equation, where x is the position for time t, a is the acceleration, vi is the initial speed and xi is the initial position. Notice that the function must transform the input in milliseconds to seconds in order to get the appropriate result. This is a concern because I must perform all calculations using integers to get the best performance possible. If you look at the implementation of the GetPosition function you will see that I calculate the 0.5 * a * t term first and convert it to a pixels per second speed. Next I add the initial speed, multiply the result by t and then convert the result to pixels by dividing by 1000. Finally, xi is added and we get the proper result. Also notice how each step is accurately rounded to make sure nothing is lost during conversions.

While I was debugging this code I found a very interesting bug. Originally, the function was using the time offset as a DWORD (an unsigned value). Occasionally the list would simply disappear while scrolling. The bug was due to the conversions performed between signed and unsigned integers and sometimes they behaved differently from what I expected, and would throw the list origin to very large negative numbers. The problem was solved by casting the time offset to a signed integer.

You can also see that the function uses a time limit that works as a "break" if you accidentally call it with a time offset larger than the one you specified. Why is this? Simple: the equation is a simple parabola that computes a trajectory until the speed (the first derivative) is zero. This is when the list stops. If you don't limit the motion, you would actually see the list bouncing back with a positive acceleration like when you throw a ball up, and it comes back down. You only want the upward movement - the one where the speed decreases until zero.

Another big change happened in the way the motion timer is calculated. The previous version used the speed of the last WM_MOUSEMOVE (displacement and time). This concept was discarded and I assumed that the movements would have a set of fixed behaviors:
  • Bounce-back movements would last 500 milliseconds.
  • List deceleration would take 2 seconds.
You can see these calculations in the CTouchWindow::SetupMotion function. This is called when the list is about to move (on the WM_LBUTTONUP handler) and during the timer (OnTimer) function in order to test for boundary conditions. There is something that's still amiss here: when you transition from a scroll to a bounce-back, the initial speed is not being considered so you see a bit of a harsh transition. I will correct this later.

Finally, and because you can now have an empty space drawn before the list (and also after, but this was already in the previous implementation), I added a fourth color to the list: the canvas color. This is what lies "beneath" the list and helps to convey the notion that the list exists above another surface (thanks for the suggestion, Anatoly).

The code is not fully cleaned up yet and you will see some more changes to this kinematic code. Meanwhile, here is the project for your perusal:

Sample code: CrypSafe03.zip (99 KB)

Thursday, July 09, 2009

Windows Mobile 6.5 Gestures documented

The documentation for Windows Mobile 6.5 Gestures is now online here.

Bouncing the list

While I was preparing the code for the next post, I realized that something really important is missing from the touch list: it does not "bounce". Use the sample I published in the last post and try to move the list. It will not budge. Similar implementations allow you to move the list out of it's stable position (minimal energy position?) and it will move back to where it was. It gives you a nice sense that you are dealing with a physical inertial entity.

The sample code I'm publishing today just allows for this and simply resets the list to it's stable position without any animation or kinematic feedback. Right now I'm going through some high-school kinematic equations in order to implement some properly accelerated animations to the list. Meanwhile, check the source code here: CrypSafe02.zip. As you can see, the list painting now allows for empty space both before and after the list so that when you force it down it will not leave garbage at the top.

Monday, June 29, 2009

A better look

Here's a better look for the CrypSafe main view. As you can see I'm using a new font for the item text, added a separation line between the items and painted the background with a different brush for odd-numbered items. The changes to the code are not very dramatic, so let's take a look at them.

The first change is the new font. To use a new font I generally declare a CFont object on the view class like this:

private:
CFont m_largeFont;

This way I know that the font will exist throughout the life cycle of the containing view. Creating the font itself is always a bit of a pain, but i prefer to use the following method because it does give me full control over what is going on. The following code snippet was taken from the view constructor in CCrypSafeView.cpp:

LOGFONT lf;
int nLogPixelsY = DRA::LogPixelsY();

lf.lfHeight = DRA::HIDPIMulDiv(-12, nLogPixelsY, 72);
lf.lfWidth = 0;
lf.lfEscapement = 0;
lf.lfOrientation = 0;
lf.lfWeight = FW_NORMAL;
lf.lfItalic = FALSE;
lf.lfUnderline = FALSE;
lf.lfStrikeOut = 0;
lf.lfCharSet = ANSI_CHARSET;
lf.lfOutPrecision = OUT_DEFAULT_PRECIS;
lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
lf.lfQuality = CLEARTYPE_QUALITY;
lf.lfPitchAndFamily = DEFAULT_PITCH | FF_SWISS;
_tcscpy(lf.lfFaceName, TEXT("Tahoma"));
m_largeFont.CreateFontIndirect(&lf);

The code at the top is the most important one because it makes sure that we create the font with the right size in points, independently of the resolution of your device's screen.

Now that the new font is ready to use, let's see how to use it on the DrawItem method. First, you need to declare an HFONT variable:

HFONT hFont;

This is used to store the DC's currently selected font while we use our custom font. Setting the new font is easy:

hFont = dc.SelectFont(m_largeFont);

When we are done with the new font, we must set the old DC font back:

dc.SelectFont(hFont);

To paint the text with a left border, I copied the item CRect to a new instance:

CRect rcText(rcItem);

Before painting, the left value is adjusted:

rcText.left += DRA::SCALEX(4);

Note that this will correctly scale in higher DPI screens. As you can see from the included image, the even-numbered items have a white background while the odd-numbered ones have a very light gray background. As I explained in the previous post, the client code in DrawItem is supposed to paint the background, and doing it is extremely easy:

COLORREF rgb(m_rgbBack);
if(iItem % 2) rgb = RGB(0xf0, 0xf0, 0xf0);
brush.CreateSolidBrush(rgb);
dc.FillRect(&rcItem, brush);

The m_rgbBack variable is declared by CTouchListBase and contains the default background color (this color is used to fill in the unpainted space at the bottom of the list). If the item has an odd number, I replace the default white with a light gray and use this RGB value to create a brush. Painting the item's background is a simple issue of calling FillRect with the supplied item CRect (rcItem).

Now we can paint the item's text making sure that it is painted with a transparent background mode:

int nBkMode = dc.SetBkMode(TRANSPARENT);
dc.DrawText(pItem->GetText(), -1, &rcText, DT_LEFT | DT_VCENTER);
dc.SetBkMode(nBkMode);

Note that the text is painted using the rcText rectangle, not the item's. This way we get the left margin effect. Finally we can print the bottom separation line:

CPen pen;
HPEN hPen;
pen.CreatePen(PS_SOLID, 1, m_rgbLine);
hPen = dc.SelectPen(pen);
dc.MoveTo(0, rcItem.bottom - 1);
dc.LineTo(rcItem.right, rcItem.bottom - 1);
dc.SelectPen(hPen);

The m_rgbLine contains the default color for the separation line (gray). As you can see, this is not rocket sience. Next, I will explore how to add a navigation cursor and key handling.

Sample code: CrypSafe01.zip (96 KB)

Friday, June 26, 2009

The CrypSafe prototype

Today I present the very first iteration of the mobile password safe application. First I decided to name it "CrypSafe". Second, I also decided to post the code in very small increments so that the whole process of using the WM framework becomes clearer (and also to allow me to add changes as I see fit). Third, I'm starting off with a prototype.

The application architecture is actually very simple (as usual, I'm using WTL 8.0):
  • A main frame window that contains the content views and any decorations
  • A category view that shows the information categories in the safe
  • A detail view showing the individual items in each category
  • An item editing dialog
More items will be added if need arises, but for now I would say that this is enough. When you create a new project using the WTL Mobile Application Wizard, you get a lot of code created for you. In fact, after creating the project you can compile and run (and it will run - just make sure that the WTL include files are reachable for both the C++ and resource compilers). I usually create an SDI application with a child view because it's the most flexible arrangement. You can skip the child view and pain directly on the frame's client area, but this will make it harder for you to use multiple views. Incidentally, the code that flips views does paint on the frame's client area, but that's another story.

After creating your initial project, our first stop is to change the view window (see the source code):

class CCrypSafeView : public CTouchList<CCrypSafeView>, public CChildView<CCrypSafeView>

This means that our view will implement both a "touch list" and will also behave like a switchable child view. Next we need to remove the standard painting protocol and replace it with the touch list's:

virtual void DrawItem(HDC hDC, int iItem, CRect &rcItem);

Yes, we only need this because the list is painted item by item. Remove the OnPaint handler because it is not needed (it's implemented by the base class). I also added a default constructor where I placed the initial list of categories for the prototype:


CCrypSafeView::CCrypSafeView()
{
AddItem(new CTouchListItem(L"Credit Cards"));
AddItem(new CTouchListItem(L"Debit Cards"));
AddItem(new CTouchListItem(L"Mail Accounts"));
AddItem(new CTouchListItem(L"SIM Cards"));
AddItem(new CTouchListItem(L"User Accounts"));
AddItem(new CTouchListItem(L"Web Sites"));
}

Note that these items are not explicitly delete anywhere in the code because their pointers are reference counted (internally). Finally, let's see how to paint the items:


void CCrypSafeView::DrawItem(HDC hDC, int iItem, CRect &rcItem)
{
CDCHandle dc(hDC);
PTouchListItem pItem = GetItem(iItem);

dc.DrawText(pItem-&gtGetText(), -1, &rcItem, DT_LEFT);
}

Note that the PTouchListItem type is a typedef that denotes the reference-counted version of a pointer to a CTouchListItem object.

As you can see from the image, the result is less than satisfactory. The whole list is painted on an off-screen bitmap that is initialized to solid black (hence the black areas of the screen). The bottom of the list is automatically filled with the background color, but not the individual items - you must fill in the background for yourself. We also need to make the item font larger (possibly bold and with ClearType rendering for a better reading experience). As you can see each row has a height of 40 pixels (80 on high DPI machines) in order to accommodate a 32x32 (64x64 on high DPI machines) image. The text will have to be correctly formatted in order to better fill each row.

For the time being, you can take a peek at the first version of the code here.

P.S.: Anatoly, I have not included all of your changes yet.

Wednesday, June 24, 2009

Back to native

After a few days struggling with the BlackBerry JDK, JDE and Eclipse, it's time to get back to predictability and safe ground. Boy, have I missed Visual Studio!

Now that I have some readers actively using, criticizing and suggesting improvements to the Windows Mobile native framework (thank you so much, Anatoly!), I think now is the time to start exercising the code with a real application. Contrary to my early plans, I will start with something that I really need on a day-to-day basis: a mobile password safe. Nowadays I struggle to remember all the mobile phone PINs and PUKs, debit and credit card PINs, online service passwords, just to name a few. I know there are some excellent applications out there ready to be purchased, but what's the fun in that? My idea is very simple: use an encrypted SQL Compact database to store all the sensitive data. The user will be able to add, modify and delete both data and structure (each information category will be stored in a different table). The user interface must be very simple:
  • A main list containing the user's information categories (credit cards, phone PINs...);
  • A secondary list containing the category details;
  • A dialog for editing the details
So, after committing to this, let me roll my sleeves and head back to VS. On the next post I will start publishing the first version of the code.

Monday, June 15, 2009

A simple GPS viewer

Here's a simple GPS viewer application. I wrote it to help me in testing the transition to reference counted pointers in my budding Windows Mobile native (WTL-based) framework. In the process I have learned a few things about reference counted pointers, especially when NOT to use them.

One of the changes I made to the way the CPropertyListView class is used is that it contains pointers to items created on the heap and not on the stack. This means that you now have to create items like this:

m_pGpsFix = new CPropertyString(L"Fix", L"Unknown");

Note that the m_pGpsFix variable is actually a "smart pointer" and you don't have to worry about deleting it in the destructor. Nor does the list, in fact... When each item's reference count reaches zero, the last smart pointer that references the object will delete it (and that's why you cannot have stack allocated items). This is when you should use smart pointers, so when should you use simple C++ pointers? I found out the hard way when adding these items to the list. My original (and right) prototype was:

void CTouchListBase::AddItem(CTouchListItem* pItem)

When I replaced the C++ pointer with a smart one, I immediately lost one of the best features these things have: the ability of a base class pointer to refer to a derived class object. Understanding that I don't know enough about C++ class templates to make this work (not even sure if that's possible - will have to look at Jossutti's book), I decided to fall back to straight C++ pointers. This poses no problem because the method internally will use the smart pointer class constructor to build a new instance using the raw pointer and add it to the underlying array, so the reference counting is respected.

The sample application just starts the GPSID and displays some data from the GPS on a dialog. As you can see from the ZIP file, there are two additional library projects that make up the framework. Note that these are subject to change and do have bugs!

Sample code: GpsView.zip (93 KB)

Thursday, June 11, 2009

unresolved external symbol CLSID_ImagingFactory

Just started out a new sample project that illustrates how to use the WM libraries I'm writing, and got the following link errors:

1>wmfw.lib(Image.obj) : error LNK2001: unresolved external symbol CLSID_ImagingFactory
1>wmfw.lib(Image.obj) : error LNK2001: unresolved external symbol IID_IImagingFactory


This means that the linker cannot find the symbols CLSID_ImagingFactory and
IID_IImagingFactory, required to use the imaging library on Windows Mobile. If you look at the documentation, you will see that a link to the imaging.lib file is required but it will not work (at least it does not work for me).

The solution I found is to force the inclusion of these symbols using a dummy file that I usually name guids.cpp. Here's the content:

#include "stdafx.h"
#include <initguid.h>
#include <imgguids.h>


The initguid.h include redefines the DEFINE_GUID macro that is used by imgguids.h so that it declares a GUID along with its value instead of making an external reference to the same symbol.

Compile and link and the error goes away.

More native memory in WM 6.x

Here's a very interesting blog post from The Windows Mobile RSS: More Memory For ALL in WM 6.x. As you can see, folks at Microsoft still care about us, native mobile developers.

Wednesday, June 03, 2009

VS 2010 and Smart Device Development

This updated link explains it all: Smart Device development is not supported by Visual Studio 2010 Beta 1, but will (somehow) be supported by the final release. Quoting:

"Microsoft is committed to making Visual Studio a great development tool for the mobile device developer, and will deliver mobile device tools for Visual Studio 2010, but cannot share details now. For existing Visual Studio 2008 mobile developers, Microsoft will release a new Windows Mobile 6.5 emulator in the upcoming months that works with the Windows Mobile 6 SDK."

Now, back to work.

Saturday, May 30, 2009

Is Native Code Hard?

If you read this blog then probably your answer is, like mine, no. So what's the difference between native and managed that makes people avoid native code like the plague? What makes people not want to come back? In my opinion there are a few reasons, especially for Windows Mobile native code:
  • Lack of tools - just try to write a C# application using notepad and the command line compiler and you will see how much tools make a managed developer life easy. There is no comparable level of tool support for native code developers, and this may be linked to the next point.
  • Lack of comprehensive and cohesive libraries and frameworks - the Win32 API is way too low-level for most uses. It's very nice to be able to use it directly without paying the P/Invoke price, but this comes at a cost of having to write dozens of lines of code to achieve a very simple outcome. The OLE DB and MAPI COM interfaces are a perfect example of this - way too complex to use as they are offered. Just compare the "stock" OLE DB samples with the OLE DB Client library I published here...
  • Memory management - this is a minor issue for small applications but when the scale starts to grow it becomes a headache. When are you supposed to delete that object? Is it safe to do it now? Are there other objects referring to it?
I have recently been confronted with the memory management issue in a relatively complex application when I found myself wanting to have the memory management of a particular set of objects to be done automatically. These objects are referred to by an arbitrary number of other objects and determining when their life cycle ended was becoming more and more difficult, especially because they were being referred to by different threads.

There are two basic approaches to automatic memory management that have been used for quite a long time:
  • Reference counting - The iPhone uses a reference counting mechanism to determine when a given object can be removed from memory. The price you pay for this type of memory management is that you have to remember to increment and decrement the memory reference counts. Failing to do this will result in memory leaks. The iPhone uses an optional "autorelease pool" object that kind of protects you from this.
  • Garbage collection - The Java and .NET platforms both use garbage collection to reclaim the memory of objects that are no longer active. The price you pay for this is that the GC has a mind of its own and stops your code in order to clean up the mess. On mobile devices, if you don't manage your memory by reusing objects and by avoiding excessive allocations, the GC will kill your application performance.
One of the interesting advantages of C++ is that it implements deteministic object destruction: when your statically allocated object goes out of scope, the destructor is called. This behavior allows us to implement classes like CWaitCursor that displays the wait cursor on the constructor and hide it or replace it on the destructor. You just have to create a variable of that type and the wait cursor will be shown while the object is alive.

If we couple this with a simple reference counting mechanism, we can actually get all the benefits of a reference-counted memory management scheme without the pain that is imposed on us by the iPhone: we don't have to remember when to increment and decrement the references. How? The dead-old solution is to use reference counted smart pointers to manage our objects' life cycles.

After performing a search for reference-counted smart pointers, and realizing that my needs were quite simple, I decided to roll my own. The first thing we need is a place where to store the reference counts. Some implementations use a proxy object to do this but, for simplicity sake, I decided to put the reference count right on the object through inheritance. This has the disadvantage of having to make all the reference-counted objects inherit from one class, but it's a simple class that will only add four bytes to the object size:


class CRefCount
{
private:
LONG m_nRefCount;

public:
CRefCount(void) : m_nRefCount(0) { };

void RefIncrement()
{
InterlockedIncrement(&m_nRefCount);
}

bool RefDecrement()
{
return InterlockedDecrement(&m_nRefCount) <= 0; } };

Note that I'm using the InterlockedIncrement and InterlockedDecrement to manage the reference count because these methods can be used from different threads. Also, note that the reference count starts at zero (and not at one like on the iPhone) because I want to count how many smart pointers are referring to this object. Let's see how the smart pointer class is defined:


template <class T>
class CRefPtr
{
private:
T *p;

public:
CRefPtr() : p(NULL) { }
CRefPtr(T *pT) : p(pT)
{
if(p)
p->RefIncrement();
}

CRefPtr(const CRefPtr& ptr) : p(ptr.p)
{
if(p)
p->RefIncrement();
}

~CRefPtr() throw()
{
Release();
}

void Release()
{
T* pTemp = p;

if(pTemp)
{
p = NULL;
if(pTemp->RefDecrement())
delete pTemp;
}
}

void Attach(T* p1)
{
Release();
p = p1;
}

operator T*() const throw()
{
return p;
}

T& operator*() const
{
ATLENSURE(p!=NULL);
return *p;
}

bool operator!() const throw()
{
return (p == NULL);
}

T* operator=(const CRefPtr& rhs)
{
if(this != &rhs)
{
Release();
p = rhs.p;
if(p)
p->RefIncrement();
}
return *this;
}

T* operator=(T* pT)
{
if(p != pT)
{
Release();
p = pT;
if(p)
p->RefIncrement();
}
return *this;
}

T* operator->() const
{
ATLASSERT(p != NULL);
return p;
}
};

As you can see each smart pointer takes up the same amount of memory as a regular pointer, so you can safely pass and return it by value from your own methods and functions. This is a very bare-bones implementation and may lack some more sophisticated features, but so far has worked quite well for me. You use it like a CComPtr (I confess that I did look it up when writing this code).

Friday, May 29, 2009

Gynoid

There is a new article on Code Project by Vincent Richomme where he presents the Gynoid framework for cross-platform mobile development. In the included sample, Vincent was so kind as to use the "touch list" WTL control that I have published in this blog. Thank you Vincent!

P.S.: I'm not a guru, I just love this stuff and write about it... ;-)

Saturday, May 23, 2009

Integer Trigonometry

Adding a live GPS feed to a map means, besides near-second updates, the requirement to display a location marker with the current heading. The Window Mobile GPSID provides the current heading in the GPS_POSITION structure as the fHeading value, representing the angle in degrees between the current heading and true North (zero degrees). So how do you go about drawing a compass like the one in the picture?

The drawing is composed of two simple triangles: red for North and blue for South. The drawing is performed by using the Polygon GDI function that takes a list of points describing a closed shape and draws it using the selected pen and brush. Nothing new here. The interesting challenge is how to draw the image in the different angles without a big performance hit (translated: how to implement fast trigonometry functions).

Current Windows Mobile devices are not guaranteed to have an FPU unit that will do all the floating point math for you. If you use the Compact Framework, you are sure that all floating point calculations are performed in a software emulated FPU, so they are much slower than what they could be when performed with a real FPU. When using native code, you have the advantage of using the FPU if one is available, but the code will fall back to the emulator if the FPU is missing.

My approach here was to skip any floating point processing at all. There are two reasons for this:
  1. Drawing a map on a Windos Mobile device is a resource-intensive operation, especially if you are updating it frequently and you want to spend the least amount of time drawing any decorations on top of it. So a fast implementation is required.
  2. This object requires very simple transformations (rotation plus offset) and the required accuracy of the final result is not very high. In fact, it is somewhat low considering the relatively small resolution of WM device screens. The bottom line is that you can live with a bit of error when drawing your compass (this is not rocket science).
So how do you calculate a rotation transformation? Please refer to a good book on the subject (I'm using this lovely book as a reference: Essential Mathematics for Games and Interactive Applications) and you will see that it all boils down to these two simple equations (transforms a point through a counter-clockwise rotation around the origin):
  • x' = x cos(a) - y sin(a)
  • y' = x sin(a) + y cos(a)
Where (x, y) are the original point coordinates, (x', y') are the transformed point coordinates and a is the rotation angle. The first thing you need to do is to "draw" your compass by defining the vertexes assuming that the center of your coordinate system is in the center of the image. In this case, I used the following points:
  • (0, 32) - North
  • (-7, 0) - West
  • (0, -32) - South
  • (8, 0) - East
The reason why I'm not using (7, 0) for East is simple: the final image looks much better on a discrete screen if it has an odd width. If you look at the sample project you will see that I split the compass into two distinct triangles in order to draw them with different pens and brushes.

Now the interesting bit is how I implemented the sin and cos functions: through a table lookup. Assuming that you can live with an error of one degree when specifying the angle, all you need is a precomputed list of the sin values between 0 and 90 degrees. Using basic trigonometry you can derive all sin and cos values from the first quadrant sin values. If you look at the code, you will see that the precomputed sin values are scaled by 10,000. When calculating x sin(a) the code uses the precomputed value and divides the result by 10,000 to get the approximate result (you can use a higher scale for a higher resolution calculation, but that might not be required for this purpose). You can see the implementation of these functions in the FastTrig.h and FastTrig.cpp files in the sample.

Before we can draw our compass on the screen, we must take care of two important issues:
  1. The original compass coordinates are centered around the origin, so we must transform them further to make it fully visible on the screen;
  2. The screen coordinates of a Windows Mobile device are a bit different: while x grows to the right as we expect, y grows down and not up.
This means that beside the rotation we must apply a translation and a "mirror" transformation. In the sample code, I translate by adding the x and y offsets corresponding to the middle of the screen and then the y coordinate is flipped by subtracting it from the window height. Enough of this talk, here's the sample project: GpsCompass.zip.

On a future post I will update this code so that it uses a double buffer painting method to eliminate flickering and connect the compass direction to the GPS heading.

Wednesday, May 20, 2009

One GPS, multiple windows

After publishing the simple GPS class on my last post, I found myself in a situation where I needed the same CGps object to notify more than one window whenever a new GPS event arrived. My scenario is quite simple: while feeding a window with a map, I also need the same CGps object to notify another window where I display some GPS information like the current latitude and longitude coordinates.

The original code supports notifications for one window only so, to solve this issue I could create another instance of the CGps class and have it notify the new window. Although this would work, it would also create an extra thread in the appliction (if you look at the CGps implementation, you will see that it uses a thread to wait on the GPSID events) which is unneeded and consumes more system resources.

I ended up by devising a simpler solution: add multiple window handle - message pairs to the notification mechanism. To implement this I created a new class - CWindowNotifier - that is nothing more than a simple array of HWND and UINT pairs. When the consuming object wants to send a notification to a set of windows, it just calls the appropriate method (Post or Send). If one of the notification windows was closed, the code automatically removes it from the notification list. Using this class is very simple: just call the AddWindow method with the HWND you want to notify and a UINT value containing the message code for the notification. When you want to send a notification use either the Post or Send methods. The Post method uses the PostMessage API so it returns immediately and is the one I recommend for most uses. The Send method uses the SendMessage API, so it works synchronously and waits before all notification windows have responded. You can get the class source code here.

The updated CGps source code is here. Note that this new version uses a new wrapper for the CRITICAL_SECTION objects which you can find here. Enjoy.

Friday, May 15, 2009

A simple GPS reader class

I've been recently involved in a number of projects that require information from the Window Mobile GPS Intermediate Driver. The usage pattern is quite similar in all cases as the application needs to update a window based on the GPS information stream. There are two possible approaches for this: you can use a window timer and poll the GPSID or you can create a worker thread that waits on the GPS stream to wake up and notify the window through a PostMessage call.

The CGps class (download here) is very simple to use. On your window class just declare a member variable of type CGps, like this:

CGps m_gps;

To start receiving GPS data, just call

m_gps.Start(m_hWnd, WM_GPS);

where WM_GPS is a user-defined window message. You can use something like:

#define WM_GPS (WM_USER + 0x654)

Now you need to handle the WM_GPS message in your code (this will be somewhat different if you are using straight API, MFC or WTL). Note that when handling the message, both wParam and lParam are zero - the message works as a simple notification mechanism to let the window class or procedure know that the GPS updated its data. You read the GPS information quite simply:

GPS_POSITION gpsPos;

m_gps.GetPosition(&gpsPos);

To stop the GPS events you can either call Stop() or let the destructor do that for you when the object goes out of scope and is destroyed.

When implementing this class, I had to work around the now-known GPSID API bug. On some devices, the GPSGetPosition API uses a different size for the GPS_POSITION structure (something that has been explained by John Spaith here). The workaround is simple: just feed the thing with a fake buffer and cast it back to a GPS_POSITION. If you look at the implementation, you will see all this trickery at work. But don't worry - it does work!

Tuesday, May 12, 2009

Windows Mobile Marketplace now open

The Windows Mobile Marketplace is now open (but only for US developers?)

Thursday, May 07, 2009

AllKeys, documented

Here is the key capturing API we've all been waiting for since the demise of GAPI: AllKeys.

Wednesday, May 06, 2009

WTL frames, toolbars and headers

The WTL CFrameWindowImpl class template uses a very simple approach to manage the client, toolbar and status bar windows. The preset arrangement for these windows is very simple:
  • a client view that occupies most of the frame's client area;
  • an optional toolbar window that is placed at the top of the frame's client area and above the client view;
  • an optional status bar placed at the bottom of the frame's client area and below the client view.
The frame window already knows how to handle the three child windows. Each frame contains three member variables for them:
  • m_hWndClient for the client view;
  • m_hWndToolBar for the top toolbar window and
  • m_hWndStatusBar for bottom status bar
To make the three child windows work together you must create them and assign them to the appropriate member variable. The top and bottom windows must implement a special handling of the WM_SIZE message because this is how the frame tells each window to place itself in its client area and thus calculate the remaining area for the client view. This special message is nothing but a WM_SIZE message with both parameters (wParam and lParam) set to zero. Here's a sample from my production code:



void OnSize(UINT nType, CSize size)
{
if(size.cx == 0 && size.cy == 0)
{
CWindow wndParent(GetParent());
CRect rc;

wndParent.GetClientRect(&rc);
rc.top = rc.bottom - m_cyToolbar;
MoveWindow(&rc);
}
}

Easy, huh?