Windows Form Designer

Visual Studio 提供給 Windows Form 開發者一個非常方便的視覺化工具來安排圖形化使用者介面的展示,在大部份不太複雜的狀況下只要拿滑鼠拖來拉去的就可以安排好你所想要展示的畫面,但究竟這些個控制項的定義是存放在哪裡?答案就是Form Desinger檔案。

       Visual Studio 提供給 Windows Form 開發者一個非常方便的視覺化工具來安排圖形化使用者介面的展示,在大部份不太複雜的狀況下只要拿滑鼠拖來拉去的就可以安排好你所想要展示的畫面,但究竟這些個控制項的定義是存放在哪裡?答案就是Form Desinger檔案。

 

       在一般的情況下,我們建立一個新的Windows Form 專案,Visual Studio 會預設先產生一個Form1,於是我們點開方案總管會看到這樣的畫面:

1

       Form1 Desinger在哪?在方案總管上有一個功能叫『顯示所有檔案』,點選它來看看會有何不同的結果。

2

3

      出現了一個名為Form1.Designer.vb (在C#中是Form1.Designer.cs) 的檔案,這個檔案的內容就是記錄著Fom1的控制項配置。一個還沒加入任何控制項的Designer檔案內容如下 (以Visual Studio 2010 Visual Basic Code為例) :

<Global.Microsoft.VisualBasic.CompilerServices.DesignerGenerated()> _
Partial Class Form1
    Inherits System.Windows.Forms.Form
 
    'Form 覆寫 Dispose 以清除元件清單。
    <System.Diagnostics.DebuggerNonUserCode()> _
    Protected Overrides Sub Dispose(ByVal disposing As Boolean)
        Try
            If disposing AndAlso components IsNot Nothing Then
                components.Dispose()
            End If
        Finally
            MyBase.Dispose(disposing)
        End Try
    End Sub
 
    '為 Windows Form 設計工具的必要項
    Private components As System.ComponentModel.IContainer
 
    '注意: 以下為 Windows Form 設計工具所需的程序
    '可以使用 Windows Form 設計工具進行修改。
    '請不要使用程式碼編輯器進行修改。
    <System.Diagnostics.DebuggerStepThrough()> _
    Private Sub InitializeComponent()
        Me.SuspendLayout()
        '
        'Form1
        '
        Me.AutoScaleDimensions = New System.Drawing.SizeF(6.0!, 12.0!)
        Me.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font
        Me.ClientSize = New System.Drawing.Size(368, 321)
        Me.Name = "Form1"
        Me.Text = "Form1"
        Me.ResumeLayout(False)
 
    End Sub
 
End Class

       在這個程式碼的一開頭寫著

Partial Class Form1
    Inherits System.Windows.Forms.Form
 

       這代表它是一個Partial Class,意即它是屬於Form1類別的一部份,而且是繼承了System.Windows.Foems.Form這個父類別而來。

 

       仔細看有一個弔詭的地方是它內部宣告了一個私有成員 Private components As System.ComponentModel.IContainer 而且在覆寫Dispose方法時有使用這個成員,但是找不到任何建構他執行個體的部份,這玩意很有趣,賣個關子,下一次再來談這玩意。

 

       再來我們看到 Private Sub InitializeComponent() 這個方法,整個畫面控制項的屬性的非預設值就在這方法中產生,我們在屬性視窗中做的任何更改都會反應在這個位置,比方說我把Form1的背景改為白色,它就會增加一行:Me.BackColor = System.Drawing.Color.White ( C# :this.BackColor = System.Drawing.Color.White; )。

 

       這個 InitializeComponent() 方法對於C#的使用者可能是比較熟悉的,因為C#在程式碼中一定會定義該表單類別的建構函式:

  public Form1()
        {
            InitializeComponent();
        }  

       但對於Visual Basic的初學者來講,通常是不會發現這個建構函式,不過你可以試著在程式碼的區域內(也就是Form1.vb)中鍵入以下程式 Sub New然後按下Enter鍵,就會發現產生以下的程式碼:

    Sub New()
        ' 此為設計工具所需的呼叫。
        InitializeComponent()
        ' 在 InitializeComponent() 呼叫之後加入任何初始設定。
    End Sub

如果我們從工具列拉一個Button放置在畫面,就會自動在Designer中產生Button的定義和基本屬性:

       [Visual Basic]

Private Sub InitializeComponent()
        Me.Button1 = New System.Windows.Forms.Button()
        Me.SuspendLayout()
        '
        'Button1
        '
        Me.Button1.Location = New System.Drawing.Point(93, 55)
        Me.Button1.Name = "Button1"
        Me.Button1.Size = New System.Drawing.Size(75, 23)
        Me.Button1.TabIndex = 0
        Me.Button1.Text = "Button1"
        Me.Button1.UseVisualStyleBackColor = True
        '
        'Form1
        '
        Me.AutoScaleDimensions = New System.Drawing.SizeF(6.0!, 12.0!)
        Me.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font
        Me.BackColor = System.Drawing.Color.White
        Me.ClientSize = New System.Drawing.Size(709, 448)
        Me.Controls.Add(Me.Button1)
        Me.Name = "Form1"
        Me.Text = "Form1"
        Me.ResumeLayout(False)
 
    End Sub
    Friend WithEvents Button1 As System.Windows.Forms.Button

[C #]

private void InitializeComponent()
        {
            this.button1 = new System.Windows.Forms.Button();
            this.SuspendLayout();
            // 
            // button1
            // 
            this.button1.Location = new System.Drawing.Point(281, 78);
            this.button1.Name = "button1";
            this.button1.Size = new System.Drawing.Size(75, 23);
            this.button1.TabIndex = 0;
            this.button1.Text = "button1";
            this.button1.UseVisualStyleBackColor = true;
            // 
            // Form3
            // 
            this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F);
            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
            this.ClientSize = new System.Drawing.Size(434, 374);
            this.Controls.Add(this.button1);
            this.Name = "Form3";
            this.Text = "Form3";
            this.ResumeLayout(false);
 
        }
 private System.Windows.Forms.Button button1;

 


       在Visual Basic和C#中共同的行為是它們都會先宣告一個繼承自Forms.Button的表單類別內的私有變數 (在這個例子中是 Button1/button1) ,然後在 InitializeComponent() 方法中產生其執行個體,並且賦予其必要的屬性值,不同點在於Visual Basic 會使用WithEvents 子句來宣告此Button的變數,這也就是為何當我們Double Click 控制項時它所產生的事件委派函式會加上Hadles子句的原因,關於這兩個子句可以閱讀MSDN文件庫中的 [WithEvents 和 Handles 子句] 以獲得進一步的瞭解;在C#中則是它只會加入該事件的委派,例如 Double Click了button1後則會在Designer中加入以下程式碼: this.button1.Click += new System.EventHandler(this.button1_Click);

 

       為什麼我會寫關於Designer的東西呢?我相信很多初學者都沒有注意過這個由系統自動產生的檔案,尤其是對於Visual Basic的使用者而言,不過其實研究Designer裡面的程式碼是很有趣的一件事,例如我在上文中所沒有提到的兩個Method -- SuspendLayout() 與 ResumeLayout(),各位有興趣可以自行查閱相關文件來瞭解為什麼在Designer檔中會用這兩個方法。而當你在Form中加入越來越多的項目,然後再仔細研究Designer Code的變化,對於在設計Windows Form程式方面會有很大的幫助,希望大家有空可以自行研究研究,也能夠分享所研究的心得給大家。