1. 程式人生 > >C# 關於控制元件的z-order(Z軸次序)屬性(By dlm)

C# 關於控制元件的z-order(Z軸次序)屬性(By dlm)

轉自豆丁
 
 
最近在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陣列的初始化部分。