溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

如何實現(xiàn)QQ窗體靠邊隱藏及GG 4.2 最新源碼

發(fā)布時間:2021-10-29 18:21:09 來源:億速云 閱讀:114 作者:柒染 欄目:編程語言

如何實現(xiàn)QQ窗體靠邊隱藏及GG 4.2 最新源碼,很多新手對此不是很清楚,為了幫助大家解決這個難題,下面小編將為大家詳細講解,有這方面需求的人可以來學(xué)習(xí)下,希望你能有所收獲。

QQ有個靠邊隱藏的功能,使用起來很方便:在屏幕上拖動QQ的主窗體,當窗體的上邊沿與屏幕的上邊沿對齊時,主窗體就會duang~~地隱藏起來,當將鼠標移到屏幕上邊沿的對應(yīng)區(qū)域時,主窗體又會duang~~顯示出來。

GG4.2中也增加了靠邊隱藏的功能,支持靠左邊沿隱藏、靠上邊沿隱藏、靠右邊沿隱藏三種模式,并且,將靠邊隱藏實現(xiàn)為了一個可復(fù)用的組件AutoDocker。

那么,靠邊隱藏功能到底是怎么實現(xiàn)的了?(最初實現(xiàn)的過程中,遇到了很多問題,花了不少時間,現(xiàn)在直接把成果共享出來)

一.靠邊隱藏的原理

靠邊隱藏的本質(zhì)實際上并不是將窗體的Visiable設(shè)為false,而是將整個窗體的位置挪到屏幕區(qū)域之外。比如,靠右邊沿隱藏,實際的效果圖如下所示:

方案說明如下:

(1)當拖動窗體在屏幕上移動時,檢測窗體的位置,是否抵達了屏幕的邊界,如果達到了邊界,則準備靠邊隱藏。

(2)當達到了隱藏條件,并且鼠標的光標已經(jīng)離開了主窗體,則實現(xiàn)隱藏。

(3)窗體隱藏后,當鼠標的光標移動到窗體與屏幕相交的邊界位置時,則正常顯示窗體;之后:

a. 當鼠標再度離開窗體區(qū)域,則又隱藏窗體。

b.如果鼠標拖動窗體改變了其位置,使其不再滿足隱藏的條件,則之后一直正常顯示窗體。

二.具體實現(xiàn)過程

1.基本元素定義

首先,我們需要定義靠邊隱藏的類型:靠左、靠上、靠右。使用DockHideType枚舉表示:

/// <summary>  /// 靠邊隱藏的類型。  /// </summary>  public enum DockHideType  {      /// <summary>      /// 不隱藏      /// </summary>      None = 0,      /// <summary>      /// 靠上邊沿隱藏      /// </summary>      Top,      /// <summary>      /// 靠左邊沿隱藏      /// </summary>      Left,      /// <summary>      /// 靠右邊沿隱藏      /// </summary>      Right  }

其次,根據(jù)上面的原理描述,我們知道窗體有三種狀態(tài):正常顯示、準備隱藏、已經(jīng)隱藏。這三種狀態(tài)使用FormDockHideStatus枚舉表示:

/// <summary>     /// 窗體的顯示或隱藏狀態(tài)     /// </summary>     public enum FormDockHideStatus     {         /// <summary>         /// 已隱藏         /// </summary>         Hide = 0,          /// <summary>         /// 準備隱藏         /// </summary>         ReadyToHide,                  /// <summary>         /// 正常顯示         /// </summary>         ShowNormally      }

2.判斷是否達到隱藏條件

很明顯,我們應(yīng)當在每次窗體的位置發(fā)生變化時,做出這樣的判斷,所以,這個判斷應(yīng)該在Form的LocationChanged事件中調(diào)用。

private void dockedForm_LocationChanged(object sender, EventArgs e)         {             this.ComputeDockHideType();             if (!this.IsOrg)             {                 this.lastBoard = this.dockedForm.Bounds;                 this.IsOrg = true;             }         }          /// <summary>         /// 判斷是否達到了隱藏的條件?以及是哪種類型的隱藏。         /// </summary>         private void ComputeDockHideType()         {             if (this.dockedForm.Top <= 0)             {                 this.dockHideType = DockHideType.Top;                 if (this.dockedForm.Bounds.Contains(Cursor.Position))                 {                     this.formDockHideStatus = FormDockHideStatus.ReadyToHide;                     return;                 }                 this.formDockHideStatus = FormDockHideStatus.Hide;                 return;             }             else             {                 if (this.dockedForm.Left <= 0)                 {                     this.dockHideType = DockHideType.Left;                     if (this.dockedForm.Bounds.Contains(Cursor.Position))                     {                         this.formDockHideStatus = FormDockHideStatus.ReadyToHide;                         return;                     }                     this.formDockHideStatus = FormDockHideStaus.Hide;                     return;                 }                 else                 {                     if (this.dockedForm.Left < Screen.PrimaryScreen.Bounds.Width - this.dockedForm.Width)                     {                         this.dockHideType = DockHideType.None;                         this.formDockHideStatus = FormDockHideStatus.ShowNormally;                         return;                     }                     this.dockHideType = DockHideType.Right;                     if (this.dockedForm.Bounds.Contains(Cursor.Position))                     {                         this.formDockHideStatus = FormDockHideStatus.ReadyToHide;                         return;                     }                     this.formDockHideStatus = FormDockHideStatus.Hide;                     return;                 }             }         }

上面的代碼主要體現(xiàn)了以下幾個要點:

