次の方法で共有


ツリー ビュー項目をドラッグする方法

このトピックでは、ツリー ビュー項目のドラッグ アンド ドロップを処理するコードを示します。 このサンプル コードは、3 つの関数で構成されています。 1 つ目の関数はドラッグ操作を開始し、2 つ目の関数は画像をドラッグし、3 つ目の関数はドラッグ操作を終了します。

Note

ツリー ビュー項目がドラッグされると、通常は TVN_BEGINDRAG (または TVN_BEGINRDRAG) 通知コード、WM_MOUSEMOVE メッセージ、および WM_LBUTTONUP (または WM_RBUTTONUP) メッセージの処理が必要になります。 また、項目がドラッグされているかのように描画するために、画像リスト関数も使用します。

 

知っておくべきこと

テクノロジ

前提条件

  • C/C++
  • Windows ユーザー インターフェイス プログラミング

手順

手順 1: ツリー ビューのドラッグ操作を開始する

ツリー ビュー コントロールは、ユーザーが項目のドラッグを開始すると常に、親ウィンドウに TVN_BEGINDRAG (または TVN_BEGINRDRAG) 通知コードを送信します。 親ウィンドウは、この通知を WM_NOTIFY メッセージの形式で受信しますが、その lParam パラメーターが NMTREEVIEW 構造体のアドレスです。 この構造体のメンバーには、マウス ポインターの画面座標と、ドラッグされる項目に関する情報を含む TVITEM 構造体が含まれます。

次の例は、WM_NOTIFY メッセージを処理して TVN_BEGINDRAG を取得する方法を示しています。

    case WM_NOTIFY: 
        switch (((LPNMHDR)lParam)->code) 
        {
            case TVN_BEGINDRAG:
                Main_OnBeginDrag(((LPNMHDR)lParam)->hwndFrom, (LPNMTREEVIEW)lParam);
                break;
        
            // Handle other cases here. 
        }
        break; 

ドラッグ操作の開始では、ImageList_BeginDrag 関数が使用されます。 この関数のパラメーターには、ドラッグ操作中に使用する画像および画像のインデックスを含む、画像リストのハンドルが含まれます。 独自のリストと画像を提供できます。または、TVM_CREATEDRAGIMAGE メッセージを使用して、ツリー ビュー コントロールにリストと画像を作成させることもできます。

ドラッグ操作の継続中はドラッグ画像でマウス ポインターが置き換えられるため、ImageList_BeginDrag では、画像内のホット スポットを指定する必要があります。 ホット スポットの座標は、画像の左上隅に対する相対位置です。 ImageList_BeginDrag では、ドラッグ画像の初期位置も指定する必要があります。 アプリケーションは通常、ユーザーがドラッグ操作を開始した時点で、ドラッグ画像のホット スポットがマウス ポインターのホット スポットに対応するように初期位置を設定します。

次の関数は、ツリー ビュー項目のドラッグを開始する方法を示しています。 この関数は、ツリー ビュー コントロールによって提供されたドラッグ画像を使用し、項目の境界となる四角形を取得して、ホット スポットの適切なポイントを決定します。 境界となる四角形の寸法は、画像の寸法と同じです。

この関数は、マウス入力をキャプチャし、マウス メッセージを親ウィンドウに送信します。 親ウィンドウは、画像のドラッグ先を決定するのに、後続の WM_MOUSEMOVE メッセージを必要とします。また、ドラッグ操作を終了するタイミングを決定するのに、WM_LBUTTONUP メッセージを必要とします。

// Begin dragging an item in a tree-view control. 
// hwndTV - handle to the image list. 
// lpnmtv - address of information about the item being dragged.
//
// g_fDragging -- global BOOL that specifies whether dragging is underway.

