Showing posts with label WTL. Show all posts
Showing posts with label WTL. Show all posts

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)

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)

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

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)

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)

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)

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.

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?

Friday, February 27, 2009

TouchBrowser - III


Here's the latest update of the TouchBrowser code. This time I added a gradient to the selection cursor and also added the file size and last access date. The file size needs to be pretty-printed to make reading easier.

On touch-screen devices, the list now supports a HitTest function that, by delegating to the underlying list item, reports what part of the item was clicked by the user and what action is associated with it. In this case I made the icon area sensitive to the selection action so you now navigate into a directory by clicking the icon. If you just click the file name, nothing will happen beyond scrolling the list and setting the selection cursor.

Sample: TouchBrowser3.zip

Wednesday, February 11, 2009

TouchBrowser - I


My planning for the first half of 2009 includes writing a SQL Compact explorer, something like the old isqlw mobile application. One of the components this application needs is a friendly way to select the database files - something along the lines of the open file dialog, only a bit better.

Towards this end, I picked up the "touch" window code used in the property list and adapted it to a very simple file browser. The sample application that I'm publishing includes a revised version of the atltouch.h file and implements a very simple-minded "file explorer" window.

You navigate either by scrolling the list or by using the arrow keys. To list a sub folder, just click it or select it and press the enter key. To back up to the previous level, use the main menu "Up" command.

There are still some issues to be sorted out in this code, like the apparent sensitivity when you start dragging a directory entry up or down - you may end up expanding that directory instead of dragging the list. I have struggled with this issue ever since I started to write this code and I'm starting to believe that a different approach may be needed, like the addition of an action button to the right of each file: only by pressing it will the user get the associated action (opening a sub-folder, for instance). This solution implies having larger list items so that a finger can be effectively used (but this is also an issue with WM devices that are expecting a stylus, not a bulky finger). I will be investigating these issues and posting the code in the next few posts.

Sample code: TouchBrowser.zip (27 KB)

Tuesday, February 03, 2009

Property List Notifications

In my last post I presented a custom control based on the previously published CTouchWindow WTL class. In this post I'm updating the code to support individual item enabling and disabling and also to illustrate how the client code can manage item notifications.

Each CTouchListItem (the base class for CPropertyListItem) now supports two new functions to control and report the enabled state: SetEnabled and IsEnabled. After changing the item state your code will have to update the item in order to reflect its updated status (this is very likely to change in the near future).

The new sample code now implements a very simple notification handling mechanism that tests the check state of the check box. This is done in the dialog's OnItemActivated method, called after a particular item is activated or deactivated. In this case, I test if the activated item is the check box item and enable or disable the second group (collapsing it when disabling).

As always, comments are welcome!

Sample: PropList2.zip (46 KB)

Wednesday, January 21, 2009

The Property List

Before I can go any further in the development of the SQL Explorer device application, I must make sure that I have some components ready for use. These will include (but will not be limited to):

  • A tree component to display the database schema;
  • A property list control to edit/display object properties such as connection, table and column properties;
  • A grid or table-like display for table and query results;
  • A splitter control for compound views;
  • A decent file open dialog box.

It surely would be easy to just use the controls that Windows Mobile has in store for us: the tree view and the list view. These are undoubtedly the most used controls but are somewhat déja-vu and are arguably hard to use (especially the list view). I decided to (guess what) write these controls from scratch using something the WTL CTouchWindow class that I published here a some months ago.

This class is a nice candidate to be a base class for the new tree, grid and property list controls because it enables a touch-like interface. My first approach was to implement the property list control taking some of my previous work as a model: A list-based form for Windows Mobile. There are two nagging issues with this code: it uses MFC and subclasses the list view control. As I've learned by implementing the WTL version I'm presenting here, subclassing and custom-painting the list view is more work than you need to implement the control.

The property list is shown here contains a list of editable items and groups. Groups are shown as collapsed (the + sign indicates that the item can be expanded) and, like the original MFC implementation, each group can contain only editable items, not other goups (I may change this later on).

A group should be used as a means to group related data items and to ease the list navigation. When clicked the group expands to display the contained editable items. By clicking again, the group collapses and hides the contained items. This is the same principle that you can see at work with a tree, so extending this concept to a "touch tree" should not be very difficult.

Each editable item may be in either of two states: focused or activated. An item gets the focus when it is clicked and when either the up or down keys are used to change the selection. A focused item shows the focus rectangle around it. When the enter key is pressed (or when the user clicks the item) it is activated (note that activating implies setting the focus). The notable exception to this rule is the text editor item that activates itself when it receives the focus.

When an item is activated, it generally creates a Windows control to perform the editing. The exceptions to this rule are the check box (changes its state) and the group item (expands / collapses the contained items).

As of this implementation, the supported data item types are:

  • Text editor
  • Date time editor
  • Check box
  • Combo box
Here is the expanding property list:



The scroll bar to the right is custom-painted and is not yet the final version (I'm still thinking about allowing the use of old style scroll bars). The advantage of this type of scroll bar is its transparency - you can actually read what's beneath it so you do get a few more pixels of screen real estate.

I will make lots of changes and additions to this code but, in the meantime, please do take a look at it and be so kind as to use it and criticize it.

Sample code: PropList.zip (45 KB)

Wednesday, October 01, 2008

CStdDialogImpl and the OK button

Are using CStdDialogImpl as the base class for your WTL dialogs? Are you having difficulty hiding the "ok" button? Here's a simple solution:

Derive your dialog class (say CMyDialog) from

CStdDialogImpl<CMyDialog, SHIDIF_SIZEDLGFULLSCREEN | SHIDIF_SIPDOWN>

On the OnInitDialog handler, call:

SHDoneButton(m_hWnd, SHDB_HIDE);
ModifyStyle(0, WS_NONAVDONEBUTTON, SWP_NOSIZE);

Make sure you change all the calls to CStdDialogImpl<CMyDialog> methods with the new base (you can use a typedef for that).

Sunday, August 03, 2008

The Touch List - II

I finally have some time to come back and write about the Touch List window. It's been quite some time since I wrote the first post about this code, and it has changed a lot (especially because I had to use it for a customer project), and I have also learned a lot about how to make this code work on both Windows Mobile and Windows CE devices.

Code Changes
The first challenge I had to face was to decouple the "kinetics" from the list and implement it in a more general WTL base class. This was a project requirement for one of the data windows where a bitmap is displayed and the same auto scrolling behavior was sought.

The second challenge was to implement some sort of scroll bar into the window. I could use the native Windows scroll bars but I decided to use something nicer and possibly "cooler".

All the "touch" code was put into one single header file pompously named atltouch.h (see the sample code here). This header file contains the following classes:
  • CScrollBarData - Contains scroll bar data (either horizontal or vertical) and associated calculations.
  • CTouchWindow - The "touch" base class, where you will find all generic "kinetics" functions.
  • CTouchListItem - Base class for touch list items. Implement one for your items (see sample code).
  • CTouchList - The touch list class template.
Please understand that this code is still very much under construction so you will see some redundant concepts and the occasional bug.

Finger Use
Most of the current devices are not ready for finger input, only for stylus input. Sure you can use your finger but I have found that on some devices, when you put your index finger to the screen, the application window receives the expected WM_LBUTTONDOWN, but may also receive a lot of WM_MOUSEMOVE messages... Why is this? Your finger is way larger than the expected stylus tip so you are effectively touching more than one screen point. What I have experienced is that most devices will produce the mouse move messages and your list will start scrolling just by touching it with your finger. This is less likely to happen when using the stylus.

The solution for this was to implement a "sensitivity" factor that will ignore movements within a given range (see the SetSensitivity method). If you use this with any value larger than 1 (in either direction) your list will become less sensitive, but you will have to adjust this value to your device...

Scroll Bars
Scroll bars have an unusual implementation, but I hope you find them useful (if not, suggestions
are mostly welcome). To use the vertical scroll bar, just drag your finger (or stylus) up or down and the list will scroll accordingly.

On Windows Mobile 5 and 6 devices, these are implemented as a transparent layer on top of your list so you can use the full screen size to display data.

Wednesday, July 02, 2008

Installing WTL Helper in VS 2008

Last April my good friend Cristiano Severini managed to recompile Sergey Solozhentsev's WTL Helper for VS 2008. He wrote a few instructions about how to do it, but they are a bit incomplete. I have just reviewed the whole process with him and managed to successfully install his version of the WTL Helper DLL on a VS 2008 under Vista. Here's how to do it:
  • Install the original WTL Helper package;
  • Download WtlHelper9.dll and copy it to the same install directory;
  • Download WtlHelper9.reg and import it into your own registry using Regedit (you may have to edit the path);
  • Open a command line (use Admin rights under Vista), go to the install directory and run the regsvr32 WtlHelper9.dll command;
  • Start VS 2008 - the WTL helper must be there.

Enjoy!

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!