次の方法で共有


イベントの追加 (ATL チュートリアル、パート 5)

この手順では、ClickIn イベントと ClickOut イベントを ATL コントロールに追加します。 ユーザーが多角形の内側をクリックすると ClickIn イベントが発生し、ユーザーが外側をクリックすると ClickOut イベントが発生するようにします。 イベントを追加するタスクは次のとおりです。

  • ClickIn メソッドと ClickOut メソッドの追加

  • タイプ ライブラリの生成

  • 接続ポイント インターフェイスの実装

ClickIn メソッドと ClickOut メソッドの追加

手順 2 で ATL コントロールを作成したときに、[接続ポイント] チェック ボックスをオンにしました。 これにより、Polygon.idl ファイルに _IPolyCtlEvents インターフェイスが作成されました。 インターフェイス名はアンダースコアで始まります。 これは、インターフェイスが内部インターフェイスであることを示すための規則です。 したがって、COM オブジェクトを参照できるプログラムでは、インターフェイスをユーザーに表示しないことを選択できます。 また、[接続ポイント] をオンにすることで、_IPolyCtlEvents が既定のソース インターフェイスであることを示す次の行が Polygon.idl ファイルに追加されました。

[default, source] dispinterface _IPolyCtlEvents;

source 属性は、コントロールが通知のソースであることを示しているので、コンテナーでこのインターフェイスが呼び出されます。

ここで、ClickIn メソッドと ClickOut メソッドを _IPolyCtlEvents インターフェイスに追加します。

ClickIn メソッドと ClickOut メソッドを追加するには

  1. ソリューション エクスプローラーで Polygon.idl を開き、PolygonLib ライブラリの dispInterface_IPolyCtlEvents 宣言内の methods: の下に次のコードを追加します。

    [id(1), helpstring("method ClickIn")] void ClickIn([in] LONG x,[in] LONG y);
    [id(2), helpstring("method ClickOut")] void ClickOut([in] LONG x,[in] LONG y);
    

ClickIn メソッドと ClickOut メソッドは、クリックされた点の X 座標と Y 座標をパラメーターとして取得します。

タイプ ライブラリの生成

この時点で、タイプ ライブラリを生成します。これは、プロジェクトでこのライブラリを使用して、コントロールに対して接続ポイント インターフェイスと接続ポイント コンテナー インターフェイスを作成するのに必要な情報を取得するためです。

タイプ ライブラリを生成するには

  1. プロジェクトのリビルドします。

    または

  2. ソリューション エクスプローラーで Polygon.idl ファイルを右クリックし、ショートカット メニューの [コンパイル] をクリックします。

これにより、タイプ ライブラリである Polygon.tlb ファイルが作成されます。 Polygon.tlb ファイルはバイナリ ファイルであり、直接表示または編集できないため、ソリューション エクスプローラーからは参照できません。

接続ポイント インターフェイスの実装

コントロールの接続ポイント インターフェイスと接続ポイント コンテナー インターフェイスを実装します。 COM では、接続ポイントのメカニズムによってイベントが実装されます。 COM オブジェクトからイベントを受信するために、コンテナーでは、COM オブジェクトによって実装される接続ポイントへのアドバイザリ コネクションが確立されます。 COM オブジェクトは複数の接続ポイントを持つことができるため、COM オブジェクトでは接続ポイント コンテナー インターフェイスも実装されます。 コンテナーでは、このインターフェイスを使用して、サポートされている接続ポイントを特定できます。

接続ポイントを実装するインターフェイスは IConnectionPoint と呼ばれ、接続ポイント コンテナーを実装するインターフェイスは IConnectionPointContainer と呼ばれます。

IConnectionPoint を実装するには、接続ポイントの実装ウィザードを使用します。 このウィザードでは、タイプ ライブラリを読み取り、発生する可能性のある各イベントに対して関数を実装することで、IConnectionPoint インターフェイスを生成します。

接続ポイントを実装するには

  1. ソリューション エクスプローラーで _IPolyCtlEvents_CP.h を開き、CProxy_IPolyCtlEvents クラスの public: ステートメントの下に次のコードを追加します。

    VOID Fire_ClickIn(LONG x, LONG y)
    {
        T* pT = static_cast<T*>(this);
        int nConnectionIndex;
        CComVariant* pvars = new CComVariant[2];
        int nConnections = m_vec.GetSize();
    
        for (nConnectionIndex = 0; nConnectionIndex < nConnections; nConnectionIndex++)
        {
            pT->Lock();
            CComPtr<IUnknown> sp = m_vec.GetAt(nConnectionIndex);
            pT->Unlock();
            IDispatch* pDispatch = reinterpret_cast<IDispatch*>(sp.p);
            if (pDispatch != NULL)
            {
                pvars[1].vt = VT_I4;
                pvars[1].lVal = x;
                pvars[0].vt = VT_I4;
                pvars[0].lVal = y;
                DISPPARAMS disp = { pvars, NULL, 2, 0 };
                pDispatch->Invoke(0x1, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_METHOD, &disp, NULL, NULL, NULL);
            }
        }
        delete[] pvars;
    
    }
    VOID Fire_ClickOut(LONG x, LONG y)
    {
        T* pT = static_cast<T*>(this);
        int nConnectionIndex;
        CComVariant* pvars = new CComVariant[2];
        int nConnections = m_vec.GetSize();
    
        for (nConnectionIndex = 0; nConnectionIndex < nConnections; nConnectionIndex++)
        {
            pT->Lock();
            CComPtr<IUnknown> sp = m_vec.GetAt(nConnectionIndex);
            pT->Unlock();
            IDispatch* pDispatch = reinterpret_cast<IDispatch*>(sp.p);
            if (pDispatch != NULL)
            {
                pvars[1].vt = VT_I4;
                pvars[1].lVal = x;
                pvars[0].vt = VT_I4;
                pvars[0].lVal = y;
                DISPPARAMS disp = { pvars, NULL, 2, 0 };
                pDispatch->Invoke(0x2, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_METHOD, &disp, NULL, NULL, NULL);
            }
        }
        delete[] pvars;
    
    }
    

