使用Firemonkey中的TTreeView拖放

时间:2018-01-08 22:21:53

标签: drag-and-drop treeview firemonkey c++builder c++builder-10.2-tokyo

我正在使用C ++ Builder 10.2.2 Tokyo和FireMonkey(FMX)。

我想将拖放功能添加到TTreeView,因此用户可以重新排列树项的顺序。我已根据this Drag and Drop sample projectTTreeView.OnMouseDown事件添加了处理程序。

有了这个,程序现在可以拖放以重新排列项目,但似乎有一些默认行为可以将TTreeViewItem移动到它被放到的TTreeViewItem的子项上,而不是在该项目之后插入。

如何覆盖此默认行为,以便在TTreeViewItem中的同一级别插入TTreeView,并且在大于TTreeViewItem的索引1处将其放入ap response.to_h

1 个答案:

答案 0 :(得分:1)

根据Abdullah的建议,您可以通过创建自定义组件来实现这一目标。一般来说,创建客户组件的方向是here。我建议将它安装在Tool Palette的Standard中,就像TTreeView所在的那样。

自定义组件(此处称为TMyTreeView)特别在标题中包含此内容:

class PACKAGE TMyTreeView : public TTreeView
{
private:
    bool IsAncestor (TTreeViewItem* oItem, TTreeViewItem* oTargetItem);
protected:
    int DragDelta;
    void StartDrag ();
    void __fastcall DragDrop (const Fmx::Types::TDragObject &Data, const System::Types::TPointF &Point);
    void __fastcall MouseDown (System::Uitypes::TMouseButton Button, System::Classes::TShiftState Shift, float X, float Y);
    void __fastcall MouseMove (System::Classes::TShiftState Shift, float X, float Y);
public:
    __fastcall TMyTreeView(TComponent* Owner);
    __fastcall ~TMyTreeView ();
    TBitmap* DragBmp;
    TPointF MouseDownPoint;
    TTreeViewItem* DragStartItem;
__published:

};
//---------------------------------------------------------------------------

其中的函数在相应的cpp文件中如下:

    __fastcall TMyTreeView::TMyTreeView(TComponent* Owner)
    : TTreeView(Owner)
{
    DragBmp = NULL;
    DragStartItem = NULL;
    DragDelta = 5;
}
//---------------------------------------------------------------------------

__fastcall TMyTreeView::~TMyTreeView ()
{
    if (DragBmp)
        delete DragBmp;
}
//---------------------------------------------------------------------------

void __fastcall TMyTreeView::MouseMove (System::Classes::TShiftState Shift, float X, float Y)
{
    TTreeView::MouseMove (Shift, X, Y);

    if ((abs (X-MouseDownPoint.X) > DragDelta) || (abs (Y-MouseDownPoint.Y) > DragDelta))
        StartDrag ();
}
//---------------------------------------------------------------------------

void TMyTreeView::StartDrag ()
{
    if (!AllowDrag)
        return;
    if (!DragStartItem)
        return;

    if (DragBmp)
        delete DragBmp;

    _di_IFMXDragDropService service;
    if ((TPlatformServices::Current->SupportsPlatformService (__uuidof(IFMXDragDropService)) &&
        (service = TPlatformServices::Current->GetPlatformService (__uuidof(IFMXDragDropService)))))
    {
        TDragObject dragData;
        if (!DragStartItem)
            return;
        dragData.Source = DragStartItem;
        DragBmp = DragStartItem->MakeScreenshot ();
        dragData.Data = DragBmp;
        service->BeginDragDrop  ((TForm*)this->Owner, dragData, DragBmp);
        DragStartItem = NULL;
    }

}
//---------------------------------------------------------------------------

void __fastcall TMyTreeView::MouseDown (System::Uitypes::TMouseButton Button, System::Classes::TShiftState Shift, float X, float Y)
{
    TTreeView::MouseDown (Button, Shift, X, Y);

    if (AllowDrag)
    {
        DragStartItem = ItemByPoint (X, Y);
        MouseDownPoint.X = X;
        MouseDownPoint.Y = Y;
    }
    else
        DragStartItem = NULL;
}
//---------------------------------------------------------------------------

void __fastcall TMyTreeView::DragDrop (const Fmx::Types::TDragObject &Data, const System::Types::TPointF &Point)
{
    TTreeViewItem* item = ItemByPoint (Point.X, Point.Y);
    if (!item)
        return;

    TTreeViewItem* srcItem = (TTreeViewItem*)Data.Source;
    if (!srcItem)
        return;

    if (IsAncestor (srcItem, item))
        return;

    if (item->ParentItem ())
        item->ParentItem ()->InsertObject (item->Index, srcItem);
    else
        this->InsertObject (item->Index, srcItem);

    //TTreeView::DragDrop (Data, Point);
}
//---------------------------------------------------------------------------

bool TMyTreeView::IsAncestor (TTreeViewItem* oItem, TTreeViewItem* oTargetItem)
{
    for (int i=0; i<oItem->Count; i++)
    {
        TTreeViewItem* item = oItem->Items [i];
        if (item == oTargetItem)
            return true;
        if (IsAncestor (item, oTargetItem))
            return true;
    }
    return false;
}
//---------------------------------------------------------------------------

将自定义组件安装到工具选项板后,您可以像添加任何其他组件一样将其添加到表单中。

特别感谢Mike Sutton,他有代码修改了早期版本的TTreeView here

添加到表单后,将TMyTreeView控件的AllowDrag设置为true。