none
アプリケーションの起動中にフォームのカルチャを変更するには?

    質問

  • ユーザーが設定変更するとフォームのカルチャを変更できるようにしたいと考えています。


    現在の状況は、

     ・フォームのメニュー等がリソースファイルによりローカライズされている。

     ・フォーム上のツリーボックスにはカルチャに依存する日付などのデータが表示される。

     ・カルチャの設定はアプリケーションのスタートアップイベントで行っており、これはうまくいっている。

     

    更にアプリケーションの起動後にユーザーがカルチャを変更できるようにしたいと考え、
       My.Application.ChangeUICulture("CultureCode")
       My.Application.ChangeCulture("CultureCode")


    のようにしたのですが、表示は変更されません。

    おそらくフォームを初期化しなければならないのだと想像しているのですが

    方法がわかりません。

     

    どのようにしたら良いか、ご教示願えないでしょうか。

     

    なお、VS2005を使用しています。
    2008年4月28日 0:33

回答

  •  ふーじあ さんからの引用

    ところが、一度Form1が表示された後にカルチャを変更しても、Form1の表示が変更されないのが

    悩みとなっています。

    ChangeCulture、ChangeUICultureは次にリソースから文字列等を引っ張ってくる際のカルチャ情報を変更するものです。

    従って、既に表示されているフォームには影響しません。(そういうものです)

     

    フォームは初期化時にInitializeComponentにてApplyResourcesメソッドを使って、リソースから情報を取得しています。

    これと同じことをすれば良いという論理になりますが、果たして本当に問題ないのかが分かりません。

    やって良いとしても、フォームやコントロールについて1つずつApplyResourcesを実行しなければならず、保守の手間がかかります。

     

    Visual Studioの多言語パッケージのように「再起動したら有効になります」では許されないのでしょうか?
    2008年4月28日 11:16
    モデレータ
  • 実行時に反映するためには、ApplyResources を実行する必要があるようです。

     

    Code Snippet

    Dim resources As New System.ComponentModel.ComponentResourceManager(Me.GetType())
    'resources.IgnoreCase = True
    resources.ApplyResources(Me, "$this")
    resources.ApplyResources(Me.Button1, "Button1")
    '・・・.Designer.vb の中にある ApplyResources の行をすべて

     

    # かぶった上に、情報量が少ない

    2008年4月28日 11:18
  • 以下のようにしてカルチャの更新ができました。

    (なお、支障がないかの確認はまだしていません)

    コントロールの種類が増えればコードも増加し、確かに保守が煩雑になります。

     

        Private Sub UpdateCulture()
         '現在のカルチャの変更

                My.Application.ChangeUICulture(My.Settings.CultureCode)
                My.Application.ChangeCulture(My.Settings.CultureCode)


                Dim resources As System.ComponentModel.ComponentResourceManager = _

                New System.ComponentModel.ComponentResourceManager(GetType(Form1))


                'フォーム内のコントロールのカルチャの更新
                Me.RecursiveControlCultureUpdate(Me, resources)

                'MenuStrip内のToolStripMenuItemのカルチャの更新
                For Each tsmi As ToolStripMenuItem In Me.MainMenuStrip.Items
                    Me.RecursiveToolStripMenuItemCultureUpdate(tsmi, resources)
                Next

                'フォーム自身のカルチャの更新
                resources.ApplyResources(Me, "$this")

     

         '以下、その他の種類のコントロールのカルチャを更新するコード

        End Sub

     


        'フォーム内に含まれるコントロールのカルチャを再帰的に更新する
        Private Sub RecursiveControlCultureUpdate(ByVal control As Control, ByVal resources As _

          System.ComponentModel.ComponentResourceManager)

            resources.ApplyResources(control, control.Name)
            For Each c As Control In control.Controls
                RecursiveControlCultureUpdate(c, resources)
            Next
        End Sub

     

      ' メニューストリップ内に含まれるToolStripMenuItemのカルチャを再帰的に更新する
        Private Sub RecursiveToolStripMenuItemCultureUpdate(ByVal tsmi As ToolStripMenuItem, _

                ByVal resources As System.ComponentModel.ComponentResourceManager)
            resources.ApplyResources(tsmi, tsmi.Name)
            For Each mi As ToolStripMenuItem In tsmi.DropDownItems
                Me.RecursiveToolStripMenuItemCultureUpdate(mi, resources)
            Next
        End Sub

    2008年4月29日 9:59

