SDK Index Previous page Next page

OLE DragDrop (IDropSourceの実装)


4つのクラスの役割

前回、各クラスの役割を書くのを忘れていたので最初に書いておきます。

CDropTarget

CDropTargetはドラッグ&ドロップを受ける側が用意するクラスです。RegisterDragDropを使ってウインドウにCDropTargetを設定するとドラッグ中のマウスがウインドウに入ってきたりしたときに、CDropTargetのメンバ関数が呼ばれるようになります。

CDropSource

CDropSourceは逆にドラッグ&ドロップを開始する側が用意するクラスです。DoDragDropにこのクラスとCDataObjectクラスを渡すことでドラッグ&ドロップを始めることが出来ます。

CDataObject

ドラッグするデータを操作するクラスです。データを受け取る側では、このクラスを使ってどのようなデータがドロップされたか判断したりそのデータを取得したりします。逆にデータを送る側ではこのクラスにデータを格納しておきます。データはクリップボードを使うときと同じ形で作ります。データ自体は最初から作っておく必要はなく、データを要求されたとき(GetData)に作ってもかまいません。その辺は好みです。

EnumFORMATETC

CDataObjectのEnumFormatEtcメンバを使うと取得できるクラスで、CDataObjectが持っているデータの形式をリストのように扱うことが出来ます。たいていCDataObjectだけで事足りるのでこれを使うことは余りないと思いますが・・・・。

CDropSourceを作る

今回はCDropSourceの作り方を説明します。ドラッグ&ドロップで他のウインドウにデータを渡したいときは、最低このクラスとCDataObjectを作らないといけません。CEnumFORMATETCは無くても何とかなるでしょう。

作らないといけない仮想関数は
 QueryInterface
 AddRef
 Release
 QueryContinueDrag
 GiveFeedback
の5つです。

最初の3つはCDropTargetと同じなので、実際は2つだけ作ればOKです。

クラス定義

とりあえずクラス定義の部分だけ先に書いておきます。
class CDropSource : public IDropSource
{
  public:
    CDropSource() : _RefCount(1){};
    ~CDropSource(){};

    virtual HRESULT __stdcall QueryInterface(const IID& iid, void** ppv);
    virtual ULONG __stdcall AddRef(void);
    virtual ULONG __stdcall Release(void);

    virtual HRESULT __stdcall QueryContinueDrag(BOOL fEscapePressed, DWORD grfKeyState);
    virtual HRESULT __stdcall GiveFeedback(DWORD dwEffect);

  private:
    LONG _RefCount;
};

QueryContineDrag

キーやマウスボタンの状態をみて、ドラッグを続けるかやめるかを決める関数です。
HRESULT __stdcall CDropSource::QueryContinueDrag(BOOL fEscapePressed, DWORD grfKeyState)
{
    /* ドラッグを継続するかどうかを決める */

    /* ESCが押された場合やマウスのボタンが両方押されたときは中止 */
    if(fEscapePressed || (MK_LBUTTON | MK_RBUTTON) == (grfKeyState & (MK_LBUTTON | MK_RBUTTON))){
        return DRAGDROP_S_CANCEL;
    }

    /* マウスボタンが離されたときはドロップ */
    if((grfKeyState & (MK_LBUTTON | MK_RBUTTON)) == 0){
        return DRAGDROP_S_DROP;
    }
    return S_OK;
}

GiveFeedback

マウスカーソルの形状を変えたり、特殊効果を出したりするための関数です。あんましよく分かってません。まあDRAGDROP_S_USEDEFAULTCURSORSを返しておけばあとはWindwosが勝手にやってくれます。
HRESULT __stdcall CDropSource::GiveFeedback(DWORD dwEffect)
{
    /* マウスカーソルを変えたり、特別な表示をするときはここで行う */

    //標準のマウスカーソルを使う
    return DRAGDROP_S_USEDEFAULTCURSORS;
}

おわりに

IDropSourceはこれだけです。実に簡単です。

to sdk prev next