void Main_OnBeginDrag(HWND hwndTV, LPNMTREEVIEW lpnmtv)
{ 
    HIMAGELIST himl;    // handle to image list 
    RECT rcItem;        // bounding rectangle of item 

    // Tell the tree-view control to create an image to use 
    // for dragging. 
    himl = TreeView_CreateDragImage(hwndTV, lpnmtv->itemNew.hItem); 

    // Get the bounding rectangle of the item being dragged. 
    TreeView_GetItemRect(hwndTV, lpnmtv->itemNew.hItem, &rcItem, TRUE); 

    // Start the drag operation. 
    ImageList_BeginDrag(himl, 0, 0, 0);
    ImageList_DragEnter(hwndTV, lpnmtv->ptDrag.x, lpnmtv->ptDrag.x); 

    // Hide the mouse pointer, and direct mouse input to the 
    // parent window. 
    ShowCursor(FALSE); 
    SetCapture(GetParent(hwndTV)); 
    g_fDragging = TRUE; 

    return; 

} 

手順 2: ツリー ビュー項目をドラッグする

次の例に示すように、親ウィンドウが WM_MOUSEMOVE メッセージを受信したら、ImageList_DragMove 関数を呼び出すことでツリー ビュー項目をドラッグします。 この例では、ドラッグ操作中にヒット テストを実行して、ドラッグ アンド ドロップ操作のターゲットとしてツリー ビュー内の他の項目を強調表示するかどうかを決定する方法も示しています。

// Drag an item in a tree-view control, 
// highlighting the item that is the target. 
// hwndParent - handle to the parent window. 
// hwndTV - handle to the tree-view control.
// xCur and yCur - coordinates of the mouse pointer,
//     relative to the parent window. 
//
// g_fDragging - global BOOL that specifies whether dragging is underway.

void Main_OnMouseMove(HWND hwndParent, HWND hwndTV, LONG xCur, LONG yCur) 
{ 
    HTREEITEM htiTarget;  // Handle to target item. 
    TVHITTESTINFO tvht;   // Hit test information. 

    if (g_fDragging) 
    { 
       // Drag the item to the current position of the mouse pointer. 
       // First convert the dialog coordinates to control coordinates. 
       POINT point;
       point.x = xCur;
       point.y = yCur;
       ClientToScreen(hwndParent, &point);
       ScreenToClient(hwndTV, &point);
       ImageList_DragMove(point.x, point.y);
       // Turn off the dragged image so the background can be refreshed.
       ImageList_DragShowNolock(FALSE); 
                
        // Find out if the pointer is on the item. If it is, 
        // highlight the item as a drop target. 
        tvht.pt.x = point.x; 
        tvht.pt.y = point.y; 
        if ((htiTarget = TreeView_HitTest(hwndTV, &tvht)) != NULL) 
        { 
            TreeView_SelectDropTarget(hwndTV, htiTarget); 
        } 
        ImageList_DragShowNolock(TRUE);
    } 
    return; 
}

手順 3: ツリー ビューのドラッグ操作を終了する

次の例では、ドラッグ操作を終了する方法を示します。 親ウィンドウが WM_LBUTTONUP メッセージを受信すると、ImageList_EndDrag 関数が呼び出されます。 ツリー ビュー コントロールのハンドルが関数に渡されます。

// Stops dragging a tree-view item, releases the 
// mouse capture, and shows the mouse pointer.
//
// g_fDragging - global BOOL that specifies whether dragging is underway.

void Main_OnLButtonUp(HWND hwndTV) 
{ 
    if (g_fDragging) 
    { 
        // Get destination item.
        HTREEITEM htiDest = TreeView_GetDropHilight(hwndTV);
        if (htiDest != NULL)
        {
            // To do: handle the actual moving of the dragged node.
        }
        ImageList_EndDrag(); 
        TreeView_SelectDropTarget(hwndTV, NULL);
        ReleaseCapture(); 
        ShowCursor(TRUE); 
        g_fDragging = FALSE; 
    } 
    return; 
} 

ツリー ビュー コントロールの使用

CustDTv サンプルでは、ツリー ビュー コントロールのカスタム描画について説明しています