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

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编程的精髓。

无重复随机数序列产生器 -VB资料 显示打开方式对话框建立文件的关联 -VB资料 显示动画鼠标图标-VB资料 修复VB5启动时可能出现的一个bug 修改IE的环境菜单-VB资料 修改安装向导生成的缺省安装目录 -VB资料 修改屏保口令 -VB资料 修改屏幕保护的口令 -VB资料 旋转字体 -VB资料 延时函数-VB资料 一个关于乘法溢出问题的探讨 -VB资料 一组VB实用小程序 一组VB应用技巧 隐藏和显示任务栏-VB资料 应用 WSH 读写注册表和建立快捷方式 -VB资料 VB用 IIF 和 SWITCH 以精减代码 VB用BASIC语言设计Windows风格的用户接口 VB用Form 的 Mouse_Move事件来检查鼠标是否在窗口内: VB用RND()函数加密 VB用SendKeys来捉屏 用VB4.0制作软件封面 用VB5 对Windows 95 任务栏提示区进行编程 用VB5读写注册表实例 用VB5开发商品软件的经验谈 用VB5设计多功能计时器 用VB5制作文字上卷效果 用VB6.0实现打字效果 用VB编写DirectX7.0游戏(上) 用VB创建Excel报表 用VB读取和控制Windows的中文输入法 用VB将命令行软件Windows化 有谁能帮帮我?我会送上高分给大家的!特急! 如何将一个选项表单中的值存下来。 求助,Thinking in c++ 中的一个问题 在NT和win2000下,如何直接操作计算机的并口? 哪位大虾在中文windows xp下安装过VS7.0,拜托告诉下怎么安装,我安装了3回了,均告失败 请问,用在java_applet中怎么实现一幅图片的旋转?怎么控制转动的速度? 天啊!救命啊!! 如何在客户端IE中执行服务器上的应用程序呢,十万火急。请各位大虾不吝赐教 :如何将包含各种数据类型的文件读入,而且要考虑文件的定位(比如从文件最后一个数据往前读) 如何响应wm_nchittest 消息? SHELL是否可以调用网络资源 在PHP中使用word COM对象的问题。 请教一个问题:如何反回一个MonthCalendar1控件上的的周期(控件上有显示,但不知道如何在程序中得到)? 老板叫我做一个界面,跟VC的界面视图一样, 能不能作一个中文编译器??? 我不要活了。。。 菜鸟:一个小问题 基于对话框的程序中,使用了Tree Control和Edit box,如何在Edit box中显示TreeControl中选中的文本文件的内容。希望提供类似的例子。 ★★★★★★★紧急求救★★★★★★★★ 寻找丢失的分区表!!! windows2000进入“等待”后,唤不醒是怎么回事,请指点! jsp数据库中的Date类型? 在vb中如何进行时间比较?例如1 / 7 / 17 10:00:00 - 1 / 7 / 17 00:00:00 得到一个值?? 请问如何获得其他机器的网卡MAC地址?非常感谢!!! 别了,最爱的BCB! 如何判断一个指向窗口的指针可用? 请教高手:怎么样破windows2000的登陆密码?其密文存放在什么地方? 急:哪里有电子文档 找到找到 网络编程、大虾有请!如何获得当前每秒的字节数? 各位高手,有人喜欢用mysql吗?谈谈这个东东吧 大富翁怎么连不上了? 各位武汉的大虾,请教武汉程序员、高级程序员、系统管理员(正规的大公司)、以及用JAVA做开发的工资一般为多少。希望大家给予帮助!!前途问题!! 网络编程大虾有请!如何获得当前每秒的字节数? 怎样在treeview中设置背景图片 to 版主:精华区太乱了,请给予分类。谢了 听说VB可以写PAD的程序,TRUE? JLabel中文本换行问题 马上要开始学BCB,请问BCB有那种类似于VC的创建类的向导吗,看到BCB的界面我就想到DELPHI中创建类的难度 我的游戏引擎BATTLEFIELD作好了,欢迎下载(这次是真的) 一个pop_up menu的问题 那位高手知道在SDK中使用ADO的方法 为普天之下正直而上进的程序员找一个温馨的家 为什么不能把JMF包打进去??? 内存泄露是指例如“为对象分配一个内存区后,未删除内存区,但删除了对象”是吗? 装pws时遇到的麻烦! to freezwy(网络自由人) 有没有限制上传图片大小的asp代码??(不是组件) 还是没有解决!!! 有关VC中数据库绑定的问题! 扔个骨头……下个“圈套”,呵呵? ^_^ 紧急情况!如何改变DataGrid控件中个别行的颜色?? 食堂计划烧煤4800千克,实际是计划烧煤的91.5%,实际烧煤多少千克? 学校食堂运进5吨煤,计划烧80天,由于改进炉灶,每天节约5千克煤,这些煤实际能少几天? 610乘800等于多少? 食堂原计划烧煤4800千克,实际比计划节约了百分之8.5,实际烧煤多少千克? 学校食堂运来1500千克煤,计划烧50天.由于改炉灶,每天节省5千克煤,这批煤可以烧多少天? 60乘800等于多少?60乘800等于48000 食堂原计划烧煤4800kg实际烧煤是原计划的91.5%实际比原计划少烧了多少千克! 学校食堂运来1500千克煤,计划烧50天.由于改炉灶,每天节省5千克煤,实际每天烧多少千克煤?要列出算式来 3吨50千克等于几分之几吨要化成最简分数 食堂11月烧煤5吨,12月烧煤4.5吨,12月比11月节约了百分之几? 某食堂六月份用煤六又四分之一吨,比五月份节约了六分之一,节约的多少t 学校食堂运来1500千克煤,计划烧50天.由于改炉灶,每天节省5千克煤,实际可以烧多少天? 一个食堂4月份烧煤45吨,比原来计划节约了5吨,节约了百分之几? 食堂六月份烧煤8吨,比五月份节约15%,五月份烧煤多少吨? 食堂运来10吨煤,计划烧40天.由于改进炉灶,每天节省5千克.这批煤现在可以烧多少天?列式为() 食堂运来6.3吨煤,原计划十一月份用完,实际每天节约了30kg.这批煤实际烧了多少天? 食堂五月份烧煤880千克,六月份比五月份节约八分之一,这个食堂六月份烧煤多少千克要算式,不要解方程 食堂改进炉灶后每天烧煤69千克,比原来节省8%.原来每天烧煤多少千克? 食堂运来煤2.4吨,计划烧了40,实际每天烧了40天,实际每天烧煤多少吨 食堂五月份用煤3吨,六月份比五月份节约了1/4,节约了多少吨?先画线段图,再列式计算 食堂运来2000千克煤,计划40天烧完,由于改进炉灶,每天节省5千克,这批煤大约可以烧多少天?两种方法 食堂买来一批煤,计划每天烧0.25吨,可烧20天,实际每天少用20%,可多烧几天?(只要公式就行) 食堂四月份比五月份多烧煤100吨,五月份比四月份节约10分之1,食堂四月份多少吨(用方程) 食堂改进炉灶后,比原计划节约5分之1,正好节约6分之7吨,实际用煤多少吨 食堂买来一批煤,计划每天烧250千克,可以烧20天,实际每天节约用煤20%.这样可以多烧几天?比例算 食堂4月份比5月份多烧煤100吨,5月份比4月份节约1/10,食堂5月份烧煤多少吨? 某食堂本月改进炉灶后,比原计划节约用煤五分之一,正好节约2吨.本月实际用煤多少吨? 食堂买来一批煤,计划每天烧0.25吨,可烧20天,实际每天少用20%,可多烧几天用比列解 食堂运来一堆煤,烧掉了35%,正好烧掉了140吨,食堂运来了()吨煤.食堂运来一堆煤,烧掉了35%,还剩140吨,食堂运来了()吨煤.食堂运来5/6吨煤,烧掉了5/9,烧掉了()吨食堂运来5/6吨煤,烧掉了5/9 食堂运来3吨煤.计划可以烧20天.由于改进炉灶,每天可比计划节约30千克,这批煤现在可以烧多少天?第二个问题:甲乙两个仓库存有大米,乙仓库比甲仓库少2800千克,甲仓库大米的重量是乙仓库的 某食堂计划每天烧煤1.5吨,可以用45天,实际比每天计划少烧0.3吨,这批煤实际可少多少天?(用比例解) 食堂的煤已经烧掉了35%,正好烧了140吨,食堂原来有多少吨煤? 某食堂改造炉灶后,每天节约用煤60千克,这样原来计划用32天的煤,现在可以用48天.这堆煤共有多少千克? 食堂有一批煤,计划每天烧105千克可以烧30天.改进烧煤技术后,每天烧煤90千克,这批煤可以多烧多少天? 食堂运来一堆煤,已经烧了3/5,还剩6吨.这堆煤烧了多少吨? 水泥厂食堂运回3吨煤计划可以烧20天,改进炉灶后,这批煤烧了25天,实际平均每天比原计划节约用煤多少千克 食堂运来一批煤,原计划每天烧210千克,可以烧24天.改进炉灶后这批煤可烧28天.问:改进炉灶后平均每天比(连上面)原计划节约多少千克?(列方程) 1.食堂运来 910吨煤,已经烧了这堆煤的35%,还剩下多少吨煤.2.汽车厂九月份按5%的税率激纳营业税1.35万元.这个厂九月份的营业额是()万元.3.有一堆煤,第一周烧了40%,第二周烧了37.5%,还剩90千克 食堂改进炉灶后,每月比计划少用煤五分之一,正好节约十分之九吨,现在每月实际用煤多少吨 食堂运来3吨煤,计划烧20天,由于改进炉灶,这批煤比计划多少了5天,实际每天烧煤多少千克? 应用题:食堂运来一些煤,计划每天用50千克,6.5天烧完,实际10天才烧完,实际每天可节约多少煤? 一项工程,计划10天完成,实际8天完成任务,工作时间缩短了20%,工作效率提高了25%!为什么?工作时间缩短了:(10-8)÷10=20%工作效率:原来10天完成,每天10分之1,实际8天完成,每天8分之1.提高了: 食堂有一批煤,计划每天烧105千克可以烧30天,改进烧煤技术后,每天烧煤90千克,这批煤可以烧多少天用比例解 学校食堂运来一堆煤,煤多少千克计划每天烧50千克,8.5天烧完,实际10天才烧完,实际每天烧煤多少千克 一件工作,原计划10天完成,实际8天完成,工作时间缩短了()%?工作效率提高了()%A12.5 B20 C25 D10(是选择题) 有一批煤,计划每天烧105千克,可以烧30天,改进技术后每天烧90千克,这批煤可以烧多少天?(用比例方法解 食堂买来一批煤,计划每天烧250千克,可以烧20天,实际每天节约用煤20%,这样可以 一项工作,原计划十天完成,实际八天完成,工作时间缩短了百分之几,工作效率提供了百分之几工作效率是10/8-1=25%吗这道算式的思路是什么 星光食品有一批煤,计划每天烧105千克,可以烧30天,由于改进了炉灶,实际每天少烧15千克,比原计划多烧几天?用方程解 美味食堂每天烧掉85kg,比原来节约15kg,节约了百分之几 一件工作,原计划10天完成,实际8天完成,工作时间缩短了百分之多少,工作效率提高了百分之多少? 有一批煤,计划每天烧105千克,可以烧30天.实际每天烧15千克,这些煤实际可以少多少天?(用比例解) 某校食堂有煤mkg,原计划每天用煤akg,实际每天节约用煤15kg,节约后可以多用多少天?(式子) 一箱工程原计划25天完成,实际提前了5天完成,工作时间缩短了几分之几? 食堂原计划烧煤4800千克,实际比计划多烧了8.5%.实际烧煤多少千克? 某食堂有煤m吨,原计划每天烧煤a吨,现在每天节约烧煤b吨,则可比原计划多烧____天 一件工作,原计划10天完成,实际8天完成,工作时间缩短了( )%,工作效率提高了( )%. 食堂原计划烧煤4800千克,实际烧煤是原计划的91.5%.实际比原计划少烧了多少千克? 学校食堂运来1吨煤计划烧40天由于改进炉灶每天可节省5千克这堆煤实际可以烧多少天?怎样计算 完成一项工程的时间由5小时缩短到4小时,工作效率提高了几分之几?要有思考过程
备案号:鲁ICP备13029499号-2 说三道四 www.s3d4.cn