Windows中的拖放功能大家一定很熟悉了,如文件的转移,拷贝等操作用鼠标轻轻一拖即可,在编写程序中有时也用到拖放,那么如何实现呢?现以C++ Builder5(简称CB5)为例,分析拖放功能的具体实现。 一.工具条的拖放 ---- 要实现拖放功能,首先必须了解几个与拖放有关的属性和方法, 对于TControl控件,CB5提供了三个属性,DockSite,DragKind和DragMode。灵活运用这三个属性会得到意想不到的效果。这三个属性的意义是: ---- DockSite:指定当前控件是否接受Drag-and-Dock类型的操作 ---- DragKind:拖放种类,分为dkDrag和dkDock两种 ---- DragMode:拖放模式,分为自动和手动模式两种 ---- 其中Dock操作是指某控件脱离它的Parent,转而成为另一个控件的Child,也就是两个控件合并。若某一控件的DockSite为True,表明它接受执行Dock操作的某控件,并成为它的Parent。 ---- 著名的Office工具条可以随意拖放,其实实现起来很简单:在Form上放一CoolBar控件,再在CoolBar控件上随意放几个ToolBar控件,它们的属性设置代码如下: CoolBar1.DockSite=true; ToolBar1.DragKind=dkDock; ToolBar1.DragMode= dmAutomatic;
---- 其它ToolBar的属性设置与ToolBar1的属性设置相同,编译运行程序,拖动工具条试试,Cool极了吧。 二、任何两上控件间的拖放 ---- 与此操作有关的几个函数有: ---- BeginDrag:开始执行拖放操作,如果控件的DragMode为dmManual,则必须调用此函数,如果DragMode为dmAutomatic,则不用调用。 ---- OnDragOver:当被拖放的对象经过此控件时触发此事件,其中的参数Accept表示是否接受拖放的对象。 ---- OnDragDrop:当放下被拖放的对象时触发此事件。 ---- 下面举例说明拖放的实现过程: ---- 在CB5中新建一工程,在Form1上放两个ListBox,分别命名为ListBox1,ListBox2,打开ListBox1的Items属性框,随便输入几行字符串。 ---- 其属性设置如下: ListBox1->MultiSelect=true; // MultiSelect属性设为true,表示可以多选 ListBox1->DragMode= dmAutomatic; ListBox2->MultiSelect=true; ListBox2->DragMode= dmAutomatic; //两个ListBox拖放事件相同,可以互相拖放 ListBox2->OnDragOver= ListBox1DragOver; ListBox2->OnDragDrop= ListBox1DragDrop; ListBox2->OnStartDrag= ListBox1StartDrag; 在头文件中设置两个int型变量CurIndex,NewIndex 程序代码如下: //----------------------------------------------------------- #include < vcl.h > #pragma hdrstop #include "unit1.h" #include "FileCtrl.hpp" //----------------------------------------------------------- #pragma package(smart_init) #pragma resource "*.dfm" TForm1 *Form1; //---------------------------------------------------------- __fastcall TForm1::TForm1(TComponent* Owner) : TForm(Owner) { } //---------------------------------------------------------- void __fastcall TForm1::ListBox1StartDrag(TObject *Sender, TDragObject *&DragObject) { //开始执行拖放事件时记录ListBox->ItemIndex; CurIndex=((TListBox *)Sender)->ItemIndex; } //---------------------------------------------------------- void __fastcall TForm1::ListBox1DragDrop(TObject *Sender, TObject *Source, int X, int Y) { int index; if(Sender==Source) //如果Sender等于Source,表明在同一控件内执行操作,本例用来交换ListBox中的任意两个Items { NewIndex=Y/(ListBox1->ItemHeight);//得到拖放后的ItemIndex //如果ItemIndex大于ListBox中的Item数,表示拖到最后一个 NewIndex=NewIndex< ((TListBox *)Sender)- >Items->Count? NewIndex:((TListBox *)Sender)->Items->Count-1; //执行Move操作,移动Item ((TListBox *)Sender)->Items->Move(CurIndex,NewIndex); } //如果Sender不等于Source,表明在两个控件间执行操作 //此例是将数据从一ListBox拖到另一个ListBox else { //若只选中一项 if(((TListBox *)Source)->SelCount==1) { ((TListBox *)Sender)->Items->Add(((TListBox *)Source)-> Items->Strings[((TListBox *)Source)->ItemIndex]); ((TListBox *)Source)->Items->Delete(((TListBox *)Source)-> ItemIndex); } //多选操作 if(((TListBox *)Source)->SelCount>=1) { //循环操作,测试哪些项被选中 for(index=0;index< ((TListBox *)Source)- >Items->Count; index++) if(((TListBox *)Source)->Selected[index]) ((TListBox *)Sender)->Items->Add(((TListBox *)Source)-> Items->Strings[index]); //从后向前删除Source控件中数据 for(index=((TListBox *)Source)->Items->Count-1;index>=0;index--) if(((TListBox *)Source)->Selected[index]) ((TListBox *)Source)->Items->Delete(index); } } } //---------------------------------------------------------- void __fastcall TForm1::ListBox1DragOver(TObject *Sender, TObject *Source,int X, int Y, TDragState State, bool &Accept) { //本例中如果原控件各目标控件都为ListBox控件,则接受拖放 Accept = Source->ClassNameIs("TListBox")&& Sender->ClassNameIs("TListBox"); }  
|