程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> 更多編程語言 >> Delphi >> Delphi中停靠技術的實現(1)

Delphi中停靠技術的實現(1)

編輯:Delphi

 


隨著軟件技術的不斷進步,軟件界面也越來越美觀,操作也越來越方便。

綜觀市面上比較專業的各種軟件,我們會發現大部分都提供窗體停靠的功能,特別象工具軟件,基本上都或多或少有停靠功能。

自然,Delphi也支持停靠,而且她和VCL緊密結合,對於廣大的Delphi程序員來說更是一大福音。讓我們省去枯燥的編碼時間。把注意力集中在核心程序的構思上。

先讓我們來復習一下VCL的結構,在TWinControl類中有一個DockSite屬性(boolean),它的作用是是否允許別的控件停靠在它的上面,在TControl類中有一個DragKind屬性,如果要這個控件能停靠在別的控件上,就把DragKind屬性設成dkDock。就這麼簡單,只要設置一下屬性,一個支持停靠的程序就完成了。

當然,上面說的只是最最基本的步驟,有了以上兩步,我們就可以繼續編寫代碼實現更復雜的功能。

一般的支持停靠的程序都可以在主窗口的上下左右停靠,也就是說在主窗口的邊上放上能被停靠的控件比較好(只要是從TWinControl繼承的都行),一般我們都選擇TPanel,為了便於讀者理解,我們可以假定主窗口的左邊可以停靠,所以在主窗口上放一個Align屬性為alLeft的Panel,取名為LeftDockPanel,寬度為0,DockSite屬性為True,當然我們的LeftDockPanel應該是可以改變大小的,所以在它右邊再放一個TSplitter,取名為LeftSplitter,Align屬性為alLeft。接下來就是停靠控件了,一般的程序停靠控件都是窗體,所以我們也建一個窗體,取名叫DockableForm,DragKind屬性設成dkDock,DragMode屬性設為dmAutomatic(自動停靠)。

現在我們可以運行這個程序了,什麼?效果不好?停靠的窗體停靠停靠進去後就不見了!

哦,我差點忘了,當停靠窗體停靠時Delphi會產生一些事件,他們分別是

1.OnDockOver(Sender: TObject; Source: TDragDockObject;

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

2.OnDockDrop(Sender: TObject; Source: TDragDockObject;

     X, Y: Integer);

3.OnGetSiteInfo(Sender: TObject; DockClient: TControl;

     var InfluenceRect: TRect; MousePos: TPoint; var CanDock: Boolean);

4.OnStartDock(Sender: TObject;

     var DragObject: TDragDockObject);

5.OnEndDock(Sender, Target: TObject; X, Y: Integer);

6.OnUnDock(Sender: TObject; Client: TControl;

     NewTarget: TWinControl; var Allow: Boolean);

先讓我們來看看第一個事件

OnDockOver是在停靠控件(DockableForm)掠過被停靠控件(LeftDockPanel)時觸發的。Source包含了停靠—拖動操作的信息,其中有一個重要的屬性是Control,就是DockableForm,另一個重要的屬性是DockRect,就是停靠的位置;X,Y是鼠標的位置,State的狀態有dsDragEnter, dsDragLeave, dsDragMove,分別表示拖動進入,拖動離開,拖動移動;Accept是是否同意停靠的意思。OnDockOver事件主要作用是控制停靠窗體的預覽位置,下面我們來加入以下代碼:

procedure TMainForm.LeftDockPanelDockOver(Sender: TObject;

 Source: TDragDockObject; X, Y: Integer; State: TDragState;

 var Accept: Boolean);

var

 ARect: TRect;

begin

 Accept := Source.Control is TDockableForm;

 if Accept then

 begin

//修改預覽停靠位置

ARect.TopLeft := LeftDockPanel.ClientToScreen(Point(0, 0));

   ARect.BottomRight := LeftDockPanel.ClientToScreen(

     Point(Self.ClientWidth div 3, LeftDockPanel.Height));

   Source.DockRect := ARect;

 end;

end;

現在再運行程序,當你把DockableForm拖動到主窗口左邊時,已經出現了預覽停靠位置,也就是虛線包含的范圍。

怎麼?窗體又不見了?那當然了,我們只是講了OnDockOver,還沒詳細講解OnDockDrop呢,它才是決定停靠窗體在哪裡出現的罪魁禍首:

OnDockDrop(Sender: TObject;

 Source: TDragDockObject; X, Y: Integer);

參數和OnDockOver差不多,只是少了State: TDragState和var Accept: Boolean

它是在停靠窗體進入被停靠控件時發生的,作用是控制停靠窗體的最終位置。下面添加如下代碼:

procedure TMainForm.LeftDockPanelDockDrop(Sender: TObject;

 Source: TDragDockObject; X, Y: Integer);

Begin

 LeftDockPanel.Width := ClientWidth div 3;

 LeftSplitter.Left := LeftDockPanel.Width + LeftSplitter.Width;

End;

現在再運行程序,哇塞,成功了。出現了一個和Delphi的IDE完全一樣的停靠窗體,上面是兩條橫線,用來把它拖出來,右上角有一個小X是用來關閉的。

不過好景不長,當我們把它關閉時,裝載DockableForm的LeftDockPanel不能還原,還是霸占著主窗口的客戶區,怎麼辦?

嘻嘻,忘了告訴你們了,其實Delphi早就為我們作好了一切。

請打開DockableForm的關閉事件,你會發現原來當你點擊右上角那個小X關閉DockableForm時,它會觸發DockableForm的OnClose事件,在OnClose事件中把LeftDockPanel的寬度設為0就行了。

procedure TDockableForm.FormClose(Sender: TObject;

 var Action: TCloseAction);

begin

 MainForm.LeftDockPanel.Width := 0;

 Action := caHide;

end;

以上所講的是如何在主窗口上停靠窗體,原代碼都通過測試。同理,我們可以在主窗口的右邊,下邊,上邊都實現停靠功能。

對了,剛才我們只介紹了OnDockOver和OnDockDrop,忘了介紹別的事件,下面簡單介紹一下:

3.OnGetSiteInfo(Sender: TObject; DockClient: TControl;

     var InfluenceRect: TRect; MousePos: TPoint; var CanDock: Boolean);

這個事件是在窗體移動時觸發的,所以經常觸發,它裡面的DockClient就是TDockableForm,

有一個引用參數叫CanDock,和OnDockOver中的Accept差不多,都是詢問是否允許停靠。在這裡可以不寫,CanDock默認就是True,也可以寫上CanDock := DockClient is TDockableForm;

4.OnStartDock(Sender: TObject;

     var DragObject: TDragDockObject);

5.OnEndDock(Sender, Target: TObject; X, Y: Integer);

6.OnUnDock(Sender: TObject; Client: TControl;

     NewTarget: TWinControl; var Allow: Boolean);

這三個事件都是在DockableForm上面有用,意思分別是停靠開始,停靠結尾,不停靠(也就是被拖出來時)。

 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved