mfc的控件与响应顺序

来源:互联网 发布:淘宝退款在哪里看 编辑:程序博客网 时间:2024/05/17 00:01
  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函数来截获消息)。

  1. 假如之后添加了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。

  1. 那如果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。

  1. 还有一个函数也会影响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值变为最小,最先响应。

0 0
原创粉丝点击