すべての返信

  • こちらで試してみましたが、特にフォームを初期化しなくても表示が変更されました。とりあえず参考になりそうなページを紹介しておきます。

     

    Visual Basic 2005 を使って、プログラムによって Windows ベースのアプリケーションにカルチャ情報を設定する方法
    http://support.microsoft.com/kb/914356/ja

    2008年4月28日 1:09
    モデレータ
  • 少し質問があいまいでした。

    (教えていただいたページのサンプルコードは上手くいきました)

     

    私の場合、

    アプリケーションのメインフォーム(Form1)のLocalizableプロパティをTrueとし、

    メニューやコントロールの文字を「既定の言語」では英語で作成しています。(例:Button1)

    次にForm1のLanguageプロパティをたとえばja-JPにした上で、

    メニューやコントロールの文字を日本語に変更します(例:ボタン1)。

    (Form1.ja-JP.resxというファイルが自動的に作成されます。)

     

    このようにした上で、アプリケーションのスタートアップ時(つまりForm1が生成される前に)

    カルチャーをja-JPに設定すれば日本語が、その他のカルチャにすればその他の言語が

    表示されるようになっています。

     

    ところが、一度Form1が表示された後にカルチャを変更しても、Form1の表示が変更されないのが

    悩みとなっています。

     

    なお、変更するためのコードとしては最初の質問のように

    My.Application.ChangeCulture("ja-JP")

    My.Applicatioin.ChangeUICulture("ja-JP")

    としています。

    2008年4月28日 5:32
  •  ふーじあ さんからの引用

    ところが、一度Form1が表示された後にカルチャを変更しても、Form1の表示が変更されないのが

    悩みとなっています。

    ChangeCulture、ChangeUICultureは次にリソースから文字列等を引っ張ってくる際のカルチャ情報を変更するものです。

    従って、既に表示されているフォームには影響しません。(そういうものです)

     

    フォームは初期化時にInitializeComponentにてApplyResourcesメソッドを使って、リソースから情報を取得しています。

    これと同じことをすれば良いという論理になりますが、果たして本当に問題ないのかが分かりません。

    やって良いとしても、フォームやコントロールについて1つずつApplyResourcesを実行しなければならず、保守の手間がかかります。

     

    Visual Studioの多言語パッケージのように「再起動したら有効になります」では許されないのでしょうか?
    2008年4月28日 11:16
    モデレータ
  • 実行時に反映するためには、ApplyResources を実行する必要があるようです。

     

    Code Snippet

    Dim resources As New System.ComponentModel.ComponentResourceManager(Me.GetType())
    'resources.IgnoreCase = True
    resources.ApplyResources(Me, "$this")
    resources.ApplyResources(Me.Button1, "Button1")
    '・・・.Designer.vb の中にある ApplyResources の行をすべて

     

    # かぶった上に、情報量が少ない

    2008年4月28日 11:18

  • trapemiyaさん、Azuleanさん、TH01さん、ありがとうございます。

     

    ApplyResourcesが必要なのですね。

    これについては更に研究してみようと思います。

     

    ただし、適用するリソースが数多くなることを考えると(ループを上手く使えばできそうですが)再起動することにするのが一番の近道のようですね。

    2008年4月28日 12:20
  • 以下のようにしてカルチャの更新ができました。

    (なお、支障がないかの確認はまだしていません)

    コントロールの種類が増えればコードも増加し、確かに保守が煩雑になります。

     

        Private Sub UpdateCulture()
         '現在のカルチャの変更

                My.Application.ChangeUICulture(My.Settings.CultureCode)
                My.Application.ChangeCulture(My.Settings.CultureCode)


                Dim resources As System.ComponentModel.ComponentResourceManager = _

                New System.ComponentModel.ComponentResourceManager(GetType(Form1))


                'フォーム内のコントロールのカルチャの更新
                Me.RecursiveControlCultureUpdate(Me, resources)

                'MenuStrip内のToolStripMenuItemのカルチャの更新
                For Each tsmi As ToolStripMenuItem In Me.MainMenuStrip.Items
                    Me.RecursiveToolStripMenuItemCultureUpdate(tsmi, resources)
                Next

                'フォーム自身のカルチャの更新
                resources.ApplyResources(Me, "$this")

     

         '以下、その他の種類のコントロールのカルチャを更新するコード

        End Sub

     


        'フォーム内に含まれるコントロールのカルチャを再帰的に更新する
        Private Sub RecursiveControlCultureUpdate(ByVal control As Control, ByVal resources As _

          System.ComponentModel.ComponentResourceManager)

            resources.ApplyResources(control, control.Name)
            For Each c As Control In control.Controls
                RecursiveControlCultureUpdate(c, resources)
            Next
        End Sub

     

      ' メニューストリップ内に含まれるToolStripMenuItemのカルチャを再帰的に更新する
        Private Sub RecursiveToolStripMenuItemCultureUpdate(ByVal tsmi As ToolStripMenuItem, _

                ByVal resources As System.ComponentModel.ComponentResourceManager)
            resources.ApplyResources(tsmi, tsmi.Name)
            For Each mi As ToolStripMenuItem In tsmi.DropDownItems
                Me.RecursiveToolStripMenuItemCultureUpdate(mi, resources)
            Next
        End Sub

    2008年4月29日 9:59