Q75040: Flow-of-Control During Recognition

Article: Q75040
Product(s): Microsoft Visual Basic for Windows
Version(s): 1.0
Operating System(s): 
Keyword(s): 
Last Modified: 06-NOV-1999

-------------------------------------------------------------------------------
The information in this article applies to:

- Microsoft Windows for Pen Computing, version 1.0 
-------------------------------------------------------------------------------

SUMMARY
=======

The text below provides an overview of recognition processing in the Microsoft
Windows for Pen Computing environment. It discusses the specific steps that
occur within an application during recognition, and outlines how each element in
the recognition context (RC) structure and RCRESULT structure are set. The first
part of the article discusses, in very general terms, the flow-of-control
through the system. The second half of the article outlines the flags and
variables checked by each component as control passes from the application
through the system into the recognizer and back again.

This article does not cover the intricacies of hedit or bedit controls; it only
outlines what happens within the system when an application makes a call to the
InitRC and Recognize functions. This article should be read in conjunction with
the "Microsoft Windows for Pen Computing: Programmer's Reference" manual.

Note that this article does not discuss the responsibilities of a recognizer or
of the dictionary. Each of these components can be replaced; therefore, the
actions of these components may vary slightly from one version to another.

DISCLAIMER: The information presented in the article was gathered from version
1.0 of the Windows for Pen Computing software. The process outlined in this
article is not guaranteed to be the process in any future release. Microsoft
provides the information below only for educational purposes and reserves the
right to change this process at any time.

MORE INFORMATION
================

BACKGROUND ASSUMPTIONS
----------------------

This article uses only the simplest sample code to keep the discussion as general
as possible. The sample code discussed in this article is a modification of the
Generic sample application provided with the Microsoft Windows Software
Development Kit (SDK). Specifically, make the following three additions to the
GENERIC.C file:

1. Add the following code to the top of the file:

        #include "penwin.h"

2. In the global variable section, add the following line:

  " RC rc; " (without the quotation marks)

3. Add the following code to the MainWindProc function to process the
  WM_LBUTTONDOWN message:

        case WM_LBUTTONDOWN:
           InitRC(&rc);
           Recognize(&rc);
           break;

  A fourth modification that checks for the WM_RCRESULT message may also be
  desirable.

INTRODUCTION
------------

From the standpoint of an application, there are three main steps in the
recognition process:

1. Create and fill an RC structure.

2. Call the Recognize function.

3. Process the WM_RCRESULT message.

Although each of these topics will be discussed in detail below, the following is
a general overview of this process. The RC structure holds the flags and
variables that are used by the system and the recognizer during a call to
Recognize. This function manages the interactions between the system and the
installed recognizer. During processing, the application receives one or more
WM_RCRESULT messages that contain the information acquired during recognition.
During each of the three steps, the system performs specific tasks, which this
article addresses in more detail.

THE SPECIFIC STEPS
------------------

The following text treats the three-step process discussed above in more detail.
The process is now broken into ten steps:

1. The application calls InitRC to retrieve a copy of the global RC structure.
  The application can modify its local copy to fine-tune the recognition
  process.

2. The application processes the WM_LBUTTONDOWN message,

and

3. calls the Recognize function, passing in the RC structure that controls the
  recognition process.

4. Based on the data in the RC structure, Recognize calls the RecognizeInternal
  function in the installed recognizer, which gathers and interprets user
  input.

5. The results from the recognition process are passed to the ResultsFunction,
  which performs any dictionary processing and gesture mapping.

6. Windows for Pen Computing sends a WM_RCRESULT message to the application.

7. through 10. After the application processes the WM_RCRESULT message, there
  are no additional function calls. Control passes through each of the
  functions called in steps 1 through 6 during the return process to allow the
  functions to perform any required housekeeping.

The following text discusses each of the ten steps above in depth:

1. Call InitRC Function
-----------------------

