[VB.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


''' &lt;summary&gt;
''' 套用資源設定到控制項(含選單與工具列)
''' &lt;/summary&gt;
''' &lt;param name="control"&gt;The control.&lt;/param&gt;
''' &lt;param name="rm"&gt;The ComponentResourceManager.&lt;/param&gt;
''' &lt;remarks&gt;&lt;/remarks&gt;
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 &gt; 0 Then
        For Each ctrl As Control In control.Controls
            ApplyControlResource(ctrl, rm)
        Next
    End If
End Sub


''' &lt;summary&gt;
''' 套用資源設定到選單或工具列
''' &lt;/summary&gt;
''' &lt;param name="toolStripItem"&gt;The tool strip item.&lt;/param&gt;
''' &lt;param name="rm"&gt;The ComponentResourceManager.&lt;/param&gt;
''' &lt;remarks&gt;&lt;/remarks&gt;
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</pre></div><p> </p><p>使用時,我們先用Threading.Thread.CurrentThread.CurrentUICulture切換當前語系,再呼叫ChangeUILanguage並把要切換語系的表單參考傳入即可,像是:</p><div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:812469c5-0cb0-4c63-8c15-c81123a09de7:b65aaadb-c7dd-47e5-8117-9930e698ff0b" class="wlWriterEditableSmartContent"><pre class="vb:nocontrols" name="code">

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

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