本文對Duilib的遮罩層以及及穿透進行相關的討論,原理很簡單,除了討論實現外,在本文也討論如何利用這些特性、原理來實現需求,歡迎討論。
1. 遮罩層的實現
在軟件的UI顯示中,我們經常會需要遮罩住整個窗口或者是窗口的一部分,以避免客戶操作相應的UI,等待特定的操作完成之後才解除鎖定。
其實這個在Duilib中,是非常容易實現的,好像還有不少人不太清楚,咱們這裏就先來討論一下這個。
Duilib繪製各個控件、響應控件的事件都是按層次從前往後進行處理的[可以簡單的理解爲XML節點的先後順序],也就是說位置越靠後的在UI顯示層次越高;那麼,我們如果在足夠靠後的位置放置一個float的控件,控制好他的位置,將需要遮罩的區域覆蓋住的話,是不是就能夠實現遮罩了呢?
答案是肯定的。
以Duilib中的TestApp爲例,我們在其XML而已文件的最外層的Layout最後,添加如下代碼【這是爲了遮罩整個窗口,如果只要遮罩部分,調整一下即可】:
<span style="font-size:14px;"><Control float="true"bkcolor="#66000000" name="cover"pos="0,0,1000,1000" /></span>
其中這個bkcolor表示是黑色,以及一定的透明度,就這樣我們就完成了一個遮罩層了,在程序中,只要適當的控制好此控件的顯示隱藏以及位置大小即可。
看看效果【只遮擋上半部分】:
2. 控件的穿透
還有另外一種需求,就是當有兩個控件有重疊的時候,我想鼠標操作時,直接操作下面的那個控件,而不要被上面的控件把事件給攔截了,這就引出了控件的穿透問題。
爲什麼會有這樣的需求呢?
舉一個簡單的例子,QQ的圖片查看器,在通過鼠標滾輪滾動時,能調整它的顯示比例,同時會有一個比例大小的顯示,如下圖:
但當鼠標在120%這個位置點擊拖動時,與它沒有顯示時一樣;如果我想用Duilib來實現的話,這就是一種穿透了【當然有別的實現方法,比如我們自己在此處繪製相應的圖片和文字,但我們現在討論的是如何利用Duilib來實現】。
如果覺得這個需求沒什麼意義,咱們討論點有意思的看看:
1) 假如你在做一個圖書閱讀的軟件,天晚了,如果可以降低閱讀的軟件亮度,又不影響對軟件的操作,是不是比較貼心?
2) 如果可以給一個文本輸入框增加一個前景半透明的圖片,且不影響文字輸入,是不是比加個背景色更顯高大上?
3) 如果你做的是一個比較煊的界面,上面在放着鞭炮,軟件雙可以繼續操作,是不是比較酷?
4) 更多的特效,在功能上支持後,就可以任意發揮你的想象力了,可以在評論裏回覆。
說了這麼多,咱們還是來討論如何實現控件的穿透吧,其實很簡單,在強大的Duilib下,我們只需要給CControlUI增加一個屬性,然後再增加一個判斷就搞定了。
步驟:
1) 給CControlUI增加一個成員變量:m_bEnableEvent,表示是否支持事件,爲否則表示穿透,這裏需要在構造函數中將其默認爲true,否則你的窗口將不能被操作了。
2) 在CPaintManagerUI::__FindControlFromPoint函數中,如果當前控件的m_bEnableEvent爲false,則直接返回NULL即可,代碼如下:
CControlUI* CALLBACKCPaintManagerUI::__FindControlFromPoint(CControlUI* pThis, LPVOID pData)
{
if (!pThis->m_bEnableEvent)
{
return NULL;
}
LPPOINTpPoint = static_cast<LPPOINT>(pData);
return ::PtInRect(&pThis->GetPos(), *pPoint)? pThis : NULL;
}
3) 如果想要哪個控件可以穿透,直接將其m_bEnableEvent設置爲false即可。以下在OnPrepare中將遮罩層及一個按鈕設置爲穿透:
m_pm.FindControl(_T("cover"))->m_bEnableEvent = false;
m_pm.FindControl(_T("insertimagebtn"))->m_bEnableEvent = false;
進一步處理的話,在XML中增加這個屬性,並且在解析XML的地方增加對此屬性的解析與賦值,就更加靈活了。
實現效果如下[可以點擊遮罩層下的任意區域,輸入信息]:
代碼下載:
http://download.csdn.net/detail/tragicguy/8950067