Share via


C++ イベント シンクのサンプル

このプログラムでは、C++ のみを使用して InkCollector イベントをキャプチャするアプリケーションを構築する方法を示します。 このプログラムでは、 InkCollector オブジェクトを共同作成して、ウィンドウを ink -enable にします。 Stroke イベントを受信するたびにメッセージ ボックスが表示されます。

インク コレクター イベントのラッパーの定義

クラスは InkCollectorEvents 、インク コレクターからこのクラスのユーザーにインク コレクター イベントを渡す処理を行います。 メソッドは AdviseInkCollectorInkCollector オブジェクトとこのクラスの間の接続を設定します。 メソッドは InvokeIDispatch イベント通知を、このクラスのユーザーが特定のイベントを処理するためにオーバーライドできる仮想関数の呼び出しに変換します。

Note

そのイベントを取得するには、イベント ハンドラーの仮想関数をオーバーライドする以外の操作を行う必要があります。 既定のイベントを除くすべてのイベントについて、インク コレクターの SetEventInterest メソッドを呼び出して、イベントの取得を保証する必要があります。 次に、このオブジェクトはそれ自体をフリー スレッドでマーシャリングするため、実装されているすべてのイベント ハンドラーもフリー スレッドである必要があります。 特に重要なのは Windows API を使用することです。これにより、イベント ハンドラーがインク コレクターに接続されているウィンドウと同じスレッドで実行されるとは限らないため、別のスレッドに切り替える可能性があります。

 

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

メソッドは InitCoCreateFreeThreadedMarshaler を呼び出して、フリー スレッド マーシャラーを設定します。

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

メソッドは AdviseInkCollectorInkCollector オブジェクトとこのクラスの間の接続を設定します。 最初に、インク コレクターへの接続ポイントを取得します。 次に、 へのポインターを 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 クラスは、InkCollectorEvents クラスの Stroke イベント ハンドラーの既定の動作をオーバーライドします。 Stroke メソッドは、 InkCollectorStroke イベントを受信したときにメッセージ ボックスを表示します。

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

インク コレクター ラッパーの定義

CMyInkCollector クラスの Init メソッドは、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);
}

タブレット PC インターフェイスとラッパー クラスへのアクセス

最初に、タブレット PC オートメーション インターフェイスのヘッダーを含めます。 これらは、Microsoft<エンティティ type="reg"/> Windows<エンティティ 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;