MFC控件的绘制与响应顺序——ZOrder

来源:互联网 发布:笔趣阁 知乎 编辑:程序博客网 时间:2024/05/29 07:13
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

0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 衣服颜色太深了怎么办 一多半宝宝爱喝水不爱吃饭怎么办 十个月宝宝不爱吃饭怎么办 十个月宝宝突然不爱吃饭怎么办 二十个月宝宝不爱吃饭怎么办 十个月的宝宝不爱吃饭怎么办 6年级学生数学差怎么办 打印机打不出来就是一张白纸怎么办 wps表格下拉数字不递增怎么办 wps表格圈怎么打出来怎么办 手表固定圈掉了怎么办 起来觉得头晕头胀怎么办? 孩子不好好写作业怎么办 孩子考试考差了怎么办 孩子计算题马虎大意怎么办 二年级孩子不认字怎么办 发现计算上的错误怎么办 孩子不好好做作业怎么办 手破了红肿了怎么办呢 老师反应孩子在校粗心胆小怎么办 四年级的学生计算粗心怎么办 老打孩子骂孩子怎么办 站久了脚肿了怎么办 孩子初中了书写越来越潦草怎么办 给孩子自由孩子无法无天怎么办 孩子挑食幼儿园老师该怎么办 老师说孩子挑食家长怎么办 工作中老是粗心不细心怎么办 小孩数学总是特别粗心该怎么办 孩子起范疙瘩的怎么办 做题马虎不认真怎么办 孩子考差了家长怎么办 小孩写作业不认真怎么办 小孩不认真检查作业怎么办 一年级的小孩作业不认真怎么办 一年级学生做题粗心怎么办 一年级的学生做题粗心怎么办 孩子做作业注意力不集中怎么办 小学三年孩子抄答案怎么办 孩子写作业不认真审题怎么办 一年级小孩审题不认真怎么办