Improved Touch Support with MFC 10

Introduction

When considering if and how to add touch support to an MFC application, the first point worth assessing is how well the application will perform in touch-scenarios without explicitly adding any support at the application level. The Windows team has gone to great efforts to make applications work well even if they have no code present to deal with touch input. In these situations, Windows will primarily use touch in much the same mode as a mouse, with screen taps equating to mouse clicks, and an on-screen keyboard allowing users to enter text into edit controls. The exact behavior of touch input can be customized via the Windows Control Panel. Figure 1 shows a simple MFC Dialog-based application that has an Edit Control to allow text input. This application has had no explicit touch support added. When this application is run on hardware with digitizer support and the digitizer is used to set the focus to the Edit Control, an on screen keyboard icon is displayed.

MFC and Touch on screen keyboard icon
Figure 1. Out-of-the-box touch experience with MFC and Touch

Clicking on the keyboard icon brings up the Touch Keyboard shown at the top of Figure 2. The text input panel on Windows 7 has two modes that can be switched between using the button at the top-left of the panel. The Touch Keyboard offers standard key-based text input, while the Writing Pad (shown at the bottom of Figure 2) has a much richer experience, offering the option to write in either character-by-character mode or using freehand style. Character-by-character has a blank cell where individual letters are entered using a pen, while freehand style offers a more natural paper-like experience of digital inking, and hand-writing recognition algorithms are used to form words and sentences. Windows 7 also supports the ability to personalize handwriting recognition at an operating system level.

Text Input Options
Figure 2. Text Input Options

Once some text has been entered in either the Writing Pad or Touch Keyboard, an Insert button allows the text to be moved into the Edit Control, as shown in Figure 3.

Writing Pad with text ready for insertion
Figure 3. Writing Pad with text ready for insertion

If an MFC application is designed with a clean, simple interface, the inbuilt operating system support for touch- and pen-based input may be sufficient. After covering the two other options for touch integration below, we'll briefly return to this first choice and see how it can be improved on.

For some MFC applications, providing direct support for touch may lead to a better user experience. There are two ways that an application can support touch, indirectly by allowing Windows to translate the touch input into gestures (such as zoom, pan or rotate), and directly by receiving the low-level touch events and executing code that responds to them.

Responding to gestures in an MFC application is simple - Windows 7 and Windows Server 2008 R2 both support the WM_GESTURE Windows message. MFC translates the various panning, zooming and rotating gestures that are all encapsulated by WM_GESTURE into distinct CWnd virtual methods like OnGestureZoom and OnGestureRotate that take care of the parsing of the information in the WM_GESTURE parameters into specific information relevant to the gesture.

The MFC Gesture CWnd virtual functions are:

  OnGestureZoom(CPoint ptCenter, long lDelta) 
  OnGesturePan(CPoint ptFrom, CPoint ptTo)
  OnGestureRotate(CPoint ptCenter, double dblAngle)
  OnGestureTwoFingerTap(CPoint ptCenter)
  OnGesturePressAndTap(CPoint ptPress, long lDelta)