このファイルには、IConnectionPointImpl から派生した CProxy_IPolyCtlEvents というクラスが含まれていることがわかります。 これで _IPolyCtlEvents_CP.h には、2 つのメソッド Fire_ClickInFire_ClickOut が定義されます。これらは 2 つの座標パラメーターを受け取ります。 コントロールからイベントを発生させるには、これらのメソッドを呼び出します。

[接続ポイント] オプションを選択してコントロールを作成することで、_IPolyCtlEvents_CP.h ファイルが自動的に生成されました。 また、適切なエントリを COM マップに追加することで、自動的に CProxy_PolyEventsIConnectionPointContainerImpl がコントロールの複数の継承リストに追加され、IConnectionPointContainer が公開されました。

イベントをサポートするコードの実装が完了しました。 ここで、適切な時点でイベントを発生させるコードをいくつか追加します。 ユーザーがコントロールでマウスの左ボタンをクリックすると、ClickIn イベントまたは ClickOut イベントが発生するようにします。 ユーザーがボタンをクリックしたことを認識できるように、WM_LBUTTONDOWN メッセージのハンドラーを追加します。

WM_LBUTTONDOWN メッセージのハンドラーを追加するには

  1. クラス ビューCPolyCtl クラスを右クリックし、ショートカット メニューの [プロパティ] をクリックします。

  2. [プロパティ] ウィンドウで、[メッセージ] アイコンをクリックし、左側の一覧で WM_LBUTTONDOWN をクリックします。

  3. 表示されるドロップダウン リストで、[<Add> OnLButtonDown] をクリックします。 OnLButtonDown ハンドラーの宣言が PolyCtl.h に追加され、ハンドラーの実装が PolyCtl.cpp に追加されます。

次に、ハンドラーを変更します。

OnLButtonDown メソッドを変更するには

  1. 次のように、PolyCtl.cpp の OnLButtonDown メソッドで構成されるコードを変更します (ウィザードによって配置されたコードをすべて削除します)。

    LRESULT CPolyCtl::OnLButtonDown(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, 
       BOOL& /*bHandled*/)
    {
       HRGN hRgn;
       WORD xPos = LOWORD(lParam);  // horizontal position of cursor
       WORD yPos = HIWORD(lParam);  // vertical position of cursor
    
       CalcPoints(m_rcPos);
    
       // Create a region from our list of points
       hRgn = CreatePolygonRgn(&m_arrPoint[0], m_nSides, WINDING);
    
       // If the clicked point is in our polygon then fire the ClickIn
       //  event otherwise we fire the ClickOut event
       if (PtInRegion(hRgn, xPos, yPos))
          Fire_ClickIn(xPos, yPos);
       else
          Fire_ClickOut(xPos, yPos);
    
       // Delete the region that we created
       DeleteObject(hRgn);
       return 0;
    }
    

このコードでは、OnDraw 関数で計算されたポイントを使用して、PtInRegion の呼び出しによってユーザーのマウス クリックを検出する領域を作成します。

uMsg パラメーターは、処理される Windows メッセージの ID です。 これにより、一連のメッセージを処理する 1 つの関数を使用できます。 wParam パラメーターと lParam パラメーターは、処理されるメッセージの標準値です。 bHandled パラメーターを使用すると、関数によってメッセージが処理されたかどうかを指定できます。 既定でこの値は、関数によってメッセージが処理されたことを示す TRUE に設定されますが、FALSE に設定することもできます。 これにより、メッセージの送信先である別のメッセージ ハンドラー関数の検索が ATL によって続行されます。

コントロールのビルドとテスト

次に、イベントを試してみましょう。 コントロールをビルドし、ActiveX コントロール テスト コンテナーを再び開始します。 今回は、イベント ログ ウィンドウを表示します。 イベントを出力ウィンドウにルーティングするには、[オプション] メニューの [ログ] をクリックし、[出力ウィンドウにログを記録] を選択します。 コントロールを挿入し、ウィンドウ内をクリックしてみます。 塗りつぶされた多角形の内側をクリックすると ClickIn が起動され、その外側をクリックすると ClickOut が起動されます。

次に、プロパティ ページを追加します。

手順 4 に戻る | 手順 6 に進む

関連項目

チュートリアル