Compartir a través de


Ejemplo de receptores de eventos de C++

En este programa se muestra cómo se puede compilar una aplicación que capture eventos InkCollector con solo C++. Este programa crea conjuntamente un objeto InkCollector para la entrada de lápiz- habilitar la ventana. Muestra un cuadro de mensaje cada vez que se recibe un evento Stroke .

Definición de un contenedor para eventos del recopilador de lápiz

La InkCollectorEvents clase controla el paso de eventos del recopilador de tinta desde el recopilador de tintas al usuario de esta clase. El AdviseInkCollector método configura la conexión entre el objeto InkCollector y esta clase. El Invoke método convierte la notificación de eventos IDispatch en una llamada a una función virtual que el usuario de esta clase puede invalidar para procesar un evento determinado.

Nota

Debe hacer más que invalidar la función virtual para que un controlador de eventos obtenga ese evento. Para todos los eventos predeterminados, debe llamar al método SetEventInterest del recopilador de tintas para garantizar la obtención de un evento. En segundo lugar, este objeto serializa en sí mismo subprocesos libres, por lo que todos los controladores de eventos implementados también deben estar libres de subprocesos. De particular importancia es usar las API de Windows, lo que puede provocar un cambio a otro subproceso, ya que no se garantiza que el controlador de eventos se ejecute en el mismo subproceso que la ventana conectada con el recopilador de tintas.

 

// Invoke translates from IDispatch to an event callout
//  that can be overridden by a subclass of this class.
STDMETHOD(Invoke)(
   DISPID dispidMember, 
    REFIID riid,
    LCID lcid, 
    WORD /*wFlags*/, 
    DISPPARAMS* pdispparams, 
    VARIANT* pvarResult,
    EXCEPINFO* /*pexcepinfo*/, 
    UINT* /*puArgErr*/)
{
    switch(dispidMember)
    {
        case DISPID_ICEStroke:
            Stroke(
                (IInkCursor*) pdispparams->rgvarg[2].pdispVal,
                (IInkStrokeDisp*) pdispparams->rgvarg[1].pdispVal,
                (VARIANT_BOOL *)pdispparams->rgvarg[0].pboolVal);
            break;
        ...
    }
    return S_OK;
}

virtual void Stroke(
    IInkCursor* Cursor,
    IInkStrokeDisp* Stroke,
    VARIANT_BOOL *Cancel)
{
    // This is a place holder designed to be overridden by
    //  user of this class.
    return;
}
...

El Init método llama a CoCreateFreeThreadedMarshaler para configurar un serializador de subprocesos libre.

// Init: set up free threaded marshaller.
HRESULT Init()
{
    return CoCreateFreeThreadedMarshaler(this, &m_punkFTM);
}

El AdviseInkCollector método configura la conexión entre el objeto InkCollector y esta clase. Primero recupera un punto de conexión al recopilador de tintas. A continuación, recupera un puntero al para IInkCollectorEvents que pueda establecer una conexión de asesoramiento al control.

// Set up connection between sink and InkCollector
HRESULT AdviseInkCollector(
    IInkCollector *pIInkCollector)
{
    // Get the connection point container
    IConnectionPointContainer *pIConnectionPointContainer;
    HRESULT hr = pIInkCollector->QueryInterface(IID_IConnectionPointContainer, (void **) &pIConnectionPointContainer);
        
    if (FAILED(hr))
        ...
    
    // Find the connection point for Ink Collector events
    hr = pIConnectionPointContainer->FindConnectionPoint(__uuidof(_IInkCollectorEvents), &m_pIConnectionPoint);
        
    if (SUCCEEDED(hr))
    {
        // Hook up sink to connection point
        hr = m_pIConnectionPoint->Advise(this, &m_dwCookie);
    }
    
    if (FAILED(hr))
        ...
    
    // Don't need the connection point container any more.
    pIConnectionPointContainer->Release();
    return hr;
}

El UnadviseInkCollector método libera las conexiones que tiene el objeto al control .

