找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 1799|回复: 0
打印 上一主题 下一主题
收起左侧

C++ Builder的拖放功能实现

[复制链接]
跳转到指定楼层
楼主
ID:3721 发表于 2015-1-2 19:46 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
     视窗系统中的拖放功能大家一定非常熟悉了,如文件的转移,拷贝等操作用鼠标轻轻一拖即可,在编写程式中有时也用到拖放,那么怎么实现呢?现以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\");

}

分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享淘帖 顶 踩
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表