Compartilhar via


Exemplo de coletores de eventos C++

Este programa demonstra como você pode criar um aplicativo que captura eventos InkCollector usando apenas C++. Este programa co-cria um objeto InkCollector para a tinta - habilite a janela. Ele exibe uma caixa de mensagem sempre que um evento stroke é recebido.

Definindo um wrapper para eventos do coletor de tinta

A InkCollectorEvents Classe manipula a passagem de eventos do coletor de tinta do coletor de tinta para o usuário dessa classe. O AdviseInkCollector método configura a conexão entre o objeto InkCollector e essa classe. O Invoke método converte a notificação de evento IDispatch em uma chamada para uma função virtual que o usuário dessa classe pode substituir para processar um evento específico.

Observação

Você deve fazer mais do que substituir a função virtual de um manipulador de eventos para obter esse evento. Para todos os eventos, exceto o padrão, você precisa chamar o método SetEventInterest do coletor de tinta para garantir a obtenção de um evento. Em segundo lugar, esse objeto realiza marshaling livre de threads para que todos os manipuladores de eventos implementados também precisem ser encadeados livres. De particular importância está o uso de APIs do Windows, o que pode fazer com que uma opção para outro thread, pois o manipulador de eventos não está sendo executado no mesmo thread que a janela conectada com o coletor de tinta.

 

// 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;
}
...

O Init método chama CoCreateFreeThreadedMarshaler para configurar um marshaler threaded gratuito.

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

O AdviseInkCollector método configura a conexão entre o objeto InkCollector e essa classe. Primeiro, ele recupera um ponto de conexão para o coletor de tinta. Em seguida, ele recupera um ponteiro para o IInkCollectorEvents para que ele possa estabelecer uma conexão de consultoria com o controle.

// 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;
}

O UnadviseInkCollector método libera as conexões que o objeto tem com o controle .

// 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;
}

Definindo um manipulador de eventos do coletor de tinta

A classe CMyInkEvents substitui o comportamento padrão do manipulador de eventos Stroke da classe InkCollectorEvents. O método Stroke exibe uma caixa de mensagem quando o InkCollector recebe um 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;
};

Definindo um wrapper de coletor de tinta

O método Init da Classe CMyInkCollector declara e inicializa um objeto CMyInkEvents. Em seguida, ele cria um objeto InkCollector e associa o coletor de tinta e o manipulador de eventos. Por fim, o InkCollector está anexado à janela e habilitado.

// 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);
}

Acessando as interfaces do tablet pc e as classes wrapper

Primeiro, inclua os cabeçalhos para interfaces de Automação de TABLET PC. Eles são instalados com o<microsoft entity type="reg"/> Windows<entity type="reg"/> XP Tablet PC Edition Development Kit 1.7.

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

Em seguida, inclua os cabeçalhos para as classes wrapper e o manipulador de eventos InkCollector foi definido.

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

Chamando as classes wrapper

Quando a janela é criada, o procedimento Window cria um wrapper de coletor de tinta e inicializa o wrapper. Quando a janela é destruída, o procedimento Window exclui o wrapper do coletor de tinta. O wrapper do coletor de tinta manipula a criação e a exclusão de seu manipulador de eventos associado.

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;