// Remove the connection of the sink to the Ink Collector
HRESULT UnadviseInkCollector()
{
    HRESULT hr = m_pIConnectionPoint->Unadvise(m_dwCookie);m_pIConnectionPoint->Release();
m_pIConnectionPoint = NULL;
    return hr;
}

Definición de un controlador de eventos del recopilador de lápiz

La clase CMyInkEvents invalida el comportamiento predeterminado del controlador de eventos Stroke de la clase InkCollectorEvents. El método Stroke muestra un cuadro de mensaje cuando inkCollector recibe un evento Stroke .

class CMyInkEvents : public InkCollectorEvents
{
public:

    // Event: Stroke
    virtual void Stroke(
        IInkCursor* Cursor,
        IInkStrokeDisp* Stroke,
        VARIANT_BOOL *Cancel)
    {
        // Demonstrate that the event notification was received.
        MessageBox(m_hWnd, "Stroke Event", "Event Received", MB_OK);
    }
    
    CMyInkEvents()
    {
        m_hWnd = NULL;
    }
    
    HRESULT Init(
        HWND hWnd)
    {
        m_hWnd = hWnd;
        return InkCollectorEvents::Init();
    }    
    
    HWND m_hWnd;
};

Definición de un contenedor del recopilador de lápiz

El método Init de la clase CMyInkCollector declara e inicializa un objeto CMyInkEvents. A continuación, crea un objeto InkCollector y asocia el recopilador de tintas y el controlador de eventos. Por último, InkCollector se adjunta a la ventana y está habilitada.

// Handle all initialization
HRESULT Init(
HWND hWnd)
{
    // Initialize event sink. This consists of setting
    //  up the free threaded marshaler.
    HRESULT hr = m_InkEvents.Init(hWnd);

    if (FAILED(hr))
        ...

    // Create the ink collector
    hr = CoCreateInstance(CLSID_InkCollector, NULL, CLSCTX_ALL, IID_IInkCollector, (void **) &m_pInkCollector);

    if (FAILED(hr))
        ...

    // Set up connection between Ink Collector and our event sink
    hr = m_InkEvents.AdviseInkCollector(m_pInkCollector);

    if (FAILED(hr))
        ...

    // Attach Ink Collector to window
    hr = m_pInkCollector->put_hWnd((long) hWnd);

    if (FAILED(hr))
        ...

    // Allow Ink Collector to receive input.
    return m_pInkCollector->put_Enabled(VARIANT_TRUE);
}

Acceso a las interfaces de PC tablet y a las clases contenedoras

En primer lugar, incluya los encabezados para las interfaces de Automatización de PC tablet. Se instalan con el tipo de entidad de Microsoft<="reg"/> Windows<entity type="reg"/> XP Tablet PC Development Kit 1.7.

#include <msinkaut.h>
#include <msinkaut_i.c>

A continuación, incluya los encabezados de las clases contenedoras y se definió el controlador de eventos InkCollector .

#include "TpcConpt.h"
#include "EventSink.h"

Llamar a las clases contenedoras

Cuando se crea la ventana, el procedimiento Window crea un contenedor del recopilador de tintas e inicializa el contenedor. Cuando se destruye la ventana, el procedimiento Window elimina el contenedor del recopilador de tintas. El contenedor del recopilador de tinta controla la creación y eliminación de su controlador de eventos asociado.

case WM_CREATE:

    // Allocate and initialize memory for object
    pmic = new CMyInkCollector();

    if (pmic != NULL)
    {
        // Real initialization. This consists of creating
        //  an ink collector object and attaching it to
        //  the current window. 
        if (SUCCEEDED(pmic->Init(hWnd)))
        {
            return 0;
        }
        
        // Failure free resources.
        delete pmic;
        pmic = NULL;
    }
    
    return -1;
...
case WM_DESTROY:
    // The destructor for the object handles releasing the
    //  InkCollector and disconnecting the InkCollector
    //  from the object's event sink. 
    delete pmic;
    pmic = NULL;
    PostQuitMessage(0);
    break;