Win32/64技術 006 コンソールアプリケーションでリソースを使おう
次の記事:[[Win32/64技術 007]]
概要
レジストリから文字列を取得できるというテストをやるために、リソースを保有するアプリケーションを作ってみよう。
まずコンソールアプリケーションを作ってみよう。特に何もしないアプリケーションでいいよね。さみしいからリソースから設定した文字列を読み込むプログラムにしてみましょう。コンソールアプリケーションを作る基礎の基礎は説明済みなのです。こちらあたりを読むといいでしょう。
先にmain関数まわりに打ち込むべきプログラムを示します。
#include <Windows.h>
#include <iostream>
#include "resource.h"
#include <locale.h>
#include <io.h>
#include <fcntl.h>
int main(){
HINSTANCE hInstance = GetModuleHandle(NULL);
wchar_t buffer[256];
int originalMode = _setmode(_fileno(stdout), _O_TEXT);
if (LoadString(hInstance, IDS_STRING104, buffer, sizeof(buffer) / sizeof(buffer[0])) > 0) {
// UTF-8 にコンソールを設定
_setmode(_fileno(stdout), _O_U8TEXT);
// Unicode 日本語文字列を表示, bufferも表示できる。
wprintf(L"こんにちは、世界!\n");
std::wcout << buffer << std::endl;
// 元のモードに戻す。元のモードだとsjisに変換しないと駄目になる。
_setmode(_fileno(stdout), originalMode);
// SJISに変換
int requiredSize = WideCharToMultiByte(CP_ACP, 0, buffer, -1, NULL, 0, NULL, NULL);
if (requiredSize > 0) {
char* sjisBuffer = new char[requiredSize];
WideCharToMultiByte(CP_ACP, 0, buffer, -1, sjisBuffer, requiredSize, NULL, NULL);
// 読み込んだ文字列をSJISとして表示
std::cout << sjisBuffer << std::endl;
delete[] sjisBuffer;
}
else {
std::cerr << "Failed to convert to SJIS." << std::endl;
}
}
else {
std::cerr << "Failed to load string resource." << std::endl;
}
return 0;
}
で、このプログラムを入力した上で、リソースを作る必要がありますので、ソリューションエクスプローラから[リソースファイル]フィルタの上で右クリックして表示されるメニュー[追加]-[リソース]を選択します。UIから追加するリソースはプロジェクト名と同じもの一つだけです。複数のリソースファイルを設定することもできます。vcxprojファイルに直接テキスト編集する方法については別の記事で言及したいと思います。
そして、文字列リソースを追加するため、ソリューションエクスプローラからプロジェクト名.rcを右クリックして、メニュー[追加]-[リソース]を選択します。すると今度はリソース選択ダイアログが表示されるので、項目から[String Table]を選択します。
すると文字列編集エディタが立ち上がるので、ID・値・キャプションの3つのセットで一つの文字列リソースとなります。IDはIDS_STRING102、値は102から始まり、キャプション欄は空白になっていますので、ダブルクリックして日本語やら英語で適当に文字を打ち込んでもいいです。ここでは、自分は以下のように入力しました。
ID 値 キャプション
IDS_STRING102 9000 接続したときの音
IDS_STRING103 9001 エラーの時の音
IDS_STRING104 9002 転送したときの音
このようにして保存すると、ヘッダファイルresource.hも自動で生成されて、以下のようになります。
//{{NO_DEPENDENCIES}}
// Microsoft Visual C++ で生成されたインクルード ファイル。
// ConsoleResource.rc で使用
//
#define IDS_STRING102 9000
#define IDS_STRING103 9001
#define IDS_STRING104 9002
// Next default values for new objects
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE 101
#define _APS_NEXT_COMMAND_VALUE 40001
#define _APS_NEXT_CONTROL_VALUE 1001
#define _APS_NEXT_SYMED_VALUE 9003
#endif
#endif
下の方の_APSなんちゃらは自動発番を管理するためのモノなので、つじつまが合う程度にいじると良いでしょう。「IDS_STRING102 9000」でresource.hが設定され、「IDS_STRING102 9000 接続したときの音」というリソースの設定がされているので、
IDS_STRING102,9000, "接続したときの音" というのが重要な組み合わせになります。コンソールアプリケーションでもリソースにアイコンも追加できるので、これも追加して生成したアプリケーション.exeのアイコンが変化するのを確かめるのも勉強になるでしょう。実行したときのアイコンは変えられませんけどね。
これでビルド(メニュー[ビルド]-[ソリューションのビルド])すると、リソースを保有したアプリケーションが生成できます。お試しなのでDebug版だけでもビルドできれば十分でしょう。
同じようにアイコンも追加してみましょう。アイコンは生成したアプリケーションをフォルダ・ファイルのエクスプローラで閲覧したときの表示アイコンに影響を与えます。でも実行したときのコンソールアプリケーションのアイコンまでは変えられません。なんて中途半端なのかしら。だから使われないんだな、コンソールアプリケーションのアイコンリソース。中途半端…。残念だな!
アイコンリソースを追加するため、ソリューションエクスプローラからプロジェクト名.rcを右クリックして、メニュー[追加]-[リソース]を選択します。すると今度はリソース選択ダイアログが表示されるので、項目から[Icon]を選択します。規定値のアイコンが追加されます。表示されたアイコンウィンドウを保存して終わりにしましょう。
これでリソースを追加した関連のスクリプトが以下のように追加されます。
resource.h
//省略
#define IDI_ICON1 101
//省略
resourceスクリプト プロジェクト名.rc
//省略
/////////////////////////////////////////////////////////////////////////////
//
// Icon
//
// Icon with lowest ID value placed first to ensure application icon
// remains consistent on all systems.
IDI_ICON1 ICON "icon1.ico"
//省略
ってな感じになったと思う。感じでいいよね。全く同じでなくても、つじつまが合っていて目的を達成できている構文になっていればいいってことですね。LoadStringは意味あるけど、LoadIconは意味ないっす。ちなみに無駄にLoadする命令は以下のとおりです。main関数の中にかけるよ。
HICON hIcon = LoadIcon(GetModuleHandle(NULL), MAKEINTRESOURCE(IDI_ICON1));
if (hIcon) {
std::cout << "Icon loaded successfully." << std::endl;
DestroyIcon(hIcon);
}
else {
std::cerr << "Failed to load icon." << std::endl;
}
以上、コンソールアプリケーションでも、リソースは使えるという情報でした。
次の記事:[[Win32/64技術 007]]