다음을 통해 공유


C++ 이벤트 싱크 샘플

이 프로그램은 C++만 사용하여 InkCollector 이벤트를 캡처하는 애플리케이션을 빌드하는 방법을 보여 줍니다. 이 프로그램은 InkCollector 개체를 공동 만들어 잉크로 창을 사용하도록 설정합니다. Stroke 이벤트가 수신될 때마다 메시지 상자가 표시됩니다.

잉크 수집기 이벤트에 대한 래퍼 정의

클래스는 InkCollectorEvents 잉크 수집기에서 이 클래스의 사용자에게 잉크 수집기 이벤트를 전달하는 것을 처리합니다. 메서드는 AdviseInkCollectorInkCollector 개체와 이 클래스 간의 연결을 설정합니다. 메서드는 InvokeIDispatch 이벤트 알림을 이 클래스의 사용자가 특정 이벤트를 처리하기 위해 재정의할 수 있는 가상 함수 호출로 변환합니다.

참고

해당 이벤트를 얻으려면 이벤트 처리기에 대한 가상 함수를 재정의하는 것 이상을 수행해야 합니다. 기본 이벤트를 제외한 모든 이벤트의 경우 이벤트 가져오기를 보장하기 위해 잉크 수집기 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 개발 키트 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;