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。演示代碼:
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的拖放編程~當然你得動手一試纔算。如果遇到問題,那跟蹤調試一番應該很快能解決。這是提高編程水平的不二之法。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章