我是个喜欢瞎琢磨的人。尤为是这几天心情很是郁闷。因而开始琢磨了…….琢磨的问题就是WS_CLIPCHILDREN和WS_CLIPSIBLINGS两种窗口样式的理解。html
1.求助MSDNwindows
个人第一步固然是求助MSDN。在MSDN里面有详细的解释。app
1.1 WS_CLIPCHILDREN编辑器
WS_CLIPCHILDREN样式从字面上能够理解成ClipChildren,裁减子窗口。函数
MSDN里的E文解释:Excludes the area occupied by child windows when drawing occurs within the parent window. This style is used when creating the parent window.this
读E文是一件困难的事,为了避免让你们再重复个人痛苦,我就越俎代庖翻译一下:WS_CLIPCHILDREN样式主要是用于父窗口,也就是说当在父窗口绘制的时候,父窗口上还有一个子窗口,那么设置了这个样式的话,子窗口区域父窗口就不负责绘制。spa
那么按照MSDN的理解,能够用下面这幅图来表示:翻译
图 1‑1 WS_CLIPCHILDREN样式的初理解code
1.1 WS_CLIPSIBLINGScdn
WS_CLIPSIBLINGS样式从字面上能够理解成ClipSiblings,裁减兄弟窗口。
MSDN里的E文解释:Clips child windows relative to each other; that is, when a particular child window receives a WM_PAINT message, the WS_CLIPSIBLINGS style clips all other overlapping child windows out of the region of the child window to be updated. If WS_CLIPSIBLINGS is not specified and child windows overlap, it is possible, when drawing within the client area of a child window, to draw within the client area of a neighboring child window.
中文意思是:子窗口间相互裁减。也就是说当两个窗口相互重叠时,设置了WS_CLIPSIBLINGS样式的子窗口重绘时不能绘制被重叠的部分。反之没有设置WS_CLIPSIBLINGS样式的子窗口重绘时是不考虑重叠不重叠,通通重绘。
图 1‑2 WS_CLIPSIBLINGS样式的初理解
2.求助Google
最初看完MSDN,说实话,没有像如今这么清晰画出上面两幅图。而是一片茫然。Google上我所搜索到的中文的还算是比较好的一篇,应该是这篇:http://blog.163.com/sandylin_wind/blog/static/935500552008105104617806/
你们能够看看,可是确实我以为还不够详细,所以才会写篇博文,讨论一下这个问题。
固然E文的专一于WS_CLIPCHILDREN和WS_CLIPSIBLINGS讨论的也比较少。可能老外因为懂E文,因此不像咱们这样费事。
通过一番搜索,仍然有一些比较重要的结论,列举以下:
(1)全部的overlapped和popup风格的窗口,都有WS_CLIPSIBLINGS 属性。也就是说这类风格的窗口,你是去不掉WS_CLIPSIBLINGS 属性的,不会在它重叠的兄弟窗口绘图;
(2)更进一步说明,WS_CLIPSIBLINGS只是用于子窗口(For use with the WS_CHILD style only.)
固然在Google上搜索,一般会有意外发现,通常和这个主题相关的每每是控件如何透明的问题。这里也给你们几个关于控件透明的讨论。
(1) http://www.pocketpcjunkies.com/Uwe/Forum.aspx/wince-vc/4744/Transparent-bitmap-button。这个是关于控件上绘制位图,而后透明的讨论。在桌面系统和WinCE的CreateWindoowsEx还有一些细微的差异,在WinCE上隐含地指定了窗口具有WS_CLIPCHILDREN和WS_CLIPSIBLINGS风格;
(2) http://www.pocketpcdn.com/articles/transparent_static.html这个是关于控件上面文本透明的例子。
3.作几个实验
3.1 验证 WS_CLIPCHILDREN
简单到什么程度呢?只须要在对话框的属性打个勾而已。
简单到什么程度呢?只须要在对话框的属性打个勾而已。
图 3‑1 如何设置对话框Clip Children属性
咱们先作作第一个程序,这个程序惟一有点难的地方就在于须要继承一下CStatic类,而后重载一下OnPaint函数。
void MYStatic::OnPaint()
{
CPaintDC dc(this); // device context for painting
// TODO: Add your message handler code here
// 得到控件客户区矩形大小
CRect rect;
GetClientRect(rect);
// 绘制控件边框
dc.MoveTo(0,0);
dc.LineTo(rect.Width(),0);
dc.LineTo(rect.Width(),rect.Height());
dc.LineTo(0,rect.Height());
dc.LineTo(0,0);
// 绘制文本
dc.TextOut(rect.Width()/2 - 5,rect.Height()/2 - 5,"Hello");
// Do not call CStatic::OnPaint() for painting messages
}
当咱们不设置对话框的Clip children属性的时候,效果以下图所示:
图 3‑2 效果图
当设置了Clip children属性的时候,接下来是见证奇迹的时刻 。^_^
图 3‑3 效果图
很明显父窗口没有管子窗口的背景色如何绘制。子窗口的背景只是当时桌面上现有的窗口内容。
3.2 验证WS_CLIPSIBLINGS
当第一个实验成功以后,我原觉得WS_CLIPSIBLINGS也会至关地简单。结果我花费了大量的时间纠缠在这个问题上。首先遇到的第一个问题,固然是动态地改样式,这个并非太复杂的问题。如何动态改样式,见下面的代码:
LONG style = GetWindowLong(m_pic.GetSafeHwnd(),GWL_STYLE);
style = style | WS_CLIPSIBLINGS ;
SetWindowLong(m_pic.GetSafeHwnd(),GWL_STYLE,style);
而后,我在对话框上添加了一个图片控件和一个自绘制的控件(和上例相似,为了效果明显,我对自绘的控件进行了填充)
按照我预先设想的效果,理想的状况应该以下:
图 3‑4 预想的效果图
发现结果很混乱,每回都得不到我想要的,具备随机性。甚至有的时候按照个人预想,有的时候则彻底无论个人心情。哪怕我气的吹胡子瞪眼睛,也是枉然。
最多见的是这样一种状况,就是不管我设置不设置WS_CLIPSIBLINGS属性,当点击重绘图片控件的时候(m_pic.Invalidate()),效果都一如既往,先开始图片控件(pic)被自定义控件(custom)压盖,而后重绘以后,图片控件(pic)压盖自定义控件(custom)。
图 3‑5 一种错误图
通过一段时间的郁闷,我最终找到了问题之所在,是这样的一个结论:WS_CLIPSIBLINGS还和控件的叠加顺序有关。叠加顺序若是不对,你没法查看WS_CLIPSIBLINGS的效果。就上面的问题,咱们能够在VC编辑器里查看到控件的叠加顺序。
图 3‑6控件的Tab顺序
Pic控件是在custom控件的下方。(Tab Order和Z Order顺序是一致的)。这样设置不设置WS_CLIPSIBLINGS都没法看出效果。
可是改变控件的压盖顺序,令pic控件压盖在custom控件之上(其实是改变Tab order顺序)
图 3‑7 控件的Tab顺序
这样就会出现预期的效果。当不设置WS_CLIPSIBLINGS,pic控件会压盖custom控件,而当设置了该属性,则pic控件不会压盖custom控件,重叠的区域由custom控件本身绘制。
图 3‑8 预期的效果
4.结论
好,到此为止,应该说点有结论的话了。
(1)WS_CLIPCHILDREN样式主要是用于父窗口,也就是说当在父窗口绘制的时候,父窗口上还有一个子窗口,那么设置了这个样式的话,子窗口区域父窗口就不负责绘制。
(2)全部的overlapped和popup风格的窗口,都有WS_CLIPSIBLINGS 属性。也就是说这类风格的窗口,你是去不掉WS_CLIPSIBLINGS 属性的,不会在它重叠的兄弟窗口绘图;
(3)更进一步说明,WS_CLIPSIBLINGS只是用于子窗口(For use with the WS_CHILD style only.)
(4)WS_CLIPSIBLINGS实际上还须要和控件的叠放顺序(z order)配合使用,才能看出明显的效果。