本文对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