我正在使用C ++ Builder 10.2.2 Tokyo和FireMonkey(FMX)。
我想将拖放功能添加到TTreeView
,因此用户可以重新排列树项的顺序。我已根据this Drag and Drop sample project为TTreeView.OnMouseDown
事件添加了处理程序。
有了这个,程序现在可以拖放以重新排列项目,但似乎有一些默认行为可以将TTreeViewItem
移动到它被放到的TTreeViewItem
的子项上,而不是在该项目之后插入。
如何覆盖此默认行为,以便在TTreeViewItem
中的同一级别插入TTreeView
,并且在大于TTreeViewItem
的索引1处将其放入ap response.to_h
?
答案 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。