VC++のフォームアプリケーションで、フォームとは無関係なリソース(例えばイメージ)をそのフォームのresXに追加することはできるのですが、何かの拍子に消えてしまいます(おそらく、フォームデザイナがヘッダーファイルを生成ときのタイミングだと思います)。
VC++のフォームプロジェクトにあるフォームは、ソリューションエクスプローラー内においては、ソースコードは「<フォーム名>.h」でその下の階層に「<フォーム名>.resX」という表示になっています。このresXを開くとリソースの一覧が表示されて、編集可能となっています。そこで、イメージなどのリソースを追加できるのですが、何故か消えてしまうのです。
そこで、フォームとは別なところにリソースを定義して、プログラムで読み取ろうということですが、少なくとも「rcファイル」はmanagedなプロジェクトでは意味がありません。なぜ、Formアプリケーションのプロジェクトに存在しているかはわかりませんのは、おそらくアプリケーションのアイコンの設定するためなのだが、.NETのドキュメントを読むとrcファイルのリソースは利用できませんと書いてあります。
managedなモジュール(Assemblyといったほうが適切か…)にこの手のリソースを組み込む方法はいくつか存在するようですが、新たにresXファイルを追加してそこにリソースを定義するという方法をやってみました。
空のresXファイルを作る
プロジェクトに組み込むresXファイルを用意します。resXといっても所詮XMLファイルなので、ベタな方法として「メモ帳」で作ることにします。ただし、中身がresXの定義に則してないとIDE上で編集できないですし、ビルド時にエラーになるので、最低限の定義だけを書いておきます。
必要な部分だけ、プロジェクト内にあるresXからコピペするのですが、まず、プロジェクトにある(エラーになっていない)resXファイルをXMLエディタで開きます(コンテキストメニューから「ファイルを開くアプリケーションの選択」というのを選ぶ)。そのresXファイルから、最初の「<?xml version="1.0" encoding="utf-8"?>
」から、「</resheader>
」の部分まで(たぶん、「<resheader name="writer">
」の対になっているのが最後のなので、そこまでをコピー、ペーストします。そのあとの行に「</root>
」でrootを閉じればOKです。
ファイルは、拡張子をresXにしてUTF-8で保存します。拡張子よりも前の部分(いわゆるbasename)はプログラムで読み込むときに指定するので、わかり易いものにしておいたほうがよいでしょう。
プロジェクトに追加する
作った空のresXファイルをプロジェクトのコンテキストメニューで「追加→既存の項目」で追加すると、ソリューションエクスプローラー上でプロジェクトの下の「リソースファイル」というツリーの中に現れるはずです。そうしたら、そのresXファイルを開くと、resX用のリソース定義用のビュー(マネージリソースエディタ)が表示されます。
そこで、好きなリソースを追加してください。
リソースの読み込み
ManagedなC++のコードの中でリソースを読み込む方法ですが、まずResourceManagerでresXに定義されたリソースを読み込みます。resXファイル名のbasenameを「リソース名」ということにすると(「hoge.resX」なら「hoge」)。
//アセンブリを取得する
System::Reflection::Assembly^ assembly = System::Reflection::Assembly::GetExecutingAssembly();
//リソースを読み込む
System::Resources::ResourceManager^ resources =
gcnew System::Resources::ResourceManager("<アセンブリ名>.<リソース名>", assembly);
ここでの「アセンブリ名」といっているのは(この言い方が正しいかは不明)、普通はプロジェクト名になっているのでプロジェクト名にします。
あとは、ResourceManagerなどのドキュメント、サンプルを見ると使い方がわかりますが、例として、イメージを読み込む場合は以下のような感じになります。
//リソースからイメージを読み込む
System::Drawing::Bitmap^ image = (System::Drawing::Bitmap^)(resources->GetObject(L"<リソースオブジェクト名>"));
ここでの「リソースオブジェクト名」は、resXの定義で命名したものを指定します。マネージリソースエディタでイメージファイルを読み込むとファイル名のbasenameになりますが、エディタ上で変更できます。
この場合、リソースファイルを手動で追加しましたが、いわゆる国際化(カルチャー毎の設定)も対応しているはずなので、ファイル名にカルチャー名を付加したresXファイルを用意しておけば、ResourceManagerで適切に処理されるはずです。