Поделиться через


Пример приемников событий C++

В этой программе показано, как создать приложение, которое записывает события InkCollector только с помощью C++. Эта программа создает объект InkCollector для рукописного ввода и включения окна. При получении события Stroke отображается окно сообщения.

Определение программы-оболочки для событий сборщика рукописного ввода

Класс InkCollectorEvents обрабатывает передачу событий сборщика рукописного ввода от сборщика рукописного ввода пользователю этого класса. Метод AdviseInkCollector настраивает соединение между объектом InkCollector и этим классом . Метод Invoke преобразует уведомление о событии IDispatch в вызов виртуальной функции, которую пользователь этого класса может переопределить для обработки определенного события.

Примечание

Чтобы получить это событие, необходимо не только переопределить виртуальную функцию для обработчика событий. Для всех событий, кроме событий по умолчанию, необходимо вызвать метод SetEventInterest сборщика рукописного ввода, чтобы гарантировать получение события. Во-вторых, этот объект маршалирует себя в свободном потоке, поэтому все реализованные обработчики событий также должны быть свободными потоками. Особое значение имеет использование API Windows, что может привести к переключении на другой поток, так как обработчик событий не гарантированно будет работать в том же потоке, что и окно, подключенное к сборщику рукописного ввода.

 

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

Метод Init вызывает CoCreateFreeThreadedMarshaler , чтобы настроить маршалер со свободным потоком.

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

Метод AdviseInkCollector настраивает соединение между объектом InkCollector и этим классом . Сначала он получает точку подключения к сборщику рукописного ввода. Затем он получает указатель на IInkCollectorEvents , чтобы установить консультативное соединение с элементом управления.

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

Метод UnadviseInkCollector освобождает подключения объекта к элементу управления .

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

Определение обработчика событий сборщика рукописного ввода

Класс CMyInkEvents переопределяет поведение по умолчанию обработчика событий Stroke класса InkCollectorEvents. Метод Stroke отображает окно сообщения, когда InkCollector получает событие 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;
};

Определение оболочки сборщика рукописного ввода

Метод Init класса CMyInkCollector объявляет и инициализирует объект CMyInkEvents. Затем он создает объект InkCollector и связывает сборщик рукописного ввода и обработчик событий. Наконец, InkCollector присоединяется к окну и включается.

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

Доступ к интерфейсам планшетного ПК и классам-оболочкам

Во-первых, добавьте заголовки для интерфейсов автоматизации планшетного ПК. Они устанавливаются с microsoft<entity type="reg"/> Windows<entity type="reg"/> XP Tablet PC Edition Development Kit 1.7.

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

Затем включите заголовки для классов-оболочек и определен обработчик событий InkCollector .

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

Вызов классов-оболочек

При создании окна процедура Window создает оболочку сборщика рукописного ввода и инициализирует оболочку. При уничтожении окна процедура Window удаляет оболочку сборщика рукописного ввода. Оболочка сборщика рукописного ввода обрабатывает создание и удаление связанного обработчика событий.

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;