「Win32/64技術 006 コンソールアプリケーションでリソースを使おう」の版間の差分

提供:yonewiki
 
編集の要約なし
1行目: 1行目:
[[Win32/64_アプリケーション開発#処理技術|Win32/64_アプリケーション開発]]に戻る。
[[Win32/64_アプリケーション開発#処理技術|Win32/64_アプリケーション開発]]に戻る。


前の記事:[[Win32/64技術 004 文字列グローバル変数にHGLOBALを使う一例]]
前の記事:[[Win32/64技術 005 レジストリ操作]]


次の記事:[[Win32/64技術 006 コンソールアプリケーションでリソースを使おう]]
次の記事:<nowiki>[[Win32/64技術 007]]</nowiki>


== '''概要''' ==
== '''概要''' ==
 
 レジストリから文字列を取得できるというテストをやるために、リソースを保有するアプリケーションを作ってみよう。
 
 
 まずコンソールアプリケーションを作ってみよう。特に何もしないアプリケーションでいいよね。さみしいからリソースから設定した文字列を読み込むプログラムにしてみましょう。[[VC PlusPlus:基本的な使い方|コンソールアプリケーションを作る基礎の基礎]]は説明済みなのです。こちらあたりを読むといいでしょう。
 
 
 先にmain関数まわりに打ち込むべきプログラムを示します。
 
 
<syntaxhighlight lang="cpp">
#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;
}
</syntaxhighlight>
 
 
 で、このプログラムを入力した上で、リソースを作る必要がありますので、ソリューションエクスプローラから[リソースファイル]フィルタの上で右クリックして表示されるメニュー[追加]-[リソース]を選択します。UIから追加するリソースはプロジェクト名と同じもの一つだけです。複数のリソースファイルを設定することもできます。vcxprojファイルに直接テキスト編集する方法については別の記事で言及したいと思います。
 
 
 そして、文字列リソースを追加するため、ソリューションエクスプローラからプロジェクト名.rcを右クリックして、メニュー[追加]-[リソース]を選択します。すると今度はリソース選択ダイアログが表示されるので、項目から[String Table]を選択します。
 
 
 すると文字列編集エディタが立ち上がるので、ID・値・キャプションの3つのセットで一つの文字列リソースとなります。IDはIDS_STRING102、値は102から始まり、キャプション欄は空白になっていますので、ダブルクリックして日本語やら英語で適当に文字を打ち込んでもいいです。ここでは、自分は以下のように入力しました。
 
 
<syntaxhighlight lang="text">
ID            値    キャプション
IDS_STRING102  9000  接続したときの音
IDS_STRING103  9001  エラーの時の音
IDS_STRING104  9002  転送したときの音
</syntaxhighlight>
 
 
このようにして保存すると、ヘッダファイルresource.hも自動で生成されて、以下のようになります。
 
 
<syntaxhighlight lang="cpp">
//{{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
</syntaxhighlight>
 
 
 下の方の_APSなんちゃらは自動発番を管理するためのモノなので、つじつまが合う程度にいじると良いでしょう。「IDS_STRING102                  9000」でresource.hが設定され、「IDS_STRING102  9000  接続したときの音」というリソースの設定がされているので、
 
 
IDS_STRING102,9000, "接続したときの音" というのが重要な組み合わせになります。コンソールアプリケーションでもリソースにアイコンも追加できるので、これも追加して生成したアプリケーション.exeのアイコンが変化するのを確かめるのも勉強になるでしょう。実行したときのアイコンは変えられませんけどね。
 
 
 これでビルド(メニュー[ビルド]-[ソリューションのビルド])すると、リソースを保有したアプリケーションが生成できます。お試しなのでDebug版だけでもビルドできれば十分でしょう。
 
 
 同じようにアイコンも追加してみましょう。アイコンは生成したアプリケーションをフォルダ・ファイルのエクスプローラで閲覧したときの表示アイコンに影響を与えます。でも実行したときのコンソールアプリケーションのアイコンまでは変えられません。なんて中途半端なのかしら。だから使われないんだな、コンソールアプリケーションのアイコンリソース。中途半端…。残念だな!
 
 
 アイコンリソースを追加するため、ソリューションエクスプローラからプロジェクト名.rcを右クリックして、メニュー[追加]-[リソース]を選択します。すると今度はリソース選択ダイアログが表示されるので、項目から[Icon]を選択します。規定値のアイコンが追加されます。表示されたアイコンウィンドウを保存して終わりにしましょう。
 
 
 これでリソースを追加した関連のスクリプトが以下のように追加されます。
 
 
resource.h
<syntaxhighlight lang="cpp">
//省略
 
#define IDI_ICON1                      101
 
//省略
</syntaxhighlight>
 
 
resourceスクリプト プロジェクト名.rc
<syntaxhighlight lang="cpp">
//省略
 
/////////////////////////////////////////////////////////////////////////////
//
// Icon
//
 
// Icon with lowest ID value placed first to ensure application icon
// remains consistent on all systems.
IDI_ICON1              ICON                    "icon1.ico"
 
//省略
</syntaxhighlight>
 
 
ってな感じになったと思う。感じでいいよね。全く同じでなくても、つじつまが合っていて目的を達成できている構文になっていればいいってことですね。LoadStringは意味あるけど、LoadIconは意味ないっす。ちなみに無駄にLoadする命令は以下のとおりです。main関数の中にかけるよ。
 
 
<syntaxhighlight lang="cpp">
    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;
    }
</syntaxhighlight>
 
 
 以上、コンソールアプリケーションでも、リソースは使えるという情報でした。


 
 


前の記事:[[Win32/64技術 004 文字列グローバル変数にHGLOBALを使う一例]]
前の記事:[[Win32/64技術 005 レジストリ操作]]


次の記事:[[Win32/64技術 006 コンソールアプリケーションでリソースを使おう]]
次の記事:<nowiki>[[Win32/64技術 007]]</nowiki>


[[Win32/64_アプリケーション開発#処理技術|Win32/64_アプリケーション開発]]に戻る。
[[Win32/64_アプリケーション開発#処理技術|Win32/64_アプリケーション開発]]に戻る。


 
 

2024年2月2日 (金) 15:39時点における版

Win32/64_アプリケーション開発に戻る。

前の記事:Win32/64技術 005 レジストリ操作

次の記事:[[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技術 005 レジストリ操作

次の記事:[[Win32/64技術 007]]

Win32/64_アプリケーション開発に戻る。