1. 程式人生 > >QQ揭祕:如何實現窗體靠邊隱藏?【低調贈送:QQ高仿版GG 4.2 最新原始碼】

QQ揭祕:如何實現窗體靠邊隱藏?【低調贈送:QQ高仿版GG 4.2 最新原始碼】

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

  我在GG的最新版4.2中也增加了靠邊隱藏的功能,支援靠左邊沿隱藏、靠上邊沿隱藏、靠右邊沿隱藏三種模式,並且,將靠邊隱藏實現為了一個可複用的元件AutoDocker。

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

      想要直接下載體驗的朋友請點選:“下載中心”

一.靠邊隱藏的原理

      靠邊隱藏的本質實際上並不是將窗體的Visiable設為false,而是將整個窗體的位置挪到螢幕區域之外。比如,靠右邊沿隱藏,實際的效果圖如下所示:

     

     方案說明如下:

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

(2)當達到了隱藏條件,並且滑鼠的游標已經離開了主窗體,則實現隱藏。

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

        a. 當滑鼠再度離開窗體區域,則又隱藏窗體。

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

二.具體實現過程

1.基本元素定義

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

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

        其次,根據上面的原理描述,我們知道窗體有三種狀態:正常顯示、準備隱藏、已經隱藏。這三種狀態使用FormDockHideStatus列舉表示:

    /// <summary>
    /// 窗體的顯示或隱藏狀態
    /// </summary>
    public enum FormDockHideStatus
    {
        /// <summary>
        /// 已隱藏
        /// </summary>
        Hide = 0,

        /// <summary>
        /// 準備隱藏
        /// </summary>
        ReadyToHide,
        
        /// <summary>
        /// 正常顯示
        /// </summary>
        ShowNormally

    }

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

  很明顯,我們應當在每次窗體的位置發生變化時,做出這樣的判斷,所以,這個判斷應該在Form的LocationChanged事件中呼叫。

        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;
                }
            }
        }

  上面的程式碼主要體現了以下幾個要點:

(1)靠邊的優先順序判斷:最先判斷靠上邊沿隱藏、其次判斷靠左邊沿隱藏、最後判斷靠右邊沿隱藏。

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

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

      詳細分析一下上面的過程,就會發現,當處於準備隱藏狀態時,如果將滑鼠移出到窗體外(這次移動並沒有拖動窗體改變其位置),那麼,窗體會一直處於“準備隱藏”的狀態。所以,此時,必須要有一個機制來觸發它,真正進行隱藏動作。我是用一個定時器來迴圈判斷的。

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

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

        /// <summary>
        /// 定時器迴圈判斷。        
        /// </summary>       
        private void CheckPosTimer_Tick(object sender, EventArgs e)
        {//當滑鼠移動到窗體的範圍內(此時,窗體的位置位於螢幕之外)
            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 //當滑鼠位於窗體範圍之外,則根據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)在窗體隱藏的情況下,準確地說,是窗體在螢幕區域之外時,將滑鼠游標移動到窗體上(實際上,是窗體的邊界),則修改窗體的Location,讓其正常顯示。

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

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

三.如何使用AutoDocker元件

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

     從工具箱中將AutoDocker拖放到主窗體MainForm上,然後在主窗體的建構函式中新增一行程式碼:

  this.autoDocker1.Initialize(this);

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

      在GG 4.2的原始碼中,找到客戶端專案(GG2014)下的AutoDocker.cs檔案,即可詳細研究靠邊隱藏的實現細節。

四.GG V4.2 原始碼 

   下載最新版本,請轉到這裡。 

________________________________________________________________________ 

歡迎和我探討關於 GG 和 GGMeeting 的一切,我的QQ:2027224508,多多交流!  

大家有什麼問題和建議,可以留言,也可以傳送email到我郵箱:[email protected]。  

如果你覺得還不錯,請粉我,順便再頂一下啊

相關推薦

QQ揭祕如何實現窗體靠邊隱藏低調贈送QQ仿GG 4.2 最新原始碼

      QQ有個靠邊隱藏的功能,使用起來很方便:在螢幕上拖動QQ的主窗體,當窗體的上邊沿與螢幕的上邊沿對齊時,主窗體就會duang~~地隱藏起來,當將滑鼠移到螢幕上邊沿的對應區域時,主窗體又會duang~~顯示出來。   我在GG的最新版4.2中也增加了靠邊隱藏的功能,支援靠左邊沿隱藏、靠上邊沿隱藏、靠

QQ揭祕如何實現托盤閃動訊息提醒?低調贈送QQ仿GG 4.1 最新原始碼

  當QQ收到好友的訊息時,托盤的圖示會變成好友的頭像,並閃動起來,點選托盤,就會彈出與好友的聊天框,隨即,托盤恢復成QQ的圖示,不再閃動。當然,如果還有其它的好友的訊息沒有提取,托盤的圖示會變成另一個好友的圖示,並繼續閃動。那麼,QQ的這一效果是如何實現的了?我在QQ高仿GG2014中實現了同樣的效果,這裡

如何實現錄製視訊聊天的全過程? 低調贈送QQ仿GG 4.3 最新原始碼

  前段時間做個專案,客戶需要將視訊對話的整個過程錄製下來,這樣,以後就可以隨時觀看。想來錄製整個視訊聊天的過程這樣的功能應該是個比較常見的需求,比如,基於網路語音視訊的1:1的英語口語輔導,如果能將輔導的整個過程錄製下來生成一個標準的MP4檔案,就是一份難得的資料,便於以後複習和分享。我將1:1的視訊對話錄

如何做到在虛擬資料庫和真實資料庫之間自由切換?低調贈送QQ仿GG 4.4 最新原始碼

      記得以前在公司上班時,有時候白天的活沒幹完,我就會把工作帶回家晚上加班繼續做。但是,我們開發用的資料庫是部署在公司局網內部的一臺伺服器上的,在家裡是肯定連不上這臺機器的。在家裡沒有資料庫,服務端就跑不起來,功能也就沒辦法除錯。後來我們的解決方法就是使用虛擬資料庫。在公司上班時,就使用公司局網的真實

可在廣域網部署執行的QQ仿 -- GG嘰嘰(原始碼

前段時間看到園子裡有朋友開發了QQ高仿版的程式,我也非常有興趣,以前一直有個做即時聊天程式的夢,趁這段時間工作不是很忙,就開始動手來做這個事情。根據我以往積累下來的專案經驗,實現QQ的基本功能,問題應該不大。當然,我的目標並不是做一個QQ高仿版的玩具,而是希望做成一個能能夠真正使用的產品(當然是免費的),並持

即時通訊系統中實現聊天訊息加密,讓通訊更安全低調贈送C#開源即時通訊系統(支援廣域網)——GGTalk4.5 最新原始碼

  在即時通訊系統(IM)中,加密重要的通訊訊息,是一個常見的需求。尤其在一些政府部門的即時通訊軟體中(如稅務系統),對即時聊天訊息進行加密是非常重要的一個功能,因為談話中可能會涉及到機密的資料。我在最新的GG 4.5中,增加了對即時聊天訊息進行加密的功能,但這一功能並不是強制的,可以通過開關來進行控制。本文

可在廣域網部署執行的QQ仿 -- GG嘰嘰V3.5,增加自拍頭像功能、細節優化(原始碼

  距離上次發版本(GG嘰嘰V3.4,增加系統設定、最近聯絡人、群功能)又有1個月了,在這個月內,由於空閒時間不是很多,所以,GG增加的主要功能只是拍照並設定其為自己頭像、修改密碼、刪除好友、以及一些bug的修改。我試著列了一下接下來GG要優化的地方,總共達20多條,看來GG離一個正式的產品還有很長的路要走。

可在廣域網部署執行的QQ仿 -- GG嘰嘰V3.6,增加語音訊息、語音留言等功能

  自從微信出來後,語音訊息和語音留言變得非常流行,按下一個鍵說話,比打字要方便多了。GG在V3.6版本增加了對語音訊息和語音留言(或稱為離線語音訊息)的支援。這兩個功能的實現已經很完整,只是比較遺憾的一點是:GG所使用的文字框控制元件,還沒有辦法像微信的聊天視窗的文字框那樣嵌入表示語音訊息的控制元件,所以,

可在廣域網部署執行的QQ仿 -- GG嘰嘰V3.4,增加系統設定、最近聯絡人、群功能(原始碼

  自從上次版本(GG嘰嘰V3.2,增加離線訊息、離線檔案功能)釋出後,我個人覺得主要的大功能都實現得差不多了,接下來的幾個版本將不斷優化GG的細節,提高其可用性。這次版本更新的內容主要是為GG增加了系統設定、並完善的了群所需的基礎功能。 一.GG V3.4 新增功能展現  1.群功能完善 (1)建立群

可在廣域網部署執行的QQ仿 -- GG嘰嘰V3.0,完善基礎功能(原始碼

  (前段時間封閉式開發完了一個專案,最近才有時間繼續更新GG的後續版本,對那些關注GG的朋友來說,真的是很抱歉。)GG的前面幾個版本開發了一些比較高階的功能,像視訊聊天、遠端桌面、檔案傳送、遠端磁碟等,但是,有一些基礎且必需的功能一直未實現,比如註冊、新增好友、加入群、群聊天等等。經常有朋友留言問這些功能要

可在廣域網部署執行的QQ仿 -- GG嘰嘰V1.8(原始碼

距離的GG 1.0釋出已經三週了,這三週內,我利用業餘時間為GG增加了視訊聊天的功能。個人覺得進展有些緩慢,主要是因為大多數時間都花在了UI上。由於本人不會PS,所以圖片素材都是從網上一個一個搜下來的,這個過程確實很煩人,而且最終有些素材還不是很滿意。 一.GG V1.8 新增功能展現 (1)傳送視訊會話

可在廣域網部署執行的QQ仿 -- GG嘰嘰V3.2,增加離線訊息、離線檔案功能(原始碼

  (幾句題外話:雖然就如何將GG發展為一個有商業價值的產品,我還沒有很清晰明確的思路,但是從GG釋出以來,通過GG認識了一些朋友,也接了一些小單子,賺了一點小錢。有了一點甜頭,目前和2、3個好朋友一起做做小專案也是不錯的,這未嘗不是一條養家餬口之路了?呵呵)   距離上次更新(GG嘰嘰V3.0,完善基礎功

可在廣域網部署執行的QQ仿 -- GG嘰嘰V2.4,增加遠端協助、桌面共享功能(原始碼

  QQ的遠端協助、或者說桌面共享是一個非常實用的功能,所以,2.4版本的GG複製了它,而且,GG增強了桌面共享的功能,它可以允許指定要共享桌面的區域,這樣,對方就只能看到指定區域的桌面,這對節省流量會非常有幫助。   GG實現這些功能的過程並不是那麼簡單,因為內部業務邏輯的關聯容易把人搞暈。從執行起來的程

可在廣域網部署執行的QQ仿 -- GG嘰嘰V3.7,優化視訊聊天、控制更多相關細節

  在廣域網中,由於網路的結構紛繁複雜、而且其實時狀況又是千變萬化的,所以,要使廣域網中的視訊聊天達到一個令人滿意的效果,存在諸多挑戰。這次釋出的GG 3.7版本嘗試在這一方向上做一些努力,據我自己測試,相比之前版本,新版本GG的視訊聊天的效果確實有較大提升。本文不僅會分享GG的最新原始碼,而且也會把我在過去

可在廣域網部署執行的QQ仿 -- GG2014 完美!新增支援聊天記錄、好友分組、托盤閃動訊息提醒、登入狀態、GIF動態表情

  距上次GG V3.7版本()的釋出,已經有50天了,這50天對於GG來說,是一個重大的飛躍。因為這段時間通過一些基於GG的實戰專案,發現了GG的很多bug和不足之處,我都一一做了修正,並增加了一些基礎且必須的功能。這次釋出的是GG V4.0版本,又稱為GG 2014。   記得在GG早期版本時,園子裡的

仿介面實現功能

第一步: 匯入類連結1連結2 第二步: 在AppDelegate.m裡 標頭檔案 #import “ViewController.h” 程式碼如下: self.window.rootViewController = [ViewController new]; self.window.back

分享《Keras快速上手基於Python的深度學習實戰-謝樑》PDF免費下載

2018-11-29 15:27:13 百度網盤下載:https://pan.baidu.com/s/1FsmtI2JqzsWPPc9Ev8iXww 《Keras快速上手:基於Python的深度學習實戰》高清PDF,531頁,帶書籤目錄,文字可以複製。 這是一本少見的深入淺出介紹深度學習的入門書籍。

詳解C# 網絡編程系列實現類似QQ的即時通信程序

並且 會話 hat chat .sh odin unicode 情況 plist 引言: 前面專題中介紹了UDP、TCP和P2P編程,並且通過一些小的示例來讓大家更好的理解它們的工作原理以及怎樣.Net類庫去實現它們的。為了讓大家更好的理解我們平常中常見的軟件QQ的工作原理

JS+CSS簡單實現DIV遮罩層顯示隱藏轉藏

button left dtd -m javascrip htm width dex absolute <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/

Spring Security 實戰QQ登錄實現

修改 str 騰訊 open index targe 登錄 pri architect 準備工作1、在 QQ互聯 申請成為開發者,並創建應用,得到APP ID 和 APP Key。2、了解QQ登錄時的 網站應用接入流程。(必須看完看懂)為了方便各位測試,直接把我自己申