Each function returns a BOOL that indicates whether the event has been handled. The MFC Class Wizard that ships with Visual C++ 2010 RTM does not currently have support for either the WM_GESTURE message or the OnGestureXXX virtual methods. However, adding the handlers is a simple exercise:

  //in View header file
  class CMyView : public CView
  {
  // Overrides
  protected:
   virtual BOOL OnGestureZoom(CPoint ptCenter, long lDelta);
  //in View Source File
  BOOL CMyView::OnGestureZoom(CPoint ptCenter, long lDelta)
  {
   //code for zooming lDelta here
   return TRUE;
  }



Improved Touch Support with MFC 10

For certain types of applications like drawing and CAD programs, the pre-processing of touch input into gestures will not be required, and the application needs to receive the raw input to determine if the touch is a gesture or a drawing command for the application. To achieve this, some preliminary work is required for the application. The first action, which is not mandatory but generally sensible to complete, is to determine what touch support in available on the hardware that the application is running on. To achieve this, a call to the Windows SDK function GetSystemMetrics is required, passing SM_DIGITIZER as the parameter. This function returns a bitflag, with the documented values from MSDN being:

  Name	                Value	        Description
  TABLET_CONFIG_NONE	0x00000000	The input digitizer does not have touch capabilities.
  NID_INTEGRATED_TOUCH	0x00000001	An integrated touch digitizer is used for input.
  NID_EXTERNAL_TOUCH	0x00000002	An external touch digitizer is used for input.
  NID_INTEGRATED_PEN	0x00000004	An integrated pen digitizer is used for input.
  NID_EXTERNAL_PEN	0x00000008	An external pen digitizer is used for input.
  NID_MULTI_INPUT	        0x00000040	An input digitizer with support for multiple inputs is used for input.
  NID_READY	        0x00000080	The input digitizer is ready for input.

The hardware support available can be determined by applying the bitwise & operator using these flags and the value returned from GetSystemMetrics(SM_DIGITIZER). Windows 7 supports multiple simultaneous touch point inputs, and calling GetSystemMetrics with a parameter of SM_MAXIMUMTOUCHES will return the number of touch points available.

After an application has determined that touch support is available, the next step is to call CWnd::RegisterTouchWindow on each CWnd-derived class for which direct touch input will be processed. Calling RegisterTouchWindow will mean that a window will no longer receive the higher-level gesture messages. Touch registration can be done any time after a window is created, so if a window will always be touch-aware, the WM_CREATE message can be handled (the Visual C++ Class Wizard can be used to add a handler for this method), and RegisterTouchWindow can be called as shown below.

  int CMyView::OnCreate(LPCREATESTRUCT lpCreateStruct)
  {
   if (CView::OnCreate(lpCreateStruct) == -1)
    return -1;
  
   VERIFY(RegisterTouchWindow(TRUE, 0));
   return 0;
  }

As with gestures, touch messages are not currently supported by the Class Wizard, and the MFC virtual overrides to handle touch messages that need to be added manually:

  //view header file
  virtual BOOL OnTouchInput(CPoint pt, int nInputNumber, int nInputsCount, PTOUCHINPUT pInput);
  //view source file
  BOOL CMyView::OnTouchInput(CPoint pt, int nInputNumber,
    int nInputsCount, PTOUCHINPUT pInput)
  {     
  //handle touch message here
   return TRUE;
  }

The first strategy for touch integration that was covered at the start of the article mentioned that simply by adopting a simple, clean interface, the built-in operating support for touch and pen input via the Onscreen Keyboard and Writing Pad may be sufficient. One enhancement to this solution worth considering is spreading out the controls on the user interface if an application detects that touch interaction is active. This compensates for the less precise nature of touch input compared to using a mouse.

To implement this enhancement, the main window of the application would register to receive touch input messages, but the OnTouchInput method would return FALSE to indicate the application does not want to handle the message, allowing normal tap processing to occur. Before returning FALSE, a flag can be set to indicate that touch-based interaction is occurring and the UI can be adjusted accordingly.

Conclusion

Windows 7 and MFC 10 provide complete and rich support for providing users with applications that "Think In Ink". Apart from the built-in operating support that allows applications without any explicit touch and ink support to receive input via the Onscreen Keyboard and Writing Pad, there are two mutually-exclusive modes of touch support. The default touch input support mode is gestures, which is a Windows-provided mapping of distinctive touch sequences into gestures like zoom and pan. MFC further translates these gestures into a simplified set of CWnd virtual methods that can be overridden as required. The most comprehensive mode of touch support is registering to receive the low-level touch messages which may be coming from multiple touch points simultaneously, and responding to these touch events in the message handler. Regardless of the touch integration strategy chosen for an application, MFC provides a rich and complete framework for implementing it.





Comments

  • There are no comments yet. Be the first to comment!

Leave a Comment
  • Your email address will not be published. All fields are required.

Top White Papers and Webcasts

  • Live Event Date: September 10, 2014 @ 11:00 a.m. ET / 8:00 a.m. PT Modern mobile applications connect systems-of-engagement (mobile apps) with systems-of-record (traditional IT) to deliver new and innovative business value. But the lifecycle for development of mobile apps is also new and different. Emerging trends in mobile development call for faster delivery of incremental features, coupled with feedback from the users of the app "in the wild". This loop of continuous delivery and continuous feedback is …

  • The explosion in mobile devices and applications has generated a great deal of interest in APIs. Today's businesses are under increased pressure to make it easy to build apps, supply tools to help developers work more quickly, and deploy operational analytics so they can track users, developers, application performance, and more. Apigee Edge provides comprehensive API delivery tools and both operational and business-level analytics in an integrated platform. It is available as on-premise software or through …

Most Popular Programming Stories

More for Developers

Latest Developer Headlines

RSS Feeds