delphi拖放编程的要素、事件流程和可能的陷阱
一、拖放的要素
鼠标拖放的二个操作对象:源对象(source)和目标对象(Target)。鼠标左键在源控件(source)上按下拖动,直至可接收目标控件(Target)上放下,即完成一次拖放操作。有四个事件拖放事件依序发生:OnStartDrag,OnDragOver,OnDragDrop,OnEndDrag。按事件名的字义理解这四个事件就对了,OnDragOver和OnDragDrop由目标对象(Target)激发,OnStartDrag和OnEndDrag由源对象(source)激发,下面简单的讲解下四个事件。
注:下文中的拖放对象,指在拖放状态的鼠标,而非TDragObject对象。
二、事件流程
1、OnStartDrag(Sender: TObject; var DragObject: TDragObject);
大多数的组件具有DragMode属性, 表示拖放操作的开始方式。DragMode 属性的默认值为dmManual,也就是要在源对象的OnMouseDown 事件的处理过程中调用BeginDrag过程才开始拖放操作,因此属性值为dmManual时,不需要处理OnStartDrag事件,而代之以OnMouseDown事件(当然此情形下OnStartDrag事件还会发生)。如果将DragMode 属性设置为dmAutomatic,则鼠标左键在源对象上按下后就自动开始拖放操作,这时就可在OnStartDrag事件中进行处理。
procedure TControl.BeginDrag(Immediate: Boolean; Threshold: Integer=-1);
Immediate参数为真时表示按下鼠标立即启动拖放操作;
Threshold:鼠标拖动偏移量为多少时启动操作,第一个参数为真时无意义,一般不用理会,默认偏移量为5。
TDragObject对象一般很少用到,大多情形是供VCL内部的使用,有兴趣或需要的可看VCL源码。
2、OnDragOver(Sender, Source: TObject; X, Y: Integer; State: TDragState; var Accept: Boolean);
拖放鼠标经过目标对象(Target)时,由其激发。
事件参数:Sender拖放目标组件;Source源对象;X,Y鼠标坐标;
State拖放操作状态:枚举类型,有三个值,dsDragEnter刚进入目标组件, dsDragMove移动, dsDragLeave离开。
注意:一般不需要处理State参数。这里有一个陷阱,当State=dsDragLeave时,Accept设值为否,即不接收拖放操作放下,将阻断拖放操作,使后续事件都不能激发,由此判断当鼠标按键释放时,即拖放对象放下时State=dsDragLeave。演示代码:
[delphi]
procedure TMyForm.mmoNoteDragOver(Sender, Source: TObject; X, Y: Integer;
State: TDragState; var Accept: Boolean);
begin
Accept := State <> dsDragLeave;
end;
procedure TMyForm.mmoNoteDragOver(Sender, Source: TObject; X, Y: Integer;
State: TDragState; var Accept: Boolean);
begin
Accept := State <> dsDragLeave;
end;[不知道这算不算VCL的一个BUG,但绝对是一个陷阱!!]
3、OnDragDrop(Sender, Source: TObject; X, Y: Integer);
OnEndDrag(Sender, Target: TObject; X, Y: Integer);
拖放放下事件OnDragDrop和拖放结束事件OnEndDrag同时发生,所不同的事件激发对象不一样,前者是目标对象(Target),后者是源对象(Source)。通常情况下只需要处理二事件其中之一。
结束:看到这里,基本上你就已经掌握了VCL的拖放编程~当然你得动手一试才算。如果遇到问题,那跟踪调试一番应该很快能解决。这是提高编程水平的不二之法。
补充:软件开发 , Delphi ,