(1)靠邊的優(yōu)先級判斷:***判斷靠上邊沿隱藏、其次判斷靠左邊沿隱藏、***判斷靠右邊沿隱藏。

(2)只要窗體的某一邊超出的屏幕的邊界(比邊沿對齊更加容易控制),則視為達到隱藏條件。

(3)如果達到了隱藏條件,仍然要判斷光標的位置(Cursor.Position)是否在窗體內(nèi),如果在其內(nèi),則為準備隱藏狀態(tài)。

詳細分析一下上面的過程,就會發(fā)現(xiàn),當處于準備隱藏狀態(tài)時,如果將鼠標移出到窗體外(這次移動并沒有拖動窗體改變其位置),那么,窗體會一直處于“準備隱藏”的狀態(tài)。所以,此時,必須要有一個機制來觸發(fā)它,真正進行隱藏動作。我是用一個定時器來循環(huán)判斷的。

3.定時檢測滿足/退出隱藏條件

我使用一個定時器,每隔300ms檢測一次,用于判斷從正常顯示到隱藏、以及從隱藏到正常顯示的轉(zhuǎn)變。

/// <summary>         /// 定時器循環(huán)判斷。                 /// </summary>                private void CheckPosTimer_Tick(object sender, EventArgs e)         {//當鼠標移動到窗體的范圍內(nèi)(此時,窗體的位置位于屏幕之外)             if (this.dockedForm.Bounds.Contains(Cursor.Position))             {                             if (this.dockHideType!= DockHideType.Top)                 {                     if (this.dockHideType!= DockHideType.Left)                     {                         if (this.dockHideType!= DockHideType.Right)                         {                             return;                         }                         if (this.formDockHideStatus == FormDockHideStatus.Hide)                         {                             this.dockedForm.Location = new Point(Screen.PrimaryScreen.Bounds.Width - this.dockedForm.Width, this.dockedForm.Location.Y);                             return;                         }                     }                     else                     {                         if (this.formDockHideStatus == FormDockHideStatus.Hide)                         {                             this.dockedForm.Location = new Point(0, this.dockedForm.Location.Y);                             return;                         }                     }                 }                 else                 {                     if (this.formDockHideStatus == FormDockHideStatus.Hide)                     {                         this.dockedForm.Location = new Point(this.dockedForm.Location.X, 0);                         return;                     }                 }             }             else //當鼠標位于窗體范圍之外,則根據(jù)DockHideType的值,決定窗體的位置。             {                switch (this.dockHideType)                 {                     case DockHideType.None:                         {                             if (this.IsOrg && this.formDockHideStatus == FormDockHideStatus.ShowNormally &&                                 (this.dockedForm.Bounds.Width != this.lastBoard.Width || this.dockedForm.Bounds.Height != this.lastBoard.Height))                             {                                 this.dockedForm.Size = new Size(this.lastBoard.Width, this.lastBoard.Height);                             }                             break;                         }                     case DockHideType.Top:                         {                             this.dockedForm.Location = new Point(this.dockedForm.Location.X, (this.dockedForm.Height - 4) * -1);                             return;                         }                           case DockHideType.Left:                         {                                                        this.dockedForm.Location = new Point(-1 * (this.dockedForm.Width - 4), this.dockedForm.Location.Y);                             return;                         }                     default:                         {                             if (anchorStyles2 != DockHideType.Right)                             {                                 return;                             }                                                         this.dockedForm.Location = new Point(Screen.PrimaryScreen.Bounds.Width - 4, this.dockedForm.Location.Y);                             return;                         }                 }             }         }

(1)在窗體隱藏的情況下,準確地說,是窗體在屏幕區(qū)域之外時,將鼠標光標移動到窗體上(實際上,是窗體的邊界),則修改窗體的Location,讓其正常顯示。

(2)從(1)描述的窗體隱藏切換到正常顯示時,代碼對窗體的位置進行了控制,使其的邊界恰好與屏幕的邊界對齊,這樣做的目的是,當鼠標再離開窗體范圍時,窗體又可以duang隱藏起來。

(3)定時器的循環(huán)檢測配合鼠標拖動窗體的事件處理,就完全實現(xiàn)了類似QQ的靠邊隱藏的效果,而且,我們比QQ更強,QQ只實現(xiàn)了靠上隱藏。

三.如何使用AutoDocker組件

AutoDocker是以組件(Component)的形式實現(xiàn)的,編譯后,會在工具箱中出現(xiàn)一個AutoDocker組件。其使用非常簡單:

從工具箱中將AutoDocker拖放到主窗體MainForm上,然后在主窗體的構(gòu)造函數(shù)中添加一行代碼:

this.autoDocker1.Initialize(this);

這樣,主窗體運行起來后,就擁有了自動靠邊隱藏的功能了,是不是很duang~~~

在GG 4.2的源碼中,找到客戶端項目(GG2014)下的AutoDocker.cs文件,即可詳細研究靠邊隱藏的實現(xiàn)細節(jié)。

四.GG V4.2 源碼(點擊下載)

GG是可在廣域網(wǎng)部署運行的QQ高仿版,2013.8.7發(fā)布V1.0版本,至今***是4.2版本,關(guān)于GG更詳細的介紹,可以查看 可在廣域網(wǎng)部署運行的QQ高仿版 -- GG2013概要。

如何實現(xiàn)QQ窗體靠邊隱藏及GG 4.2 最新源碼

看完上述內(nèi)容是否對您有幫助呢?如果還想對相關(guān)知識有進一步的了解或閱讀更多相關(guān)文章,請關(guān)注億速云行業(yè)資訊頻道,感謝您對億速云的支持。

向AI問一下細節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI