|
視窗系統(tǒng)中的拖放功能大家一定非常熟悉了,如文件的轉(zhuǎn)移,拷貝等操作用鼠標(biāo)輕輕一拖即可,在編寫程式中有時(shí)也用到拖放,那么怎么實(shí)現(xiàn)呢?現(xiàn)以C++ Builder5(簡(jiǎn)稱CB5)為例,分析拖放功能的具體實(shí)現(xiàn)。
一.工具條的拖放
要實(shí)現(xiàn)拖放功能,首先必須了解幾個(gè)和拖放有關(guān)的屬性和方法, 對(duì)于TControl控件,CB5提供了三個(gè)屬性,DockSite,DragKind和DragMode。靈活運(yùn)用這三個(gè)屬性會(huì)得到意想不到的效果。這三個(gè)屬性的意義是:
DockSite:指定當(dāng)前控件是否接受Drag-and-Dock類型的操作
DragKind:拖放種類,分為dkDrag和dkDock兩種
DragMode:拖放模式,分為自動(dòng)和手動(dòng)模式兩種
其中Dock操作是指某控件脫離他的Parent,轉(zhuǎn)而成為另一個(gè)控件的Child,也就是兩個(gè)控件合并。若某一控件的DockSite為True,表明他接受執(zhí)行Dock操作的某控件,并成為他的Parent。
著名的Office工具條能隨意拖放,其實(shí)實(shí)現(xiàn)起來(lái)非常簡(jiǎn)單:在Form上放一CoolBar控件,再在CoolBar控件上隨意放幾個(gè)ToolBar控件,他們的屬性設(shè)置代碼如下:
CoolBar1.DockSite=true;
ToolBar1.DragKind=dkDock;
ToolBar1.DragMode= dmAutomatic;
其他ToolBar的屬性設(shè)置和ToolBar1的屬性設(shè)置相同,編譯運(yùn)行程式,拖動(dòng)工具條試試,Cool極了吧。
二、所有兩上控件間的拖放
和此操作有關(guān)的幾個(gè)函數(shù)有:
BeginDrag:開(kāi)始執(zhí)行拖放操作,如果控件的DragMode為dmManual,則必須調(diào)用此函數(shù),如果DragMode為dmAutomatic,則不用調(diào)用。
OnDragOver:當(dāng)被拖放的對(duì)象經(jīng)過(guò)此控件時(shí)觸發(fā)此事件,其中的參數(shù)Accept表示是否接受拖放的對(duì)象。
OnDragDrop:當(dāng)放下被拖放的對(duì)象時(shí)觸發(fā)此事件。
下面舉例說(shuō)明拖放的實(shí)現(xiàn)過(guò)程:
在CB5中新建一工程,在Form1上放兩個(gè)ListBox,分別命名為L(zhǎng)istBox1,ListBox2,打開(kāi)ListBox1的Items屬性框,隨便輸入幾行字符串。
其屬性設(shè)置如下:
ListBox1->MultiSelect=true; // MultiSelect屬性設(shè)為true,表示能多選
ListBox1->DragMode= dmAutomatic;
ListBox2->MultiSelect=true;
ListBox2->DragMode= dmAutomatic; //兩個(gè)ListBox拖放事件相同,能互相拖放
ListBox2->OnDragOver= ListBox1DragOver;
ListBox2->OnDragDrop= ListBox1DragDrop;
ListBox2->OnStartDrag= ListBox1StartDrag;
在頭文件中設(shè)置兩個(gè)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)
{
//開(kāi)始執(zhí)行拖放事件時(shí)記錄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,表明在同一控件內(nèi)執(zhí)行操作,本例用來(lái)交換ListBox中的任意兩個(gè)Items
{
NewIndex=Y/(ListBox1->ItemHeight);//得到拖放后的ItemIndex
//如果ItemIndex大于ListBox中的Item數(shù),表示拖到最后一個(gè)
NewIndex=NewIndex< ((TListBox *)Sender)- >Items->Count?
NewIndex:((TListBox *)Sender)->Items->Count-1;
//執(zhí)行Move操作,移動(dòng)Item
((TListBox *)Sender)->Items->Move(CurIndex,NewIndex);
}
//如果Sender不等于Source,表明在兩個(gè)控件間執(zhí)行操作
//此例是將數(shù)據(jù)從一ListBox拖到另一個(gè)ListBox
else
{ //若只選中一項(xiàng)
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)
{
//循環(huán)操作,測(cè)試哪些項(xiàng)被選中
for(index=0;index< ((TListBox *)Source)- >Items->Count; index++)
if(((TListBox *)Source)->Selected[index])
((TListBox *)Sender)->Items->Add(((TListBox *)Source)-> Items->Strings[index]);
//從后向前刪除Source控件中數(shù)據(jù)
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)
{
//本例中如果原控件各目標(biāo)控件都為L(zhǎng)istBox控件,則接受拖放
Accept = Source->ClassNameIs(\"TListBox\")&& Sender->ClassNameIs(\"TListBox\");
}
|
|