2020年12月
« 10月    
 123456
78910111213
14151617181920
21222324252627
28293031  

カテゴリー

最近のコメント

    <!–:ja–>Visual Basic 6.0国際化プログラミング<!–:–><!–:en–>Visual Basic 6.0 Internationalization Programming<!–:–>

    ソフトウェア国際化ツールWorld Wide Navi(ワールドワイドナビ)の国際化プログラミング参考情報から、Visual Basic 6.0の国際化の抜粋です。

    ちょっとというかかなり古いトピックですが、上記の参考情報以外にここまでまとめられているサイトはないので、VB6の古いアプリの多言語化を探している方には、かなり有用なトピックではないかと思います。

    眠っているアプリケーションをもういちど引き出しから出して、世界に羽ばたかせてみてはいかがでしょうか?

    各言語設定(ロケール)に対応してメッセージ、ラベル、キャプション、フォントなどを切り替えるためには、 これらのデータをリソースにまとめ動的に読み込む必要があります。
    Visual Basic 6.0では、それはWindows APIのリソース読み込みと同じ方法を用いることで達成できます。
    次の手順ではVisual Basic 6.0でリソースデータを作成、読み込む方法を、 World Wide Naviの文字列の外部化を使って説明しています。

    1. リソースファイル(.rc)の作成
    文字列をリソースのキーと値からなるリソースファイルに記述します。
    (このファイルはテキストエディタ、またはWorld Wide Navi文字列の外部化によって作成できます。)
    以下はWorld Wide Naviによって作成されたサンプルコードです。

    wwnavi_string.rc
    ...
    #pragma code_page(1252)
    STRINGTABLE
    BEGIN
     101 "My Name" // MsgBox ("My Name"), MyClass.cls
     102 "Form1" // Caption
     = "Form1", Form1.frm
     103 "MS PGothic" // Name
     = "MS PGothic", Form1.frm
     104 "Button1" // Caption
     = "Button1", Form1.frm
     105 "@Arial Unicode MS" // Name
     = "@Arial Unicode MS", Form1.frm
     106 "Label1" // Caption
     = "Label1", Form1.frm
     107 "Ms Mincho" // Name
     = "Ms Mincho", Form1.frm
     108 "array 1" // strs1(0) = "array 1", Form1.frm
     109 "array 2" // strs2(0) = "array 2", Form1.frm
     110 "Hello, how are you? This is
    sample for Windows DLL."
    // MsgBox ("Hello, how are you?
     This is sample for Windows DLL."), Form1.frm
     111 "this is simple text."
    // msg = "this is simple text.", Module1.bas
     112 "This is message 2."
    // MsgBox ("This is message 2."), Module1.bas
    END

    *コードページとファイルのエンコーディングは対応している必要があります。

    2. Windows API関数を宣言

    Windows APIをVBで使うためには、それらの宣言を以下のように記述する必要があります。

    Private Declare Function
    GetThreadLocale Lib "kernel32" () As Long
    Private Declare Function
    GetUserDefaultLCID Lib "kernel32" () As Long
    Private Declare Function
    GetLocaleInfo Lib "kernel32" Alias "GetLocaleInfoA" _
     (ByVal Locale As Long,
    ByVal LCType As Long, ByVal lpLCData As String, _
     ByVal cchData As Long) As Long
    Private Declare Function
    LoadLibrary Lib "kernel32" Alias "LoadLibraryA" _
     (ByVal lpLibFileName As String) As Long
    Private Declare Function
    LoadString Lib "user32" Alias "LoadStringA" _
     (ByVal hInstance As Long,
    ByVal wID As Long, ByVal lpBuffer As String, _
     ByVal nBufferMax As Long) As Long
    
    Private Const
    LOCALE_IDEFAULTANSICODEPAGE =
    &H1004&
    Private Const
    LOCALE_SISO639LANGNAME
    = &H59

    GetThreadLocale, GetUserDefaultLCID … 現在のロケールを取得
    GetLocaleInfo … ロケール情報を取得
    LoadLibrary … リソースDLLを読み込む
    LoadString … 文字列データをDLLから読み込む(*1)
    LOCALE_IDEFAULTANSICODEPAGE, LOCALE_SISO639LANGNAME … ロケール関数用の定数

    *1)VBは同じ様な関数”LoadResString”を持っていますが、 DLLから読み込むためには”LoadString”が必要です。

    3. リソース読み込み処理を記述
    リソースから文字列を読み込む処理を記述します。
    読み込みにはLoadString関数を使います。 以下はWorld Wide Naviによって作成されたサンプルコードです。

    MsgBox (wwnaviGetString(110))
    ...
    Function WwnaviGetString
    (id As Long) As String
     Dim buf As String * 512
     Dim rslt As Long
     rslt = LoadString(
    wwnaviH, id, buf, 512)
     WwnaviGetString = buf
    End Function

    wwnaviH … DLLモジュールへのポインタ(後述)
    id … リソースキー
    buf … 読み込んだ文字列を格納する文字列
    512 … 読み込む文字列のバッファサイズ

    4. 動的なリソースDLL読み込みを記述
    リソースDLLの読み込み処理を、LoadStringの初回呼び出しの前に記述します。
    実行時の言語設定にあったDLLを読み込む必要があります。
    World Wide Naviは現在のLCID (ロケールID)をGetUserDefaultLCID関数によって取得し、 それをISO-639言語コードに変換してから適切なDLLを読み込みます。
    以下はWorld Wide Naviによって作成されたサンプルコードです。

    Private wwnaviH As Long
    
    Function WwnaviLoadLibrary()
    As Long
     Dim libName As String
     Dim langName As String * 10
     Dim langName2 As String
     Dim lcId As Long
     Dim rslt As Long
     Dim posNull As Long
     Dim cnt As Integer
     Dim i As Integer
     "lcId = GetThreadLocale()
     lcId = GetUserDefaultLCID()
     rslt = GetLocaleInfo(lcId,
    LOCALE_SISO639LANGNAME, langName, 10)
     posNull = InStr(langName,
     Chr$(0))
     langName = Left$(langName,
    posNull - 1)
     langName2 = ""
     cnt = Len(langName)
     For i = 1 To cnt
     If Mid(langName,
    i, 1) <> " " Then
     langName2 =
     langName2 & Mid(langName, i, 1)
     End If
     Next i
     libName = "./" &
    langName2 &
    "/wwnavi_string_VBTest.dll"
     wwnaviH =
    LoadLibrary(libName)
     If wwnaviH = 0 Then
     wwnaviH =
     LoadLibrary("./wwnavi_string_VBTest.dll")
     End If
     WwnaviLoadLibrary = wwnaviH
    End Function
    
    Function WwnaviGetModule() As Long
     WwnaviGetModule = wwnaviH
    End Function
    
    Function WwnaviGetString(
    id As Long) As String
     Dim buf As String * 512
     Dim rslt As Long
     If WwnaviGetModule()
    = 0 Then
     WwnaviLoadLibrary(*1)
     End If
     rslt = LoadString(
    wwnaviH, id, buf, 512)
     WwnaviGetString = buf
    End Function

    wwnaviH … DLLモジュールへのポインタ
    LoadLibrary … DLLを読み込みポインタへセットする関数
    GetUserDefaultLCID … 実行時のロケールIDを取得する関数
    GetLocaleInfo … ロケールIDから文字列情報を取得する関数
    *LCIDから変換された現在の言語コードのDLLを読み込むか、 または適切なDLLがない場合はデフォルトのものを読み込みます。

    *1)リソースDLLがまだ読み込まれていない場合に読み込みます。 これは一回の実行に一度だけ呼び出される必要があります。

    5. フォントの切り替え
    フォーム、ラベル、ボタンなどのフォントはVisual Basic 6.0 IDEのGUIによってセットされるため、 フォームのコードを手動で編集することはできません。 (もし行った場合はIDEはエラーを表示します)
    代わりに、Form_LoadイベントでリソースDLLから読み込まれたフォント名称をセットするのが、 フォントを動的に切り替えるためのよい解決策と言えます。 (フォント切り替えは全てのアプリケーションに必要ではありません、それはGUIの設計に依存します。)

    Form1.frm
    ...
    VERSION 5.00
    Begin VB.Form Form1
     Caption
    = "Form1"
     ClientHeight
     = 1530
     ...
     BeginProperty Font
     Name
     = "MS PGothic" (*1)
     Size
     = 8.25
    
    ...
    
    Private Sub Form_Load()
     WwnaviSetCaption
    End Sub
    
    Private Sub WwnaviSetCaption()
     Form1.Caption
    = wwnaviGetString(102) " "Form1"
     "Form1.Font.Name
     = "Lucida Sans Unicode"
     Form1.Font.Name
     = wwnaviGetString(103) (*2) " "MS PGothic"
     Command1.Caption
     = wwnaviGetString(104) " "Button1"
     "Command1.Font.Name
    = "Lucida Sans Unicode"
     Command1.Font.Name
     = wwnaviGetString(105) " "@Arial Unicode MS"
     Label1.AutoSize
     = True
     Label1.Font.Charset
     = WwnaviGetCharSet(WwnaviGetCodePage)
     Label1.Caption
     = wwnaviGetString(106) " "Label1"
     "Label1.Font.Name
     = "Lucida Sans Unicode"
     Label1.Font.Name
     = wwnaviGetString(107) " "Ms Mincho"
    End Sub

    *1)IDEによるデフォルトフォント。これは自動生成されたコードであり、手動で編集できません。

    *2)フォントをDLLから読み込まれた現在の言語に適切なものに切り替えています。

    6. リソースファイルをDLLにコンパイルする
    RCコマンド(Visual Studioツールに含まれます)とVisual Basic DLLプロジェクトを使って、 リソースファイル(.rc)をDLL(.dll)にコンパイルします。

    1. Visual Basic DLLプロジェクトは .resファイル(RCコマンドによってコンパイル)しか読み込めないため、 .rcファイルをこのコマンドで作成します。

    2. .resファイル作成後、それをコンパイルするためのDLLプロジェクトを、 Visual Basicアドインの”Rsource Editor”をロード、有効にした状態で作成します。

    3. EXEとDLLを一度にコンパイルするために、ソースプロジェクトとDLLプロジェクトを含んだVisual Basicグループを作成します。

    World Wide Naviはこれらの手順を、 1.のための.batファイル、2.のためのDLLプロジェクトファイル、3.のためのグループファイルを作成することにより、 自動化しています。
    World Wide Naviによって作成されたコードは、実行ファイルと同じディレクトリにあるDLLをデフォルトとみなし、 各言語コードのディレクトリにあるDLLをその言語用のものとみなします。
    例えば日本語のリソースの場合、以下のようにDLLを作成します。

    ./Foo.exe
    ... 実行ファイル
    ./wwnavi_string.rc
     -> ./wwnavi_string.res
    -> ./wwnavi_string.dll
    ... <- * デフォルトDLL
    ./wwnavi_string_ja.rc
    -> ./wwnavi_string_ja.res
    -> ./ja/wwnavi_string.dll
    ... <- * 日本語DLL