Freigeben über


Beispiel für C++-Ereignissenken

Dieses Programm veranschaulicht, wie Sie eine Anwendung erstellen können, die InkCollector-Ereignisse nur mit C++ erfasst. Dieses Programm erstellt gemeinsam ein InkCollector-Objekt , um das Fenster freizugeben. Es wird ein Meldungsfeld angezeigt, wenn ein Stroke-Ereignis empfangen wird.

Definieren eines Wrappers für Freihandsammlerereignisse

Die InkCollectorEvents Klasse verarbeitet das Übergeben von Freihandsammlerereignissen vom Freihandsammler an den Benutzer dieser Klasse. Die AdviseInkCollector -Methode richtet die Verbindung zwischen dem InkCollector-Objekt und dieser Klasse ein. Die Invoke -Methode konvertiert die IDispatch-Ereignisbenachrichtigung in einen Aufruf einer virtuellen Funktion, die der Benutzer dieser Klasse überschreiben kann, um ein bestimmtes Ereignis zu verarbeiten.

Hinweis

Sie müssen mehr als die virtuelle Funktion überschreiben, damit ein Ereignishandler dieses Ereignis abrufen kann. Für alle Ereignisse mit Ausnahme der Standardereignisse müssen Sie die SetEventInterest-Methode des Freihandsammlers aufrufen, um das Abrufen eines Ereignisses zu gewährleisten. Zweitens marshallt dieses Objekt selbst einen freien Thread, sodass alle implementierten Ereignishandler ebenfalls frei threaded sein müssen. Von besonderer Bedeutung ist die Verwendung von Windows-APIs, die zu einem Wechsel zu einem anderen Thread führen kann, da nicht garantiert wird, dass der Ereignishandler im selben Thread ausgeführt wird wie das Fenster, das mit dem Freihandsammler verbunden ist.

 

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

Die Init -Methode ruft CoCreateFreeThreadedMarshaler auf, um einen free threaded marshaler einzurichten.

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

Die AdviseInkCollector -Methode richtet die Verbindung zwischen dem InkCollector-Objekt und dieser Klasse ein. Zuerst wird ein Verbindungspunkt mit dem Freihandsammler abgerufen. Anschließend wird ein Zeiger auf das IInkCollectorEvents abgerufen, damit eine Beratende Verbindung mit dem Steuerelement hergestellt werden kann.

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

Die UnadviseInkCollector -Methode gibt die Verbindungen frei, die das Objekt mit dem -Steuerelement hat.

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

Definieren eines Freihandsammler-Ereignishandlers

Die CMyInkEvents-Klasse setzt das Standardverhalten des Stroke-Ereignishandlers der InkCollectorEvents-Klasse außer Kraft. Die Stroke-Methode zeigt ein Meldungsfeld an, wenn der InkCollector ein Stroke-Ereignis empfängt.

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

Definieren eines Freihandsammler-Wrappers

Die Init-Methode der CMyInkCollector-Klasse deklariert und initialisiert ein CMyInkEvents-Objekt. Anschließend wird ein InkCollector-Objekt erstellt und dem Freihandsammler und dem Ereignishandler zugeordnet. Schließlich wird der InkCollector an das Fenster angefügt und aktiviert.

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

Zugreifen auf die Tablet-PC-Schnittstellen und die Wrapperklassen

Fügen Sie zunächst die Header für Tablet PC Automation-Schnittstellen ein. Diese werden mit dem Microsoft<entity type="reg"/> Windows<entity type="reg"/> XP Tablet PC Edition Development Kit 1.7 installiert.

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

Schließen Sie dann die Header für die Wrapperklassen ein, und der InkCollector-Ereignishandler wurde definiert.

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

Aufrufen der Wrapperklassen

Wenn das Fenster erstellt wird, erstellt die Window-Prozedur einen Freihandsammler-Wrapper und initialisiert den Wrapper. Wenn das Fenster zerstört wird, löscht die Window-Prozedur den Freihandsammler-Wrapper. Der Freihandsammler-Wrapper übernimmt das Erstellen und Löschen des zugeordneten Ereignishandlers.

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;