懸浮窗口(智能隱藏和顯示)的一種實現方案


懸浮窗口應該具有的特性

 

為了實現讓用戶能方便打開軟件主窗口,又不對用戶界面造成明顯的視覺干擾,懸浮窗口應該有以下特點:

  • 和主窗口是二選一的關系,主窗口顯示時自動隱藏,主窗口被全部遮擋時自動顯示
  • 始終置前,不被其它窗口遮擋,全屏播放電影、截圖軟件截圖等情形時,取消置前。
  • 支持全窗口拖動
  • 半透明效果,鼠標移上時全為不透明
  • 為了使隱藏和出現不顯得突兀,支持淡入淡出效果
  • 點擊懸浮窗時,呼出主窗口,並隱藏懸浮窗口

上述特點的實現方案

整個實現方案依賴於主窗口內的一個定時器(200ms),定時檢查主窗口的顯示狀態以及懸浮窗口的頂置屬性。

和主窗口是二選一的關系,主窗口顯示時自動隱藏,主窗口被全部遮擋時自動顯示

與主窗口二選一的顯示,是通過定時檢查主窗口的顯示狀態,來設置是否顯示懸浮窗口。
如果主窗口未隱藏,並且沒有被其它窗口完全遮擋(可以是一個或者多個窗口的組合),懸浮窗口不顯示。

IsEntirelyCovered(HWND hWnd)(http://blog.csdn.net/harbinzju/article/details/6781646)函數可以判斷一個窗口,是否被完全遮擋住,可能是被一個或者多個窗口遮擋。
實現思路:向上找到Z-Order大於目標窗口的窗口,將這些窗口逐一拼接,每拼接一個窗口后,判斷一下目標窗口是不是被這個拼接后的區域覆蓋。
這里用到的CRgn來自WTL的atlgdi.h,MFC中也有相似的類,都是對API的一個封裝。

始終置前,不被其它窗口遮擋,全屏播放電影、截圖軟件截圖等情形時,取消置前。

這個功能的實現同樣依賴於主窗口的定時器,當定時器觸發時,發現主窗口未顯示,會調用懸浮窗的顯示窗口方法,這里會重新設置置前屬性。
在設置置屬性之前,要判斷是否有其它全屏的置前窗口遮擋了懸浮窗,如果有,不再去搶置前。這樣就可以避免與截圖和全屏播放電影沖突。
實現思路:向上找到Z-Order大於懸浮窗口的窗口,判斷這個窗口是否為全屏。
IsFullScreen(HWND hWnd)函數可以判斷窗口是否為全屏。

BOOL IsFullScreen(HWND hWnd)
{
    if (hWnd == NULL)
    {
        return FALSE;
    }

    if (!::IsWindowVisible(hWnd))
    {
        return FALSE;
    }

    int nScreenWidth = ::GetSystemMetrics(SM_CXSCREEN);
    int nScreenHeight = ::GetSystemMetrics(SM_CYSCREEN);

    CRect rcWnd;
    GetWindowRect(hWnd, &rcWnd);

    if (rcWnd.top == 0 && rcWnd.left == 0 
        && rcWnd.Width() == nScreenWidth
        && rcWnd.Height() == nScreenHeight)
    {
        return TRUE;
    }

    return FALSE;
}

支持全窗口拖動

窗口響應WM_NCHITTEST消息,固定返回HTCAPTION。

半透明效果,鼠標移上時全為不透明

設置WS_EX_LAYERED屬性,使用UpdateLayeredWindow來繪制窗口。因為懸浮窗口一般比較簡單,沒有復雜的控件,甚至沒有控件,所以此方案比較簡單可行。
當鼠標移入和移出時,調用SetLayeredWindowAttributes來改變懸浮窗的透明度。

為了使隱藏和出現不顯得突兀,支持淡入淡出效果

實現思路:開始淡入\淡出時,啟動定時器(30ms),定期增加\減少窗口透明度,當增加至1(或者預設的最大透明度)\減小到0時,停止定時器。

http://blog.csdn.net/harbinzju/article/details/7022882


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM