说三道四技术文摘-感悟人生的经典句子
说三道四 > 文档快照

Delphi拖放编程(2)

HTML文档下载 WORD文档下载 PDF文档下载
Delphi拖放编程(2)

9.2开发拖放功能的一般步骤

拖放作为Windows提供的一种方便操作对象的功能,在Delphi中可以很容易地开发出来。根据拖放操作的过程可以把开发步骤划分为四个阶段,即:

●开始拖动操作

●接收拖动项目

●放下拖动项目

●终止拖动操作

在介绍过程中我们将结合一个TabSet(标签集)的拖放操作实例。界面设计如图。在运行时当用户把一个标签拖动到另一个标签的位置时,该标签将移动到该位置并引起标签集的重新布置。

9.2.1开始拖动操作

当拖动模式(DragMode)设置为dmAutomatic时,用户在源控件上按下鼠标时拖动自动开始;当设置为dmManual时通过处理鼠标事件来决定拖动是否开始。如果想开始拖动调用BeginDrag方法。

在TabSet拖放中,我们用下面的MouseDown事件处理过程来开始一个标签的拖动。

首先判断按下的是否是左键,而后再判断项目是否合法。

procedure TForm1.TabSet1MouseDown(Sender: TObject; Button: TMouseButton;

Shift: TShiftState; X

Y: Integer);

var

DragItem: Integer;

begin

if Button = mbLeft then

begin

DragItem := TabSet1.ItemAtPos(Point(X

Y));

if (DragItem > -1) and (DragItem < TabSet1.Tabs.Count) then

TabSet1.BeginDrag(False);

end;

end;

9.2.2接收拖动项目

一个控件能否接收拖动项目是由该控件的OnDragOver事件决定的。在TabSet拖动中,主要是利用鼠标的位置进行判断。

procedure TForm1.TabSet1DragOver(Sender

Source: TObject; X

Y: Integer;

State: TDragState; var Accept: Boolean);

var

DropPos: Integer;

begin

if Source = TabSet1 then

begin

DropPos := TabSet1.ItemAtPos(Point(X

Y));

Accept := (DropPos > -1) and (DropPos <> TabSet1.TabIndex) and

(DropPos < TabSet1.Tabs.Count);

end;

else

Accept := False;

end;

9.2.3放下拖动项目

当OnDragOver事件处理过程返回的Accept为True且项目被放下时,由OnDragDrop事件处理过程来完成拖动放下后的响应。在TabSet拖放实例中是改变标签的位置。

procedure TForm1.TabSet1DragDrop(Sender

Source: TObject; X

Y: Integer);

var

OldPos: Integer;

NewPos: Integer;

begin

if Source = TabSet1 then

begin

OldPos := TabSet1.TabIndex;

NewPos := TabSet1.ItemAtPos(Point(X

Y));

if (NewPos > -1) and (NewPos <> OldPos) then

TabSet1.Tabs.Move(OldPos

NewPos);

end;

end;

9.2.4结束拖动操作

结束拖动操作的方式有两种:或者是用户释放了鼠标键或者是程序用EndDrag方法强行中止拖动。结束拖动操作的后果有两种:放下被接受或放下被忽略。

拖动操作结束后源控件都要收到一条消息响应拖动结束事件OnEndDrag。

9.3  拖放应用实例:文件管理器的拖放支持

在第六章最后开发的文件管理器应用实例,虽然功能上已初具规模,但在操作上与Windows的文件管理器相比还有很大不足。其中最大的缺陷是它不支持文件的拖放移动和拖放拷贝。在这一章结束的时候,我们可以来弥补这一缺陷了。

文件拖放移动指的是当用户把一个文件拖动到目录树下的某一目录并放下时,文件将自动移动到该目录中;文件拖放拷贝指的是当用户把一个文件拖动到某个驱动器标签上并放下时,文件将自动拷贝到该驱动器的当前目录下。作为源控件的文件列表框和作为目标控件的目录树、驱动器标签可以位于不同的子窗口。驱动器的当前目录是任一子窗口的最新操作结果,而不论这一子窗口与拖动源、拖动目标是否有关系。

