1. 程式人生 > >C++ Builder中實現拖放功能

C++ Builder中實現拖放功能

在C++ Builder中實現拖放功能

關鍵字:實現拖放功能,DockSite,DragKind,DragMode

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)   // >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");

}
// 本文轉自 C++Builder研究 - http://www.ccrun.com/article.asp?i=44&d=7pm23u

執行程式,用滑鼠拖拖看。