亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 編程 > Delphi > 正文

Delphi中??考夹g的實現

2019-11-18 18:47:02
字體:
來源:轉載
供稿:網友

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

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

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

 

先讓我們來復習一下VCL的結構,在TWinControl類中有一個DockSite屬性(boolean),它的作用是是否允許別的控件??吭谒纳厦?,在TControl類中有一個DragKind屬性,如果要這個控件能??吭趧e的控件上,就把DragKind屬性設成dkDock。就這么簡單,只要設置一下屬性,一個支持??康某绦蚓屯瓿闪?。

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

一般的支持??康某绦蚨伎梢栽谥鞔翱诘纳舷伦笥彝??,也就是說在主窗口的邊上放上能被??康目丶容^好(只要是從TWinControl繼承的都行),一般我們都選擇TPanel,為了便于讀者理解,我們可以假定主窗口的左邊可以???,所以在主窗口上放一個Align屬性為alLeftPanel,取名為LeftDockPanel,寬度為0,DockSite屬性為True,當然我們的LeftDockPanel應該是可以改變大小的,所以在它右邊再放一個TSplitter,取名為LeftSplitter,Align屬性為alLeft。接下來就是??靠丶?,一般的程序??靠丶际谴绑w,所以我們也建一個窗體,取名叫DockableForm,DragKind屬性設成dkDock,DragMode屬性設為dmAutomatic(自動停靠)。

現在我們可以運行這個程序了,什么?效果不好???康拇绑w??客?窟M去后就不見了!

 

哦,我差點忘了,當??看绑w??繒rDelphi會產生一些事件,他們分別是

