mfc z 次序

    xiaoxiao2021-12-14  17

    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); 总结(MFC控件的绘制与响应顺序——ZOrder): 控件在Create时就指定了ZOrder的顺序,先Create的控件ZOrder值最小(最先响应此控件); 反之,后面Create的控件ZOrder值逐渐增大(绘制时层层叠加,即ZOrder值最大的控件就会画到最上层,从而先被看到)。

    而如果调用了SetWindowPos,且第一个参数为NULL,也不指定SWP_NOZORDER属性,则系统会将此控件置顶,此时ZOrder值变为最小,最先响应。

    有些时候发现后加的某些空间被前面的窗口挡住,就可以把前面的窗口剪切在粘贴上就好了

    转载请注明原文地址: https://ju.6miu.com/read-968116.html

    最新回复(0)