While most CE devices have some sort of “keyboard”, these are often tiny
and awkward. For obvious reasons, users prefer the stylus. The
stylus-oriented interface is really a bonus for Windows CE programmers,
because it allows us to dispense with a great deal of the housekeeping that
goes with mouse and keyboard based user input on the desktop. Being a “touch
screen” kind of device, the stylus eliminates the need for floating cursors,
by inherently keeping track of insertion points, and the like.
When used to “tap” the CE device’s screen, the stylus is conceptually
treated as a “1 button mouse”. In general, you can assume existing programming
logic that detects left mouse button presses, including double clicks, will
port to CE with few or no changes. Code that handles right mouse button
presses will require some work-arounds, but porting this code is more a matter
of strategy than technique.
Porting Tip: Ease of use is the overriding consideration when designing
user input mechanisms.
On many CE devices, the keyboard is really a “last resort” for user input.
For this reason, you’ll want to give some consideration to allowing users to
provide input to your application using the “inking” capability of the CE
device. I use the word “consideration” advisedly, for there are some serious
issues to weigh in this matter. On the positive side, users really
like being able to treat their CE devices as “smart” memo pads.
Conversely, you’ll find that most of them really dislike “typing”
with a stylus or on a miniscule keyboard. This argues in favor of giving users
the opportunity to interact with your application in the ways they find most
convenient. On the other hand, the implementation of inking is maddeningly
asymmetrical across the various CE versions and platforms. If you choose to
aggressively support inking, expect to maintain a variety of code bases until
all of this gets sorted out.
With a view to the overarching theme of this book ( rapidly porting Win32
code to CE), I’ll offer my personal metric for deciding when to use inking in
the first CE version of your Win32 app:
- Speed and ease of input are very important
- Absolute accuracy is relatively unimportant
- It’s not practical to supply a predetermined list of choices
- The application doesn’t use the input to drive runtime decision
making
Porting Tip: Use inking to store small to medium amounts of text that don’t
drive runtime decision making.
We’ll move on to explore example applications that show how to use the
stylus as a substitute for the mouse, and how to use it as a pen.
The Stylus Behaves As A One Button Mouse
The StylusTrack Example application shows how to receive and manipulate
stylus input. It captures the coordinates of the starting and ending points
of the line the user specifies by dragging the stylus across the screen, then
uses the point either as the diagonal of a rectangle or of the bounding
rectangle of an ellipse. Figure 1 shows how the StylusTrack example looks on
an HPC:
Figure 1 – The StylusTrack Application
The main source file for the StylusTrack example can be found in the
accompanying zipped code file. In the interest of brevity, we have omitted
the support files.
All of the drawing done in the StylusTrack example is done in response to
mouse messages. Notice that the message switch has no case for application
specific handling of the WM_PAINT message. Lets look at the initial stylus
handling, done in the WM_LBUTTONDOWN case of the message switch:
case WM_LBUTTONDOWN : //If Left button is down, save mouse coordinates in Line[0] point bLBDown = TRUE; line[0].x = LOWORD(lParam); line[0].y = HIWORD(lParam); break;
Notice that we don’t have to use SetCapture() to get the mouse movement
messages generated by the stylus. By default, CE sends the top window the
mouse messages. In response to the WM_LBUTTONDOWN we set the bLBDown to TRUE,
and copy the coordinates at which the mouse button went down from the lParam.
When the WM_LBUTTONUP message arrives, the drawing work begins. First, we
copy the point coordinates from the lParam of the message. We test them to
see if the stylus has actually moved, or if this was just a tap. If the stylus
moved we draw a line that is either the diagonal of the rectangle or the long
axis of the ellipse.
case WM_LBUTTONUP : //Draw last line. Since Left button down is false, // no more lines are drawn //until next WM_LBUTTONDOWN message line[1].x = LOWORD(lParam); line[1].y = HIWORD(lParam); if((line[0].x != line[1].x) || (line[0].y != line[1].y)) { Polyline(hdc, line, 2);} if ( bLBDown == TRUE ) { hdc = GetDC(hWnd); Polyline(hdc, line, 2);
Next, we use the coordinates to draw either the rectangle or the
ellipse:
if( iFigure == RECTANGLE ) { Rectangle( hdc, line[0].x, line[0].y, line[1].x, line[1].y ); } if( iFigure == ELLIPSE ) { Ellipse( hdc, line[0].x, line[0].y, line[1].x, line[1].y ); }
Finally, we reinitialize the coordinates in the point array, release the
DC, and set bLBDown to FALSE.
//reset value of initial point to end point line[1].x = 0; line[1].y = 0; line[0] = line[1]; } ReleaseDC(hWnd, hdc); } //end if LButtonDown bLBDown = FALSE;
If you wanted to continuously track the stylus, you could add a
WM_MOUSEMOVE case that accumulated points in a larger array, or simply did the
drawing as the stylus moved.
Downloads
Download source code: StylusInput.zip – 3
kb.
Looking Ahead:
In the next installment we’ll look at the how to use the CE ink
control.
About the Author
Nancy Nicolaisen is a software engineer who has designed
and implemented highly modular Windows CE products that include features such
as full remote diagnostics, CE-side data compression, dynamically constructed
user interface, automatic screen size detection, entry time data
validation.
In addition to writing for Developer.com, she has written several books
including Making Win 32 Applications Mobile.
# # #