テクニカル ノート 57: MFC コンポーネントのローカライズ
Note
次のテクニカル ノートは、最初にオンライン ドキュメントの一部とされてから更新されていません。 結果として、一部のプロシージャおよびトピックが最新でないか、不正になります。 最新の情報について、オンライン ドキュメントのキーワードで関係のあるトピックを検索することをお勧めします。
このノートでは、MFC が使用されているアプリケーション、OLE コントロール、DLL などのコンポーネントをローカライズするときに使用できる設計や手順について説明します。
概要
MFC が使用されているコンポーネントをローカライズする場合、解決すべき問題が 2 つあります。 まず、ご自身のリソースをローカライズする必要があります。これは、コンポーネントに固有の文字列、ダイアログなどのリソースです。 また、MFC を使用して構築されたほとんどのコンポーネントに、MFC で定義されたリソースが多数含まれ、使用されています。 ローカライズされた MFC リソースも提供する必要があります。 幸い、MFC 自体に複数の言語が既に用意されています。
さらに、お使いのコンポーネントを、ターゲット環境 (ヨーロッパ環境または DBCS 対応環境) で動作するように準備する必要があります。 これは、ほとんどの場合、お使いのアプリケーションが、高位ビットが設定された文字を正しく処理し、ダブルバイト文字を含む文字列を扱うかにかかっています。 MFC は、この両方の環境で既定で有効になっているため、セットアップ時にさまざまなリソースを接続するだけで、すべてのプラットフォーム上で使用される単一のワールドワイド バイナリを持つことができます。
コンポーネントのリソースのローカライズ
ご自身のアプリケーションまたは DLL をローカライズするには、リソースを、ターゲット言語のリソースに置き換えるだけです。 独自のリソースについては、比較的シンプルで、リソース エディターでリソースを編集し、ご自身のアプリケーションをビルドします。 お使いのコードが適切に書かれていれば、ローカライズしたい文字列やテキストが C++ のソースコードにハード コーディングされることはありません。リソースを変更するだけで、すべてのローカライズが可能です。 実際、ローカライズ バージョンを提供するときに、オリジナル コードをビルドする必要がないように、ご自身のコンポーネントを実装することができます。 これはさらに複雑ですが、その価値は十分にあり、MFC 自体のための選ばれたメカニズムです。 EXE ファイル や DLL ファイルをリソース エディターに読み込み、リソースを直接編集することで、アプリケーションをローカライズすることも可能です。 可能ではありますが、新しいバージョンのアプリケーションをビルドするたびに、これらの変更を再適用する必要があります。
これを回避する方法として、個別の DLL (サテライト DLL と呼ばれることもあります) 内のすべてのリソースを検索する方法があります。 その後、この DLL は実行時に動的に読み込まれ、リソースは、すべてのコードが含まれるメイン モジュールからではなく、その DLL から読み込まれます。 MFC では、このアプローチを直接サポートしています。 MYAPP.EXE と呼ばれるアプリケーションを考えてみましょう。このアプリケーションのリソースはすべて、MYRES.DLL という DLL に格納されている可能性があります。 アプリケーションの InitInstance
では、次の処理を実行してその DLL を読み込み、MFC によってその場所からリソースが読み込まれるようにします。
CMyApp::InitInstance()
{
// one of the first things in the init code
HINSTANCE hInst = LoadLibrary("myres.dll");
if (hInst != NULL)
AfxSetResourceHandle(hInst);
// other initialization code would follow
// ...
}
それ以降、MFC は、myapp.exe からではなく、その DLL からリソースを読み込みます。 ただし、その DLL 内には、すべてのリソースが存在していなければなりません。MFC が特定のリソースを探すために、アプリケーションのインスタンスを検索することはありません。 この手法は、OLE コントロールのほか、通常の MFC DLL にも同様に適用されます。 ユーザーが希望するリソース ロケールに応じて、適切なバージョンの MYRES.DLL が、お使いのセットアップ プログラムによってコピーされます。
リソースのみの DLL については、比較的容易に作成できます。 DLL プロジェクトを作成し、そのプロジェクトにご自身の .RC ファイルを追加して、必要なリソースを追加します。 この手法が使用されていない既存のプロジェクトがある場合は、そのプロジェクトからリソースをコピーできます。 リソース ファイルをプロジェクトに追加したら、プロジェクトをビルドする準備はほぼ完了です。 あとは、リンカー オプションに /NOENTRY を含めるように設定するだけです。 これにより、DLL にエントリ ポイントがないことをリンカーに伝えます。コードがないため、エントリ ポイントもありません。
Note
Visual C++ 4.0 以降のリソース エディターは、.RC ファイルあたり複数の言語をサポートしています。 これにより、1 つのプロジェクト内でご自身のローカライズを簡単に管理できるようになります。 各言語のリソースは、リソース エディターによって生成されるプリプロセッサ ディレクティブで制御されます。
提供されている MFC ローカライズ済みリソースの使用
ビルドする MFC アプリケーションはすべて、MFC から 2 つの要素、つまりコードとリソースを再利用します。 つまり、MFC には、さまざまなエラーメッセージ、組み込みダイアログなど、MFC クラスによって使用されているリソースが用意されています。 ご自身のアプリケーションを完全にローカライズするには、アプリケーションのリソースだけでなく、MFC から直接取得するリソースもローカライズする必要があります。 MFC では、さまざまな言語のリソース ファイルが自動的に提供されます。このため、対象言語が MFC によって既にサポートされている場合は、そのローカライズされたリソースを使用するようにするだけです。
このドキュメントの作成時点で MFC がサポートしているのは、中国語、ドイツ語、スペイン語、フランス語、イタリア語、日本語、韓国語です。 これらのローカライズ バージョンを含むファイルは、MFC\INCLUDE\L.* ("L" は Localized の略) ディレクトリ内にあります。 たとえば、ドイツ語ファイルは MFC\INCLUDE\L.DEU にあります。 これらの RC ファイルが、MFC\INCLUDE 内のファイルの代わりに、アプリケーションで使用されるようにするには、/IC:\PROGRAM FILES\MICROSOFT VISUAL STUDIO .NET 2003\VC7\MFC\INCLUDE\L.DEU
を、RC コマンド ラインに追加します (これは一例なので、ご自身が選択したロケールと、Visual C++ をインストールしたディレクトリに置き換える必要があります)。
上記の手順は、アプリケーションが MFC と静的にリンクしている場合に有効です。 ほとんどのアプリケーションが動的にリンクしています (AppWizard の既定)。 このシナリオでは、コードだけでなく、リソースも動的にリンクされます。 その結果、お使いのアプリケーション内のリソースはローカライズできますが、MFC の実装リソースは引き続き、MFC7x.DLL (以降のバージョン) または MFC7xLOC.DLL (存在する場合) から読み込まれます。 これには、2 つの異なる角度からアプローチできます。
より複雑なアプローチは、ローカライズされた MFC7xLOC.DLL (ドイツ語の場合は MFC7xDEU、スペイン語の場合は MFC7xESP.DLL)、またはそれ以降のバージョンを配布することです。ユーザーはアプリケーションをインストールするときに、適切な MFC7xLOC.DLL をシステム ディレクトリにインストールします。 この方法は、開発者とエンド ユーザーの両方にとって非常に複雑になる場合があるため、お勧めしません。 この手法と注意事項の詳細については、「テクニカル ノート 56」を参照してください。
最も簡単で安全なアプローチは、ローカライズされた MFC リソースを、ご自身のアプリケーションまたは DLL 自体 (あるいは、そのサテライト DLL (使用している場合)) に含めることです。 これにより、MFC7xLOC.DLL のインストールに伴う問題を回避できます。 これを行うには、上記に示した静的なケースと同じ手順に従います (ローカライズされたリソースを指定するように RC コマンド ラインを適切に設定します)。ただし、AppWizard によって追加された /D_AFXDLL
定義も削除する必要があります。 /D_AFXDLL
が定義されていると、実際、AFXRES.H (および他の MFC RC ファイル) ではどのリソースも定義されません (MFC DLL からプルされるため)。