[VB.NET].NET多語系程式(四) - 已開啟表單的語系切換

.NET多語系程式(四) - 已開啟表單的語系切換

記得在.NET多語系程式(一)中,有提到若要切換已開啟的表單時,我們可以參考Designer.vb檔,透過ComponentResourceManager配合遞迴來作切換的動作。這邊讓我們來看一下實作方式:


    ''' <summary>
    ''' Changes the UI language.
    ''' </summary>
    ''' <param name="form">The form.</param>
    ''' <remarks></remarks>
    Public Shared Sub ChangeUILanguage(ByVal form As Form)
        '-------------------------------
        'Author: Larry Nung   Date:2008/12/11
        'Memo: 參數檢查
        '-------------------------------
        If form Is Nothing Then
            Throw New ArgumentNullException("form")
        End If
        '-------------------------------
        'Author: Larry Nung   Date:2008/12/11
        'Memo: 區域變數宣告
        '-------------------------------
        Dim rm As ComponentResourceManager = Nothing
        '-------------------------------
        'Author: Larry Nung   Date:2008/2/11
        'Memo: 切換介面顯示的語言
        '-------------------------------
        Try
            rm = New ComponentResourceManager(form.GetType)

            For Each ctl As Control In form.Controls
                ApplyControlResource(ctl, rm)
            Next
        Finally
            rm = Nothing
        End Try
    End Sub


    ''' <summary>
    ''' 套用資源設定到控制項(含選單與工具列)
    ''' </summary>
    ''' <param name="control">The control.</param>
    ''' <param name="rm">The ComponentResourceManager.</param>
    ''' <remarks></remarks>
    Private Shared Sub ApplyControlResource(ByRef control As Control, ByRef rm As ComponentResourceManager)
        '-------------------------------
        'Author: Larry Nung   Date:2008/12/11
        'Memo: 參數檢查
        '-------------------------------
        If control Is Nothing Then
            Throw New ArgumentNullException("control")
        End If
        If rm Is Nothing Then
            Throw New ArgumentNullException("rm")
        End If

        '-------------------------------
        'Author: Larry Nung   Date:2008/12/11
        'Memo: 
        '-------------------------------
        rm.ApplyResources(control, control.Name)
        If TypeOf control Is MenuStrip Then
            Dim menuStrip As MenuStrip = CType(control, MenuStrip)
            For Each menuItem As ToolStripItem In menuStrip.Items
                ApplyToolStripResource(menuItem, rm)
            Next
        ElseIf TypeOf control Is ToolStrip Then
            Dim toolStrip As ToolStrip = CType(control, ToolStrip)
            For Each toolStriptItem As ToolStripItem In toolStrip.Items
                ApplyToolStripResource(toolStriptItem, rm)
            Next
        ElseIf control.Controls.Count > 0 Then
            For Each ctrl As Control In control.Controls
                ApplyControlResource(ctrl, rm)
            Next
        End If
    End Sub


    ''' <summary>
    ''' 套用資源設定到選單或工具列
    ''' </summary>
    ''' <param name="toolStripItem">The tool strip item.</param>
    ''' <param name="rm">The ComponentResourceManager.</param>
    ''' <remarks></remarks>
    Private Shared Sub ApplyToolStripResource(ByRef toolStripItem As ToolStripItem, ByRef rm As ComponentResourceManager)
        '-------------------------------
        'Author: Larry Nung   Date:2008/12/11
        'Memo: 參數檢查
        '-------------------------------
        If toolStripItem Is Nothing Then
            Throw New ArgumentNullException("toolStripItem")
        End If
        If rm Is Nothing Then
            Throw New ArgumentNullException("rm")
        End If

        '-------------------------------
        'Author: Larry Nung   Date:2008/12/11
        'Memo: 
        '-------------------------------
        rm.ApplyResources(toolStripItem, toolStripItem.Name)
        If TypeOf toolStripItem Is ToolStripMenuItem Then
            Dim toolStripMenuItem As ToolStripMenuItem = CType(toolStripItem, ToolStripMenuItem)
            For Each Item As ToolStripItem In toolStripMenuItem.DropDownItems
                ApplyToolStripResource(Item, rm)
            Next
        End If
    End Sub

 

使用時,我們先用Threading.Thread.CurrentThread.CurrentUICulture切換當前語系,再呼叫ChangeUILanguage並把要切換語系的表單參考傳入即可,像是:


System.Threading.Thread.CurrentThread.CurrentUICulture = New Globalization.CultureInfo("en")
ChangeUILanguage(Me)

 

執行後已開啟的視窗介面就會被切換語系了

image

 

另外還有一種切換方式是在小歐大那邊貼的連結看到的,程式較為簡單,主要是透過呼叫InitializeComponent來達成,使用上會像下面這樣:


        System.Threading.Thread.CurrentThread.CurrentUICulture = New Globalization.CultureInfo("en")       
        For idx As Integer = Controls.Count - 1 To 0 Step -1
            Controls(idx).Dispose()
        Next
        InitializeComponent()

 

雖然簡單很多,但使用上需特別注意記憶體的使用與效率。因為InitializeComponent副程式內部會建立過多物件、設定過多不需重設的屬性,且使用中的物件可能會無法被GC回收。另外還會造成畫面閃爍與介面變回初始狀態等問題。

這邊我也做了點小實驗,讓我們看看ComponentResourceManager配合遞迴來切換語系的測試程式:


        System.Threading.Thread.CurrentThread.CurrentUICulture = New Globalization.CultureInfo("en")
        Dim sw As Stopwatch = Stopwatch.StartNew
        For i As Integer = 1 To 10000
            ChangeUILanguage(Me)
        Next
        MsgBox(sw.ElapsedMilliseconds.ToString & "ms")

 

測試後所花的時間為19943ms

image

 

記憶體佔用量為19,944k

image

 

InitializeComponent切換語系的測試程式如下:


        System.Threading.Thread.CurrentThread.CurrentUICulture = New Globalization.CultureInfo("en")
        Dim sw As Stopwatch = Stopwatch.StartNew
        For i As Integer = 1 To 10000
            For idx As Integer = Controls.Count - 1 To 0 Step -1
                Controls(idx).Dispose()
            Next
            InitializeComponent()
        Next
        MsgBox(sw.ElapsedMilliseconds.ToString & "ms")

 

測試後所花的時間為35416ms

image

 

記憶體佔用量為20,100k

image 

 

記憶體佔用量差異不大,有可能會有誤差值。請自行測試判斷。