C# 关于控件的z-order(Z轴次序)属性

转自豆丁

最近在C#的windows form编程中,涉及到了控件的z-order(Z轴次序)的属性。它来源于三维空间的概念,x和y分别代表屏幕所在平面上的水平坐标和垂直坐标,而z轴则是垂直于屏幕的。在此根据<<Programming Microsoft Window with c#.net>>书籍中的相关内容及自己的理解做一个总结,并实现了一个应用实例,即由按钮和列表控件一起构成的分栏框。


 对于属于同一父控件的一组控件,z-order的作用表现在两方面:一是控件组中每个控件在同一位置时的叠加顺序;二是当几个控件停靠在父控件的同一边缘时的堆积顺序。z-order的初始值是根据你设置每个控件的parent属性值的顺序或者将一个控件加入到一个控件集合的顺序来决定的。具体如下:


若一个控件是在z轴最上层,则它具有以下属性:


l         它第一个被设置parent属性或第一个被加入到控件集合中;


l         它在控件集合中的index即索引值为0;


l         它在其它所有控件的最上层,可以接收到鼠标消息;


l         当多个控件停靠到父控件的同一边缘时,它最靠近客户区的中间;


 


若一个控件是在z轴最下层,则它具有以下属性:


l         它最后一个被设置parent属性或最后一个被加入到控件集合中;


l         它在控件集合中的index即索引值为(Controls.Count-1,即控件组中的控件数目减1);


l         它在其它所有控件的最下层;


l         当多个控件停靠到父控件的同一边缘时,它停靠在此边缘上;


 


可以查看相应的Windows 窗体设计器生成的代码,可以看到最靠近客户区中间的控件是最早被加入到控件集合中的,而停靠在边缘的控件则是最后被加入到控件集合中的。明白了以上基础原理后,即可调用控件类提供的相关方法例如SetChildIndex或者BringToFront和SendToBack等等来修改控件的z-order,从面起到按需调整控件位置的作用。


 


以下将实现一个利用z-order进行编程的实例。


新建一个窗体Form1,添加一个Panel,再在Panel中从上到下依次画出三个Button控件及对应的三个ListBox控件(大小不必太严格,后面调整了Dock属性后就会对齐)button1,listBox1, button2,listBox2, button3,listBox3。设想程序运行的最早的初始情况是button1, button2, button3均停靠在Panel的上边缘,然后接着是listBox3。因些将三个Button控件的Dock属性设为Top,而将listBox1和ListBox2的Visible属性设置为false,ListBox2设置为true.


 


到此界面设计完毕,接着主要的代码编写步骤如下:


 


a.在Form类中添加如下变量用于存放panel中的所有子控件的初始位置信息。


 private const int numOfcontrols=6;//子控件数量


private Control []controlsOriginalPosition;


 


b.在Form类的构造函数中初始化该控件数组变量


controlsOriginalPosition=new Control[numOfcontrols];


//数组中依次存放的是panel中从下到上的子控件


controlsOriginalPosition[0]=this.listBox3;


controlsOriginalPosition[1]=this.button3;


controlsOriginalPosition[2]=this.listBox2;


controlsOriginalPosition[3]=this.button2;


controlsOriginalPosition[4]=this.listBox1;


controlsOriginalPosition[5]=this.button1;


 


c.在Form类中添加如下函数


//对于一个容器控件中的控件集合,将集合中的所有控件的索引进行修改,


//以改变控件停靠在容器同一边时的排列位置。


//例如所有控件的索引从屏幕的下面到上面依次为:0 1 2 3.


//对应的controlsOriginalPosition中的控件索引依次为:0 1 2 3


//若conToChangePosi的索引为2,则将controlsOriginalPosition中的控件索引依次修改为:1 0    2 3


//其中索引为2 3的将放到容器上面,索引为1 0的将放到容器下面


     private bool changeConPosi(Control parentOfCon,Control conToChangePosi)


         {


              int index=0;


              


              //


              //在存放了控件集合的数组中找到该控件


              //


              for(index=0;index<numOfcontrols;index++)  


              {


                   if(conToChangePosi==controlsOriginalPosition[index])


                       break;


              }


            


              if(index==numOfcontrols)


                   return false;                        


              //


              //依次修改控件索引值


              //


              if(index>0)  


                   for(int i=0;i<index;i++)  //修改排在index前面的索引部分                   parentOfCon.Controls.SetChildIndex(controlsOriginalPosition[i],index-1-i);


              for(int i=index;i<numOfcontrols;i++)  //修改排在index后面的索引部分


                parentOfCon.Controls.SetChildIndex(controlsOriginalPosition[i],i);


              //


              //修改索引值完毕后,重新排列控件顺序


              //


              for(int i=0;i<index;i++)


                   controlsOriginalPosition[i].Dock=DockStyle.Bottom;


              for(int i=index;i<numOfcontrols;i++)


                   controlsOriginalPosition[i].Dock=DockStyle.Top;


 


              return true;


         }


 


d.建立各button的单击事件处理函数,仅举button1的例子如下:


private void button1_Click(object sender, System.EventArgs e)


         {


              changeConPosi(this.panel1,this.button1);


              this.listBox1.Visible=true;


              this.listBox2.Visible=false;


              this.listBox3.Visible=false;


              this.listBox1.Dock=DockStyle.Fill;   


         }


 


最终程序运行效果如下:


单击button1








单击button2








单击button3






 


当然,将窗体中的Panel换成GroupBox,或者将ListBox换成ListView,TreeView等其它控件也是可以的,或者控件总数目有所变化挺方便的,不需要修改changeConPosi函数,而只需要修改controlsOriginalPosition数组的初始化部分。

猜你喜欢

转载自blog.csdn.net/lbc2100/article/details/80729431