1. 创建4个按钮
CRect rcCreate(0,0,80,80);
m_btTest1.Create(TEXT("Test1"),WS_CHILD|WS_VISIBLE,rcCreate,this,114);
m_btTest2.Create(TEXT("Test2"),WS_CHILD|WS_VISIBLE,rcCreate,this,112);
m_btTest3.Create(TEXT("Test3"),WS_CHILD|WS_VISIBLE,rcCreate,this,111);
m_btTest4.Create(TEXT("Test4"),WS_CHILD|WS_VISIBLE,rcCreate,this,113);
4个按钮位置是重叠的:先看到的是m_btTest4,但先响应的(点击有效)却是m_btTest1。
这是为什么呢?
原因就在于Create的时候,程序会指定每个控件的ZOrder值,先创建的ZOrder值最小,后面逐渐增大。
而关键点就在于:
绘制时,按照ZOrder值由小到大层层绘制,最后绘制排在最上层的控件(m_btTest4),而响应时先处理ZOrder最小的控件(m_btTest1)。
经测试,绘制和响应顺序跟最后面的参数IDC编号(111~114)无关,此编号只是让按钮的响应能够对号入座。
即点击了m_btTest1的控件,程序就会去执行ID=114的相关代码(可由OnCommand函数来截获消息)。
2. 假如之后添加了SetWindowPos函数,那又会如何呢?
m_btTest2.SetWindowPos(NULL,0,0,80,80,SWP_NOMOVE);
m_btTest3.SetWindowPos(NULL,0,0,80,80,SWP_NOMOVE);
此处要说明一点:SetWindowPos第一个参数传NULL,系统会将此控件ZOrder置顶,即ZOrder值变为最小,响应时最先处理;
所以当执行完m_btTest2.SetWindowPos之后,m_btTest2被放到了窗口顶层,此时ZOrder的顺序(由小到大)变为m_btTest2,m_btTest1,m_btTest3,m_btTest4。
而后m_btTest3又被放到了窗口顶层,而m_btTest2就会自动下移。此时的ZOrder顺序(由小到大)就会变为m_btTest3,m_btTest2,m_btTest1,m_btTest4。
到此为止,绘制时先看到的就是m_btTest4,而先响应的却变成了m_btTest3。
3. 那如果SetWindowPos函数最后一个参数再加上SWP_NOZORDER属性呢?比如将第2步的两行代码改为如下:
m_btTest2.SetWindowPos(NULL,0,0,80,80,SWP_NOMOVE|SWP_NOZORDER);
m_btTest3.SetWindowPos(NULL,0,0,80,80,SWP_NOMOVE);
SWP_NOZORDER,顾名思义,就是不改变ZOrder的顺序。那程序就会按照上一次修改控件ZOrder的代码来处理(绘制和响应顺序都是如此)
结果又变成这样的了(由小到大ZOrder排序):
m_btTest2.SetWindowPos(NULL,0,0,80,80,SWP_NOMOVE|SWP_NOZORDER);
//ZOrder:m_btTest1,m_btTest2,m_btTest3,m_btTest4。
m_btTest3.SetWindowPos(NULL,0,0,80,80,SWP_NOMOVE);
//ZOrder:m_btTest3,m_btTest1,m_btTest2,m_btTest4。
4. 还有一个函数也会影响ZOrder----DeferWindowPos(同时调整多个窗口(同一父窗口),比SetWindowPos效率高些)
此处uFlags含有SWP_NOZORDER,则DeferWindowPos函数不会改变相应控件的ZOrder值,即绘制和响应顺序都不改变。
否则如果不加SWP_NOZORDER属性,则跟SetWindowPos的作用是一样的
const UINT uFlags=SWP_NOACTIVATE|SWP_NOZORDER|SWP_NOCOPYBITS|SWP_NOSIZE;
DeferWindowPos(hDwp,m_btTest1,NULL,0,0,0,0,uFlags|SWP_NOMOVE);
DeferWindowPos(hDwp,m_btTest2,NULL,0,0,0,0,uFlags|SWP_NOMOVE);
DeferWindowPos(hDwp,m_btTest3,NULL,0,0,0,0,uFlags|SWP_NOMOVE);
DeferWindowPos(hDwp,m_btTest4,NULL,0,0,0,0,uFlags|SWP_NOMOVE);
总结:
控件在Create时就指定了ZOrder的顺序,先Create的控件ZOrder值最小(最先响应此控件);
反之,后面Create的控件ZOrder值逐渐增大(绘制时层层叠加,即ZOrder值最大的控件就会画到最上层,从而先被看到)。
而如果调用了SetWindowPos,且第一个参数为NULL,也不指定SWP_NOZORDER属性,则系统会将此控件置顶,此时ZOrder值变为最小,最先响应。
http://blog.csdn.net/icebergsnowfox/article/details/8986065#comments