The InitRC function copies the global RC structure held by the system into a
local variable within the application. This RC structure contains all the
information needed to perform recognition. If the user has not modified the
global RC structure, the values listed in the following table will be copied
into the local RC structure. The values that the user can change using the
Control Panel are labeled with the letters "CP" following the description.

  hrec             = NULL            // Default recognizer; CP
  hwnd             = NULL            // Result window; set by InitRC
  wEventRef        = RC_WDEFAULT     // Eventref; fixed default
  wRcPreferences   = 0               // No RCP flags; CP
  lRcOptions       = 0               // No RCO flags; fixed default
  lpfnYield        = NULL            // Null yield callback
  lpUser           = {0,0}           // Default user; CP
  lpLanguage       = {0,0}           // Default language; CP
  rglpdf           = {LPDFNULL}      // Default dictionary path; CP
  clTryDictionary  = 0               // Default dictionary level; CP
  clErrorLevel     = 0               // Default error level; CP
  alc              = ALC_DEFAULT     // Fixed default
  alcPriority      = ALC_NOPRIORITY
  rgbfAlc          = {0, 0}          // Bit field for enabled characters
  wResultMode      = RRM_COMPLETE    // Fixed default
  wTimeOut         = 1000            // Time Out; CP
  lPcm             = PCM_TIMEOUT     // CP
  rectBound        = {0,0,0,0}       // Bounding rect; set by InitRC
  rectExclude      = {0,0,0,0}       // Exclude rect; fixed default
  guide            = {0,0,0,0,0,0,0,0,0} // Guidelines; fixed default
  wRcOrient        = RCOR_NORMAL     // Text orientation; fixed default
  wRcDirect        = RCD_DEFAULT     // Text direction; fixed default
  bInkWidth        = 1               // Ink width; CP
  rgbInk           = 0L              // Ink color; CP
  dwAppParam       = 0L
  dwDictParam      = 0L
  dwRecognizer     = 0L              // No default
  rgwReserved      = {0,0,0,0,0,0,0,0} // Fixed default

An application can verify the values for each of these variables by examining the
RC structure returned by InitRC.

InitRC copies the global RC to a local variable and also initializes a small set
of variables to RC_LDEFAULT or RC_WDEFAULT. These two default values instruct
the Recognize function to use the current default settings defined in the
Control Panel for a given variable. If an application overrides a default
setting, the Recognize function will not receive the most current system setting
for that value.

(NOTE: According to the PENWIN.H header file, the values of RC_WDEFAULT and
RC_LDEFAULT are 0xFFFF and 0xFFFFFFFF, respectively. The value for
RC_WDEFAULTFLAGS is 0x8000.)

The following four steps take place when an application calls InitRC:

a. The global RC structure is copied to a local variable.

b. The hwnd field is set to the value of the hwnd parameter passed in to the
  InitRC function.

c. The local RC structure is modified as follows:

        lprc->hrec            = RC_WDEFAULT;
        lprc->wRcPreferences  = RC_WDEFAULT;
        lprc->lpUser          = RC_LDEFAULT;
        lprc->lpLanguage      = RC_LDEFAULT;
        lprc->rglpdf          = RC_LDEFAULT;
        lprc->lPcm            = PCM_ADDDEFAULTS;
        lprc->wTryDictionary  = RC_WDEFAULT;
        lprc->clErrorLevel    = RC_WDEFAULT;
        lprc->wTimeOut        = RC_WDEFAULT;
        lprc->nInkWidth       = RC_WDEFAULT;
        lprc->rgbInk          = RC_LDEFAULT;
        lprc->wCountry        = RC_WDEFAULT;
        lprc->wIntlPreferences= RC_WDEFAULTFLAGS;

d. If the hwnd parameter is not NULL, the client area of he window is retrieved,
  converted the window coordinates to screen coordinates, and stored the
  coordinates in the rectBound field of the RC structure. Set the lPcm field to
  PCM_RECTBOUND.

2. Process the WM_LBUTTONDOWN Message
-------------------------------------

The logical place for an application to initiate the recognition process is
during the processing of the WM_LBUTTONDOWN message. The application calls the
Recognize function and passes in the address of the RC structure initialized by
InitRC.

3. Call the Recognize Function
------------------------------

To control the recognition process, Recognize requires only a pointer to an
application-specified RC structure. Upon receiving control, the Recognize
function performs the following twenty steps:

a. Validates the Guide Structure and returns REC_GUIDE error if it is not valid.

b. Creates a local copy of the RC structure passed to it.

c. Validates the hwnd field. The REC_HWND error is returned if validation fails.

d. If the RCO_TABLETCOORD flag is not set in the lRcOptions field, and the
  application specifies cold recognition, then Recognize converts the values of
  the rc.rectBound structure, rc.rectExclude structure, and rc.Guide structure
  into tablet coordinates from screen coordinates. If the application does not
  specify cold recognition, then Recognize sets only the rectBound and
  rectExclude structures.

  If the application set the PCM_RECTBOUND flag in the RC structure, Recognize
  creates a clipping rectangle for the rectBound member. Similarly, if the
  application set the PCM_RECTEXCLUDE flag in the RC structure, Recognize
  creates a clipping rectangle for the rectExclude member.

e. Checks the lPcm field for the PCM_ADDDEFAULTS flag. If this flag is set,
  fills the RC structure with the default lPcm values from the most current
  global RC structure.

f. If the lPcm field does not contain PCM_TIMEOUT, sets the TimeOut field to
  zero. Otherwise, if lPcm is set to RC_WDEFAULT, puts the wTimeOut value found
  in the most current global RC structure in this position. If neither flag is
  set, does not modify the wTimeOut field.

g. If the wEventRef field is set to RC_WDEFAULT, the Recognize function
  retrieves the "extra" information associated with the most recent mouse
  message from the system.

h. If Recognize is called from RecognizeData, sets the cold recognition flag,
  RCO_COLDRECOG.

i. If the RCO_COLDRECOG flag is not set, determines that the pen is or is not in
  contact with the tablet. If the pen is in contact with the tablet, then
  verifies that the RC structure has valid values for rectBound and
  rectExclude, and determines that the point is or is not in either the
  rectBound or rectExclude rectangle.

j. Checks each of the following fields to see if it contains either RC_WDEFAULT
  or RC_LDEFAULT. If so, Recognize copies the value found in the corresponding
  position in the current global RC structure into the local RC structure. At
  this step, Recognize introduces the current values, which are controlled by
  the Control Panel, into the RC structure.

   - nInkWidth

   - rgbInk

   - hrec

   - wRcPreferences

   - wTryDictionary

   - clErrorLevel

   - lpfnYield

   - lpUser

   - lpLanguage

   - rglpdf

   - wCountry

   - wIntlPreferences

k. Checks for RCO_NOPOINTEREVENT. If pointer events are allowed, determines that
  the pen is acting like a mouse or like a pen. If the user "taps" or "presses
  and holds" the pen, the recognizer returns the REC_POINTEREVENT value.
  Otherwise, the user "presses and moves" the pen, which initiates pen
  functionality.

l. Verifies that the dynamic-link library (DLL) specified in the hrec field
  exported the RecognizeInternal function. If this call fails, Recognize
  returns the error code REC_HREC.

m. If the value in the ink width field is greater than zero, initializes inking.

n. Makes an internal call to set up the terminating conditions. Fields used in
  this process include: lPcm, rectBound, and rectExclude. If Recognize cannot
  create a terminating condition, it returns the error code REC_PCM.

o. Puts the pen in collection mode. If the call fails, Recognize returns the
  error code REC_BADEVENTREF.

p. Turns off Mouse Trails, if enabled.

q. Checks lRcOptions for the RCO_NOHIDECURSOR flag. If this flag is not set,
  Recognize calls ShowCursor to hide the cursor.

r. Enables inking.

s. Removes any mouse messages currently in queue.

t. Calls the RecognizeInternal function with the RC structure and the address of
  the ResultsFunction.

4. Call the RecognizeInternal Function
--------------------------------------

Most of the work of the recognition process occurs here. This function gathers
the raw data, builds the PenData data structure, interprets the raw data, builds
the symbol graph, and returns the RCRESULT structure to the ResultsFunction.

NOTE: This function is the heart of the recognizer. RecognizeInternal is a
replaceable component that may vary slightly between versions. The flags and
variables that are typically referenced by the recognizer depend upon the
recognizer being used. Therefore, that information is not included here.

5. Call ResultsFunction
-----------------------

In the ResultsFunction, the system can make any necessary modifications to the
values in the RCRESULT structure before it is returned to the application that
called Recognize. This function checks flags, calls the DictionarySearch
function, performs any gesture mapping, and then sends the WM_RCRESULT message
to the application. The seven specific steps are listed below:

a. If the value of the syg.lpsye member of the RCRESULT structure is NULL, the
  ResultsFunction sets the cSyv and lpsyv variables to zero. Also, if the
  syg.lpsye is NULL and hSyv was created by the ResultsFunction , then the
  ResultsFunction sets hSyv to NULL as well.

  Otherwise, the ResultsFunction performs the following three steps:

  1. If the value of syg.hSyv is NULL, allocates memory for the symbol array.
     Otherwise, the ResultsFunction assumes that the recognizer has performed
     dictionary processing.

  2. Calls the DictionarySearch routine. For more information about dictionary
     processing, refer to the "Programmer's Reference" manual or search in the
     Microsoft Knowledge Base on the following words:

  " prod(penwin) and dictionary " (without the quotation marks)

  3. Records the length of the symbol string returned by the DictionarySearch
     function in the cSyv variable. This length does not include the NULL that
     terminates the SYV.

b. If the following four conditions are met, the ResultsFunction calculates the
  value of the rectBound variable from the PenData structure. The
  ResultsFunction converts this value to client coordinates and stores it in
  the rectBoundInk field.

  1. The results are not generated from cold recognition (the RCO_COLDRECOG
     flags was not set).

  2. The ink width for the data is greater than zero (nInkWidth > 0).

  3. A PenData structure exists (getPenDataHeader returned success).

  4. The PenData structure is not empty.

c. If RCO_SAVEALLDATA is set and data is present, then the ResultsFunction will
  reallocate the memory with Pen Windows as the owner to prevent the memory
  from being discarded if Pen Windows frees the recognizer DLL.

d. The ResultsFunction checks to see if it must call the gesture mapper. If so,
  it modifies the SYV array in the RCRESULT structure to represent the mapped
  string of characters or key strokes that the user defined with the gesture
  mapper in the Pen Palette. If the following two conditions are met, the
  ResultsFunction calls the internal gesture mapper:

  1. The wResultsType field of the RCRESULT structure has the RCRT_GESTURE bit
     set.

  2. If the RCO_DISABLGESMAP bit in the lRcOptions member of the RC structure
     is not set, the gesture mapper maps the gesture into the SYG structure in
     the RCRESULTS structure. If the mapping is performed, the gesture mapper
     sets the RCRT_ALREADYPROCESSED flag and either the RCRT_GESTURETOKEYS or
     RCRT_GESTURETRANSLATED flag, depending on type of mapping.

e. If the RCRT_NOSYMBOLMATCH flag is set in the wResultsType field, and the
  RCO_NOFLASHUNKNOWN flag is not set, the ResultsFunction flashes the question
  mark cursor to inform the user that nothing was recognized. If the
  wResultsType field contains RCRT_GESTURE, the application did not disable the
  cursor flash by setting the RCO_NOFLASHCURSOR flag, and lpsyv is not NULL,
  then if lpsyv points to SYV_COPY, the cursor temporarily changes to a COPY
  cursor to indicate that a copy operation is taking place; otherwise, the
  cursor does not change. This step is designed to give the user some visual
  feedback when the system might not otherwise react.

f. If RCO_NOHOOK is not set in the lRcOptions field, the ResultsFunction returns
  the results to the function that set the hook. An application can set a hook
  by calling the SetRecogHook function.

g. The system sends the WM_RCRESULT message to the original calling application.

6. Process the WM_RCRESULT Function
-----------------------------------

When the application receives the WM_RCRESULT message, it can copy anything from
the RCRESULT structure into local variables for future reference. The
application must copy any data to save it. All memory allocated by the system
and the recognizer is freed in the following steps.

7. Return Control to ResultsFunction
------------------------------------

After the application processes the WM_RCRESULT message, control returns to the
ResultsFunction to perform two steps:

a. The ResultsFunction checks the wResultsType field to see if the
  RCRT_GESTURETOKEYS flag is set. If so, it passes the gesture-mapped key
  strokes to the system. Otherwise, the ResultsFunction assumes that the
  application either processed the information or does not want it processed.

b. If the handle to the symbol graph, hSyv in the RCRESULT structure, is not
  NULL and belongs to the system, the ResultsFunction frees that memory.

8. Return Control to the RecognizeInternal Function
---------------------------------------------------

At this point, the application has processed the WM_RCRESULT message and copied
any information critical to its operations. Perform whatever cleanup is required
and return to Recognize.

9. Return Control to the Recognize Function
-------------------------------------------

Recognize checks the lRcOptions field. If the RCO_NOHIDECURSOR bit is set,
Recognize shows the cursor using ShowCursor and returns control to the
application. If Mouse Trails is set (select the Mouse icon in the Control Panel
and check the Mouse Trails check box), Recognize reenables the Mouse Trails
option.

10. Return Control to the Application
-------------------------------------

The application completes the processing of the WM_LBUTTONDOWN message. Process
the return value from Recognize.

NOTE: The application will not receive a WM_LBUTTONUP message after calling
Recognize. The system places this message into the message queue of the calling
application early in the recognition process to work with Windows. Shortly
thereafter, Recognize removes this message from the queue.

Additional query words: 1.00

======================================================================
Keywords          :  
Technology        : kbWinPenSearch kbZNotKeyword3 kbWinPen100
Version           : :1.0

=============================================================================