为了实现上述功能,有两个问题必须首先解决:

1.如何记录每一驱动器的当前目录?

为此我们定义了一个全局变量:

var CurentDirList: Array[0...25] of string[70];

在DirectoryOutline的OnChange事件中:

procedure TFMForm.DirectoryOutlineChange(Sender: TObject);

begin

CreateCaption;

FileList.clear;

FileList.Directory := DirectoryOutline.Directory;

FileList.Update;

CurrentDirList[DriveTabSet.TabIndex] := DirectoryOutline.Directory;

FileManager.DirectoryPanel.Caption := DirectoryOutline.Directory;

end; 

由于DriveTabSet在响应OnDragDrop事件前先响应OnClick事件,并由该事件激发DirectoryOutline的Onchange事件,因而可保证在任何时候OnDragDrop事件中用到的CurrentDirList数组项不为空字符串。

2.如何保证移动、拷贝与子窗口的无关性?

在这里一个关键问题是我们判断源控件时是用is操作符进行类型检查:

If Source is TFileList then …

如果我们用下面的语句:

If Source = FileList then

则移动、拷贝操作将限制在本子窗口范围内。

当解决了上述问我们的工作就只是遵循拖放的一般开发步骤,按步就班来完成了。

1.FileList开始拖动操作

procedure TFMForm.FileListMouseDown(Sender: TObject; Button: TMouseButton;

Shift: TShiftState; X

Y: Integer);

begin

if Button = mbLeft then

with Sender as TFileListBox do

begin

if ItemAtPos(Point(X

Y)

True) >= 0 then

BeginDrag(False);

end;

end;

ItemAtPos用来检查当前是否有文件存在。而BeginDrag方法传递参数False

允许FileList单独处理鼠标事件而并不开始拖动。事实上这种情况是大量存在的。

2.DirectoryOutline、DriveTabSet决定是否能接受拖动的就地放下。

procedure TFMForm.DirectoryOutlineDragOver(Sender

Source: TObject; X

Y: Integer; State: TDragState; var Accept: Boolean);

begin

if Source is TFileListBox then

Accept := True;

end;

procedure TFMForm.DriveTabSetDragOver(Sender

Source: TObject; X

Y: Integer; State: TDragState; var Accept: Boolean);

var

PropPos: Integer;

begin

if Source is TFileListBox then

with DriveTabSet do

begin

PropPos := ItemAtPos(Point(X

Y));

Accept := (PropPos > -1) and (PropPos < Tabs.Count);

end;

end;

DirectoryOutline是无条件的接受,而DriveTabSet需检查是否是合法的标签。

3.拖动放下的响应

DirectoryOutline的拖动放下用于实现文件移动功能。程序中调用ConfirmChange 事件处理过程,目标路径由DirctoryOutline.Items[GetItem(X

Y)].FullPath来得到。

procedure TFMForm.DirectoryOutlineDragDrop(Sender

Source: TObject; X

Y: Integer);

begin

if Source is TFileListBox then

with DirectoryOutline do

begin

ConfirmChange('Move'

FileList.FileName

Items[GetItem(X

Y)].FullPath);

end;

end;

DriveTabSet的拖动放下用于实现文件拷贝功能。程序中把当前位置转化为相应的驱动器号,目标路径由CurrentDirList[DriveTabSet.TabIndex]获得。

procedure TFMForm.DriveTabSetDragDrop(Sender

Source: TObject; X

Y: Integer);

var

APoint: TPoint;

begin

APoint.X := X; APoint.Y := Y;

DriveTabSet.TabIndex := DriveTabSet.ItemAtPos(APoint);

if Source is TFileListBox then

with DriveTabSet do

begin

if CurrentDirList[TabIndex] <> '' then

ConfirmChange('Copy'

TheFilename

CurrentDirList[TabIndex]);

end;

end;

4.FileList响应拖动结束,更新文件列表

procedure TFMForm.FileListEndDrag(Sender

Target: TObject; X

Y: Integer);

begin

if Target <> nil then FileList.Update;

end;

到目前为止,我们的文件管理器功能已足够强大。不过还有许多问题值得读者去进一步探讨,如:

1.文件与应用程序关联的建立;

2.在文件列表框中显示更多的文件信息;

3.文件列表框中的文件按后缀各排序等。

文件管理器是一个真正的综合例程,对它的钻研会使您更进一步模到Delphi编程的精髓。

JVM垃圾收集器使用调查:CMS最受欢迎 技术创业不能一味追求“骨感”,必要时丰富自己的5个途径 帷千动媒副总经理兰旭:整合现在,梳理未来! 11月份浏览器份额:IE继续上涨,Chrome仍不温不火 Windows 8令人担忧:8和8.1两版本份额目前仅有9.3% 一周消息树:微软还需更激进的手段——开放Windows Phone 【开源推荐】Genome.js:当DNA遇到开源 Go 1.2发布 着重语言特性的改进 微软资深IE专家邹颂兵:好产品才是竞争的关键 Web应用程序完全测试指南 Python正在取代R,成为数据科学界新宠 代号Threshold:微软将推Windows统一平台Threshold 日本任天堂掌机应用:《卢浮宫》革了谁的命? [TUP第31期]《浪潮之巅》吴军:硅谷3.0助力中国企业走向国际 SequoiaDB创始人:比MongoDB领先一到两年 打造企业级NoSQL数据库 [对话CTO]甲骨文熊光樑:全球研发模式开发出接地气产品 GitHub中国游记之长城——跨越那堵看不见的墙 IE11开发人员工具:UI响应工具详解 2013 Linux领域年终盘点 腾讯云俱乐部深圳站成功落幕 开创移动开发新篇章 解读云计算、大数据、物联网等九大IT技术发展趋势 苹果已证实收购Topsy或将涉足社交领域 触摸未来:Tactus微流体技术2014年来袭 Windows的未来:一个核心 多个版本 Github项目中使用率最高的Java/Ruby/JS库 2013中国大数据技术大会盛大开幕 从黑色星期五找到的六个规则 帮助网站转化 移动开发者的自学宝典:十大在线编程学习网站 MIT新技术:远程触摸和操纵实物 创新人机交互 中国移动研究院业务支撑研究所所长孙少陵:大数据实时处理技术发展趋势及中国移动实践和展望 “第一届中国大数据技术创新与创业大赛”主办方发言及创新分赛颁奖 数据复制的问题,高分求救! 如何获取TitleBar的尺寸? 创建文件夹的函数及检查是否存在某文件夹的函数?(手册上没有) qqq pcAnywhere操作不能刷新的问题?高手来解救我吧!! 请帮我分析一下为什么会出现这样的错误提示:Access vidation at address 004a36B2 in modale'**.exe'read of address FFFFFFFF CTime和CTimeSpan的使用问题!!!很奇怪??????? 我在写Tuxedo服务程序时,在VC++环境下编译连接时发生以下错误。 关于PDF文件(高分奉送) 来新公司一月了,遇到一个问题,请大家帮忙分析! 谋杀——转贴 打安装包时,提示某些dll过期(很多),怎么办呀? 出生年月与年龄的问题 大家帮帮忙!!!!!!!!!!! 我的天啊!CListCtrl不允许设置行间距和字体大小吗? 如何在40G的硬盘(maxtor)上安装nt4.0 100分(我全部的分),加速,代码优化,JPEG 求救 如何编代码自动创建NT的账号、密码(用什么API实现) 大家看看,我在做一个Messagebox的提示信息时的提示!!!!!奇怪,.net真奇怪 关于计数统计的问题 查某一个人全部贴子的方法。 怎样建立无盘工作站?? pcAnywhere操作不能刷新的问题?高手来解救我吧!! 高手们帮帮忙,我的聊天室怎么不支持中文??? 关于换行的问题??? 各位大侠,请教注册表子项枚举问题?(100分) 修改記錄問題(20)分! 各位大侠帮我检查一下这段代码 再线关注,一个关于excel的问题?一解决立即给分,up有分! 居中 哪里有这些书下载啊!!!! 我的控件不见了! reintroduce和overload有什么区别吗? 关于Javadoc的使用 请问如何在程序运行时根据分辨率等比例调整窗体,控件和字体的大小,使得在任何分辨率下均满屏显示 世界杯“蓝色厄运”理论:英格兰胜巴西 德国淘汰美国(转贴) 关于treeview的节点事件问题,把在下高糊涂了,请高手明示。 要毕业了。。。 BCB中数据库控件的错误扑捉怎么写?比如数据库不存在? 请教如何在调运api函数时,建立缓冲区 SetEvent函数调用带来非法内存访问,扭心的问题。 文件和字符混和上传问题 诸位大虾请帮忙? 各位大虾:哪里有vb.net下载啊? 请教:“开始”菜单中的“文档”菜单不见了! 急!急!急! 一个关于模式对话框的问题 oracle 用sql plus /spool 输出 查询结果时怎么把 查询sql 本身 去掉(不输出) ? 世界杯“蓝色厄运”理论:英格兰胜巴西 德国淘汰美国(转贴) !!请 “arxing(阿行)”回答!!about 对象池!!!! 各位老大,怎样将给定的中文根据拼音排序? access97中的报表中显示中文字段时为什么是乱码,怎样解决,急呀!老大们!! 李明以每小时4千米的速度从家去学校,1/6时行全程的3/5,李明家离学校多少千米?李明以每小时4千米的速度从家去学校,1/6时行全程的3/5,李明家离学校多少千米? 6岁孩子适合玩什么益智玩具 一块长方形的木板长60厘米,宽35厘米在这块木板上锯下一个最大的正方形,这个正方形的周长是多少厘米?请帮计算 李明家距学校600米远,某一天他上学时,以1米每秒的速度走完前一半路程,为了不迟到用200s的时间走完后半路求走路的平均速度. 极坐标系下,圆 ρ=2cos(θ+π/4)上的点与直线ρsin(θ+π/4)=√2上的点的最大距离是——? 谁能给写一个关于教育方面的调查报告?一千字以上抄袭的就给这些分 心算方法是什么 底面直径是20厘米的圆柱体容积中装了一些水,现将一个底面直径是12厘米的铁圆锥全部浸没在水中,水面上升了9毫米【水不满出】,求圆锥的高 一篇稿件,甲独抄6小时完成,乙独抄要8小时完成,两人合抄要几小时完成?列式计算!重赏! 宝宝六个月了,大家都给宝宝买的什么玩具.同上 d一个底面直径为20厘米的圆柱中装水,水中有一个底面直径为8厘米,高12厘米的圆锥,取出圆锥后,水面下降了多少? 一瓶水有5分之4升,4分之3之瓶水有几分之几升? 六个月的婴儿应该买什么玩具? 甲乙两个水桶共蓄水160升,如果把乙桶的水注入甲桶20升,这时甲桶的水等于乙桶的3倍,问原来甲乙各有多少升水不能用XY来解答.请用算式来解答此题. 最搞笑的诗 句是什么? 六个月的宝宝买什么玩具好? 有两只大的网球拍和一只小的乒乓球拍共200元,每只网球拍和乒乓球拍多少元? 有没有像这样的搞笑诗【一年级的小偷,三年级的美眉跳芭蕾……】这样的,不要古诗 谁知道《长歌行》这首古诗的解释越详细越好 长歌行的诗句 如图,已知阴影部分的面积是100平方厘米,求圆环的面积. 《长歌行》全诗 要《长歌行》诗句 在一只长50厘米,宽40厘米的长方体玻璃水缸中,浸入一块棱长20厘米的正方体铁块后,水面会上升多少厘米? 长歌行全诗句 怎样快速口算出两位数乘法(两位数乘除两位数) 在一只长40厘米宽20厘米的玻璃水缸中放入一块棱长10厘米的正方体铁块,铁块浸没在水中水面升高了几厘米 长歌行,江南,七步诗,饮酒属于哪类诗? 在极坐标系(ρ,θ)(0 一只长方形玻璃缸高为40,浸入个棱长20的正方体铁块,水面上升了2厘米,这个水缸的体积是多 长歌行 全诗是什么? 把长30厘米,宽24厘米的长方形木板锯成大小相等的小正方形,每个小正方形的边长最少是多少厘米?锯多少块 关于亲情的初中作文 有什么好的心算方法 一块木板长36厘米,宽24厘米,锯成相同的小正方形若干块,求正方形尽量大,正方形边长是几厘米?可以锯几块 乒乓球拍每幅定价30元乒乓球每盒定价5元甲店买一副球拍给一盒乒乓球乙店全9折优惠需球拍5副乒乓球不小于51)当购买乒乓球多少盒时,两种优惠办法付款一样?2)当分别购买15盒,30盒乒乓球 小学株心算,心算方法 一块木板长36厘米,宽24厘米,锯成相同的正方形木板若干块,要求正方形面积尽量大而没有余料,锯成的正方形木块边长是多少厘米?可以据几块? 一副球怕定价30元,一盒乒乓球定价5元,店买一副球拍给一盒乒乓球乙店全9折优惠需球拍5副乒乓球不小于5当购买乒乓球多少盒时,两家商店给予的优惠相同? 一辆自行车,前轮行10000千米报废,后轮行6000千米报废,如在合适的时候交换前后轮,则最多可以行?千米 一个长6分米,宽5分米的长方体,浸没在一个长2米宽1.5米,2米的水箱中,水面升高5厘米,这个长方体高?快. 我想把比叫小的虫子拿来喂鱼,但我又不想买饲料,怎么样才可以捕捉昆虫. 甲乙两个水桶,从甲桶倒出1/5给乙桶后,乙桶比甲桶水还少20千克,乙桶原有40千克的水,甲桶原有多少水?最好用算术方法解,如果是方程的话请把解方程的过程写出来, 把长24厘米、宽30厘米的长方形木板锯成大小相等的小正方形,且没有剩余,每个小正方形的边长最长是多少厘米?能锯成多少块? 详细的步骤!谢 了! 怎么大量捕捉昆虫 怎么教幼儿快心算? 英语翻译 简述宋朝商品经济发展的特点 什么图形 用英语怎么写 一个底面半径为10厘米的圆柱形水桶中装满水,把一个底面半径为5厘米的圆锥形铁件浸没在水中后,水面上升了2厘米、且水没有溢出铁件高是多少厘米?铁件重多少千克?得数保留两位小数,1立方 运用经济常识的有关知识,阐述低碳商品间隔下降得必然性. 添加照片的英文怎么写 请问谁知道手指心算数字表示方法 从《西方经济学》角度分析企业如何利用产品差别在竞争中获胜? 六个月的小孩买什么玩具 都有什么牌子?6岁儿童益智玩具┵“益智玩具有哪些╈10岁儿童益智玩具 怎么回事啊?2012排行榜?6岁儿童益智玩具┵“益智玩具有哪些╈10岁儿童益智玩具 非常感谢真能开发智力的有吗? 一块长45厘米宽30厘米的长方形木板锯成若干块正方形而无剩余,所锯成的正方形边长最长是几厘米?越快越好 六岁的孩子给他买什么玩具可以开发智力? 兰州大学:羽毛球拍、网球拍、乒乓球拍……在哪买质量好,价格合适? 一块长方形木板,长60厘米、宽40厘米,锯下一个最大的正方形后,剩下的小长方形周长是多少厘米
备案号:鲁ICP备13029499号-2 说三道四 www.s3d4.cn 说三道四技术文摘