1OnDockOver(Sender: TObject; Source: TDragDockObject;

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

2OnDockDrop(Sender: TObject; Source: TDragDockObject;

      X, Y: Integer);

3OnGetSiteInfo(Sender: TObject; DockClient: TControl;

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

4OnStartDock(Sender: TObject;

      var DragObject: TDragDockObject);

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

6OnUnDock(Sender: TObject; Client: TControl;

      NewTarget: TWinControl; var Allow: Boolean);

哇,這么多,別急,讓我細細道來:

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

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

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

//修改預覽??课恢?/SPAN>

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呢,它才是決定??看绑w在哪里出現的罪魁禍首:

OnDockDrop(Sender: TObject;

  Source: TDragDockObject; X, Y: Integer);

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

它是在??看绑w進入被??靠丶r發生的,作用是控制??看绑w的最終位置。下面添加如下代碼:

procedure TMainForm.LeftDockPanelDockDrop(Sender: TObject;

  Source: TDragDockObject; X, Y: Integer);

Begin

  LeftDockPanel.Width := ClientWidth div 3;

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

End;

現在再運行程序,哇塞,成功了。出現了一個和DelphiIDE完全一樣的??看绑w,上面是兩條橫線,用來把它拖出來,右上角有一個小X是用來關閉的。

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

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

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

procedure TDockableForm.FormClose(Sender: TObject;

  var Action: TCloseAction);

begin

  MainForm.LeftDockPanel.Width := 0;

  Action := caHide;

end;

 

以上所講的是如何在主窗口上??看绑w,原代碼都通過測試。同理,我們可以在主窗口的右邊,下邊,上邊都實現??抗δ?。

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

3OnGetSiteInfo(Sender: TObject; DockClient: TControl;

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

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

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

 

4OnStartDock(Sender: TObject;

      var DragObject: TDragDockObject);

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

6OnUnDock(Sender: TObject; Client: TControl;

      NewTarget: TWinControl; var Allow: Boolean);

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

OnStartDockOnEndDock經常會被觸發,

OnUnDock只在??看绑w變成浮動時觸發

 

 

講了那么多,大家有沒有被搞糊涂?那好,我來做一下總結:

Delphi中只要是從TWinControl繼承的控件都支持被???/SPAN>(如上面的LeftDockPanel),也就是有DockSite這個屬性;所有從TControl繼承的控件都支持???/SPAN>(如上面的DockableForm),也就是有DragKind這個屬性.所以支持被??康目丶贾С滞??,支持??康目丶灰欢ㄖС直煌??,道理很簡單,因為TWinControl繼承于TControl。OnDockOver事件是控制??看绑w的預覽位置;OnDockDrap事件是控制??看绑w的最終位置;OnGetSiteInfo是詢問是否可以??浚?/SPAN>OnStartDock是??块_始,OnEndDock是??拷Y尾,OnUnDock是不???/SPAN>(也就是被拖出來時)。

 

想必Delphi用的熟的大蝦都知道在Delphi的可??看绑w間可以相互???,而且花樣還很多,可以??砍刹⑴诺?,也可以??砍?/SPAN>PageControl樣式的,兩個可??看绑w合并后的窗體又可以再和別的可??看绑w合并,形成樹狀。下面來介紹這方面的技術:

說道這里,我們不得不介紹一下CM_DOCKCLIENT消息和TCMDockClient結構,

CM_DOCKCLIENT消息和TCMDockClient結構是相互對應的,TCMDockClient的結構是:

  TCMDockClient = packed record

    Msg: Cardinal;

    DockSource: TDragDockObject;

    MousePos: TSmallPoint;

    Result: Integer;

  end;

其中DockSource包含了???/SPAN>拖動操作的信息,前面已經提到過;MousePos是鼠標的位置。CM_DOCKCLIENT事件在停靠和被??靠丶伎梢圆东@,因為它是TWinControl類發出的,

代碼如下:

procedure TWinControl.DockDrop(Source: TDragDockObject; X, Y: Integer);

begin

  if (Perform(CM_DOCKCLIENT, Integer(Source), Integer(SmallPoint(X, Y))) >= 0)

    and Assigned(FOnDockDrop) then

    FOnDockDrop(Self, Source, X, Y);

end;

 

可以看出,TWinControl是先發送DOCKCLIENT消息,再觸發OnDockDrop事件的。

為了演示可??看绑w之間相互???,我們先創建一個宿主窗體,取名叫TiledHost,把它的DockSite設成True。它的作用是用來裝載兩個DockableForm的。

首先在DockableForm中捕獲DOCKCLIENT消息,在里面完成兩個窗體的相互???/SPAN>

聲明:

private

procedure CMDockClient(var Message: TCMDockClient); message CM_DOCKCLIENT;

end;

 

實現:

procedure TDockableForm.CMDockClient(var Message: TCMDockClient);

var

  Host: TForm;

begin

  if Message.DockSource.Control is TDockableForm then

  begin

Host := TTiledHost.Create(application);

    Host.BoundsRect := Self.BoundsRect;

    Self.ManualDock(Host, nil, alNone);

    Self.DockSite := False;

    Message.DockSource.Control.ManualDock(Host, nil, alNone);

    TDockableForm(Message.DockSource.Control).DockSite := False;

    Host.Visible := True;

End;

end;

先解釋一下上面的代碼,首先創建TTiledHost的實例,然后用ManualDock函數把自己??康?/SPAN>TTiledHost,把Message.DockSource.Control也??康?/SPAN>TTiledHost,這樣就完成了窗體的相互???,當然,要是我們要程序產生??康念A覽效果,就在DockableFormOnDockOver事件里加入代碼:

procedure TDockableForm.FormDockOver(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 := ClientToScreen(Point(0, 0));

    ARect.BottomRight := ClientToScreen(

      Point(ClientWidth div 2, ClientHeight));

    Source.DockRect := ARect;

  end;

end;

 

怎么樣,效果還可以吧。對了,需要注意的是,用ManualDock函數可以安全的完成??抗δ?,不要用Dock函數。ManualDock函數有一些參數:

function ManualDock(NewDockSite: TWinControl; DropControl: TControl = nil; ControlSide: TAlign = alNone): Boolean;

NewDockSite:要被??康拇绑w;

DropControl:已經存在于NewDockSiteTControl,在這里可以把它設成nil;

ControlSide: ??康奈恢?,可以是上,下,左,右,全部等。

 

當然,我們也可以讓TiledHost也具有和LeftDockPanel一樣有被??康墓δ?,只要把TiledHost看成前面的LeftDockPanel,添加一些屬性和事件;把TiledHost看成DockableForm,

就可以有??康墓δ芰?。具體的做法這里不再闡述了,相信對VCL有深刻研究的大蝦都知道怎么做了。

 

 

下面我來講一下兩個窗體怎樣??砍?/SPAN>PageControl樣式。

首先創建一個窗體,叫TabHost,在它上面放一個PageControl,Align屬性設成alClient,讓它占滿整個TabHost,別忘了把PageControlDockSite屬性設成True.

然后我們依次加入代碼:

procedure TDockableForm.FormDockOver(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 := ClientToScreen(ClientRect.TopLeft);

    ARect.BottomRight := ClientToScreen(ClientRect.BottomRight);

    Source.DockRect := ARect;

  end;

procedure TDockableForm.CMDockClient(var Message: TCMDockClient);

var

  Host: TForm;

begin

  if Message.DockSource.Control is TDockableForm then

  begin

      Host := TTabHost.Create(Application);

      Host.BoundsRect := Self.BoundsRect;

      Self.ManualDock(TTabHost(Host).PageControl1, nil, alClient);

      Message.DockSource.Control.ManualDock(TTabHost(Host).PageControl1, nil, alClient);

      Host.Visible := True;

       End;

End;

代碼的具體意思在這里就不再解釋了,同理也可以讓TabHost具有??亢捅煌?康墓δ?。還需要說明一下,TPageControl封裝了一些對??康闹С?,它捕獲了CM_DOCKCLIENT,

CM_DOCKNOTIFICATION,CM_UNDOCKCLIENT,WM_LBUTTONDBLCLK消息處理停靠動作。具體可以查看TPageControl的原代碼。

 

工具條的??恳惨粯?,在主窗體上放一個ControlBarCoolBar,把他們的DockSite設成True;再在上面放ToolBar, ToolBarDragKind屬性設成dkDock,DragMode屬性設為dmAutomatic。在這里,TControl有一個屬性叫FloatingDockSiteClass,它的類型是TWinControl的引用(class of TWinControl),只要在主窗口創建時,把ToolBarFloatingDockSiteClass屬性設成某一個窗體A,比如在設計時A這個窗體叫ToolBarDockForm,但在程序里面不用顯式的創建A,Delphi會自動創建,當ToolBar被拖動出來時,Delphi自動把它裝載到ToolBarDockForm里,當然ToolBarDockForm也要象上面提到的DockableForm一樣設置一定的屬性和添加一些代碼。

 

講了一大堆,還是沒有把Delphi支持的??抗δ苋恐v完,據我所知,還有很多。還是把它們列出來供大家參考(前面介紹的就省略了)

屬性:

1TControl. TBDockHeight               //存儲??靠丶谕?繒r的的高度;

2TControl. LRDockWidth                //存儲??靠丶谕?繒r的的寬度;

3TControl. UnDockHeight               //存儲??靠丶诟訒r的的高度;

4TControl. UnDockWidth                //存儲??靠丶诟訒r的的寬度;

5TControl. HostDockSite           //存儲被??靠丶膶嵗?/SPAN>

6TControl. FloatingDockSiteClass    //前面講過

7TControl. Floating                        //是否浮動

9TControl. DockOrientation        //??靠丶姆轿?/SPAN>

10TWinControl .DockClientCount  //在這個控件里面有幾個已經??康目丶?/SPAN>

11TWinControl . DockClients      //在這個控件里面有已經??康目丶牧斜?/SPAN>

12TWinControl . DockManager    //一個控制??康念?,其實是一個ActiveX控件,和它對應的類是TDockTree.

13. TWinControl .UseDockManager   //是否使用DockManager。


上一篇:用Delphi處理公歷到農歷的轉換

下一篇:DELPHI與INTERNET2

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
學習交流
熱門圖片

新聞熱點

疑難解答

圖片精選

網友關注

亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
91在线播放国产| 日av在线播放中文不卡| 亚洲第一男人天堂| 欧美激情18p| 久久免费国产视频| 海角国产乱辈乱精品视频| 日韩欧美成人区| 91超碰caoporn97人人| 91精品中文在线| 久久久久久久久国产| 亚洲美腿欧美激情另类| 亚洲高清久久网| 欧美日韩亚洲成人| 国产91在线高潮白浆在线观看| 亚洲成人免费网站| 欧美成人第一页| 亚洲国产精品va在线观看黑人| 国产精品美女主播在线观看纯欲| 欧美午夜影院在线视频| 亚洲精品久久久久国产| 国产精品老女人视频| 91成人天堂久久成人| 欧美精品一本久久男人的天堂| 伊人久久久久久久久久久久久| 国产精品无码专区在线观看| 欧美日韩激情美女| 欧美日韩国产中字| 97在线视频免费播放| 久久久久久久国产| 91黑丝高跟在线| 奇门遁甲1982国语版免费观看高清| 成人深夜直播免费观看| 亚洲欧美在线x视频| 亚洲国产又黄又爽女人高潮的| 亚洲欧美成人在线| 国产精品综合不卡av| 2020久久国产精品| 日韩av在线影视| 中文字幕精品一区久久久久| 九色成人免费视频| 韩国v欧美v日本v亚洲| 亚洲精品中文字幕女同| 欧美国产日韩一区二区| 亚洲一区二区三区777| 国产噜噜噜噜久久久久久久久| 日韩中文第一页| 日本欧美在线视频| 精品中文字幕在线观看| 成人天堂噜噜噜| 亚洲精品网址在线观看| 国产欧美一区二区三区四区| 欧美国产日韩中文字幕在线| 国产精品一区二区av影院萌芽| 美女福利精品视频| 免费91麻豆精品国产自产在线观看| 亚洲一级片在线看| 国产精品高清网站| 精品亚洲夜色av98在线观看| 九九久久精品一区| 国产精品高精视频免费| 欧美视频在线观看免费网址| 亚洲性生活视频| 欧美性猛交xxxx免费看漫画| 国产精品一区二区性色av| 日韩经典一区二区三区| 午夜精品久久久久久久久久久久久| 91精品久久久久久综合乱菊| 亚洲男人的天堂在线播放| 成人av.网址在线网站| 青草热久免费精品视频| 久久精品人人做人人爽| 欧美大学生性色视频| 91香蕉嫩草神马影院在线观看| 性欧美视频videos6一9| 麻豆成人在线看| 国内精品久久久久久| 国产视频亚洲精品| 精品视频在线播放免| 欧美一区二粉嫩精品国产一线天| 在线播放日韩精品| 97在线免费观看视频| 成人在线视频网| 国产日韩精品在线| 中文字幕精品网| 欧美激情视频播放| 992tv成人免费视频| 亚洲精品免费网站| 欧美精品成人在线| 久久伊人91精品综合网站| 国语自产精品视频在线看| 精品视频偷偷看在线观看| 国产成人精品网站| 日韩美女视频免费看| 亚洲第一精品久久忘忧草社区| 国产精品成人一区| 欧美日韩在线另类| 国产大片精品免费永久看nba| 国产精品福利在线观看网址| 98视频在线噜噜噜国产| 午夜精品一区二区三区在线播放| 亚洲第一区在线观看| 久久久久国产精品免费| 亚洲黄色有码视频| 尤物九九久久国产精品的分类| 欧美在线观看网站| 亚洲成人999| 亚洲欧美日韩在线一区| 久久精品电影一区二区| 亚洲在线观看视频网站| 深夜福利国产精品| 青青久久av北条麻妃黑人| 国内精品久久久久久| 日韩中文字幕在线精品| 日韩电影视频免费| 欧美激情视频在线免费观看 欧美视频免费一| 日韩成人av在线播放| 久久亚洲春色中文字幕| 92福利视频午夜1000合集在线观看| 欧美日韩国产一区二区三区| 九九热精品视频国产| 亚洲国产高潮在线观看| 欧美日韩中文字幕综合视频| 欧美老肥婆性猛交视频| 国产精品久久久久久久9999| 国产成人自拍视频在线观看| 国产精品欧美日韩一区二区| 亚洲欧美在线播放| 亚洲色图13p| 日本欧美在线视频| 日本sm极度另类视频| 最好看的2019的中文字幕视频| 中文字幕精品久久| 亚洲精品v欧美精品v日韩精品| 欧美富婆性猛交| 欧美精品福利视频| 亚洲欧美制服丝袜| 亚洲美女激情视频| 国产精品露脸av在线| 国产日韩在线看| 日韩在线免费视频| 久久色精品视频| 亚洲日本欧美日韩高观看| 久久久久久久久久久免费精品| 成人免费午夜电影| 国产精品高潮呻吟久久av无限| 免费97视频在线精品国自产拍| 亚洲精品一区二三区不卡| 国产热re99久久6国产精品| 日本精品中文字幕| 久久久久久久久网站| 欧美日韩国产成人| 亚洲欧美成人在线| 在线观看国产精品淫| 成人欧美一区二区三区在线湿哒哒| 日韩免费观看视频| 91精品在线一区| 黑人极品videos精品欧美裸| 国产精品久久久久久av福利| 久久精品一区中文字幕| 国内成人精品视频| 国产一区二区三区18| 精品久久久久久久久中文字幕| 亚洲社区在线观看| 日韩欧美一区二区在线|