Using the Automation Library with Windows Mobile Ink

4/8/2010

The Automation Library allows you to interact with the UI and invoke specific controls and UI elements by using COM. This topic contains examples of how to use Automation with Windows Mobile Ink.

For more information, see Automation and Automation Reference.

The _NewEnum property is marked restricted in the Interface Definition Language (IDL) definition for the collection interfaces.

In C++, use a for loop to iterate through a collection by first obtaining the collection's length. The example below shows how to iterate through the strokes of an InkDisp object, pInk.

Syntax

IInkStrokes* pStrokes;
HRESULT result = pInk->get_Strokes(&pStrokes);
if (SUCCEEDED(result))
{
  // Loop over strokes
  long nStrokes;
  result = pStrokes->get_Count(&nStrokes);
  if (SUCCEEDED(result))
  {
    for (int i =0; i < nStrokes; i++)
    {
      IInkStrokeDisp* pStroke;
      result = pStrokes->Item(i, &pStroke);
      if (SUCCEEDED(result))
      {
        // Insert code that uses pStroke
      }
    }
  }
}

Parameters

If you pass in VT_EMPTY or VT_NULL as the index to any of the collection objects in the Automation Library, you receive the first item in the collection because these argument values are coerced to 0 when the call is made.

Support for Aggregation

Aggregation has been tested for only the IInkDisp object, and the IInkOverlay object. Aggregation has not been tested for other controls and objects in the library.

C++

Using the Windows Mobile Ink API requires the use of some COM concepts, such as VARIANT, SAFEARRAY, and BSTR. This section describes how to use them.

VARIANT and SAFEARRAY

The VARIANT structure is used for communication between COM objects. Essentially, the VARIANT structure is a container for a large union that carries many types of data. For more information, see VARIANT and VARIANTARG.

The value in the first member of the structure, vt, describes which of the union members is valid. When you receive information in a VARIANT structure, check the vt member to find out which member contains valid data. Similarly, when you send information using a VARIANT structure, always set vt to reflect the union member that contains the information.

Before using the structure, initialize it by calling the VariantInit COM function. When finished with the structure, clear it before the memory that contains the VARIANT is freed by calling VariantClear.

The SAFEARRAY structure is provided as a way to safely work with arrays in Automation. The VARIANT's parray field is a pointer to a SAFEARRAY. Use functions such as SafeArrayCreateVector, SafeArrayAccessData, and SafeArrayUnaccessData to create and fill a SAFEARRAY in a VARIANT.

The following C++ example demonstrates how to create an IInkStrokeDisp object, pInkStrokeDisp, in an IInkDisp object, pInk, from an array of point data.

VARIANT   var, varPK;
LONG*   plongArray=NULL;
POINT   ptArray[2]={0};
long   lSize=0;
IInkStrokeDisp* pInkStrokeDisp;

IInkDisp*   pInk;   // the object should be created correctly
                    // elsewhere and assigned here.
HRESULT   hr=E_FAIL;

ptArray[0].x = 20;
ptArray[0].y = 100;
ptArray[1].x = 30;
ptArray[1].y = 110;
lSize = 2;   // two points

VariantInit( &var );
VariantInit( &varPK );
SAFEARRAY* psa = SafeArrayCreateVector( VT_I4, 0, lSize*2 );
if( psa )
{
  if( SUCCEEDED( hr = SafeArrayAccessData( psa, (void**)&plongArray) ))
   {
      for( long i = 0; i < lSize; i++ )
      {
         plongArray[2*i] = ptArray[i].x;
         plongArray[2*i+1] = ptArray[i].y;
      }
      hr = SafeArrayUnaccessData( psa );

      if ( SUCCEEDED( hr ) )
      {
         var.vt     = VT_ARRAY | VT_I4;
         var.parray = psa;

        // varPK (packet description) is currently reserved, so it is
        // just an empty variant for now.
         pInk->CreateStroke( var, varPK, &pInkStrokeDisp );
      }
   }
}
VariantClear( &var );
VariantClear( &varPK );

BSTR

The supported string format for Automation is BSTR. The "B" stands for Basic — this is the string format Visual Basic uses internally. A BSTR has a pointer to a zero–terminated string, but it also contains the length of the string in bytes, not counting the terminator, which is stored in the 4 bytes immediately preceding the first character of the string.

The following C++ sample shows how to set the factoid on an IInkRecognizerContext using a BSTR.

IInkRecognizerContext* pRecognizerContext = NULL;
result = CoCreateInstance(CLSID_InkRecognizerContext,
    NULL, CLSCTX_INPROC_SERVER,
    IID_IInkRecognizerContext,
    (void **) &pRecognizerContext);
if SUCCEEDED(result)
{
    BSTR bstrFactoid = SysAllocString(FACTOID_DATE);
    result = pRecognizerContext->put_Factoid(bstrFactoid);
    if SUCCEEDED(result)
    {
      // Insert code that uses the recognizer context
    }
    SysFreeString(bstrFactoid);
}

See Also

Concepts

Windows Mobile Ink Reference

Other Resources

Windows Mobile Ink