プリント基板設計・シミュレーション

TOP > アポロレポート > コラム > 第71回 プログラミングについて『ウィンドウのアイコン』
コラム
2024/05/23

第71回 プログラミングについて『ウィンドウのアイコン』

アポロレポート

 前回のプログラムを試してみましたか? とっても楽しくなかったかなと思います。今回もあまり楽しくないとは思いますが、Windowsのプログラムを始めた頃には一体どうやってやればいいのか分からないことばかりですので、基本的な部分の話をしていきましょう。
 まず前回のソースコード。

 #include <afxwin.h>

 class MyApp : public CWinApp
 {
  public:
   virtual BOOL InitInstance();
 };

 class MyWnd : public CFrameWnd
 {
  public:
   MyWnd();
 };

 class MyApp MyApp;

 BOOL MyApp::InitInstance()
 {
  m_pMainWnd = new class MyWnd;

  return TRUE;
 }

 MyWnd::MyWnd()
 {
  Create(NULL,"",WS_OVERLAPPEDWINDOW | WS_VISIBLE ,rectDefault);
 }

 このプログラムを動かしてみると、左上のアイコンがディフォルトのつまらないものであることに気が付いたと思います。何もしていないので当然のことなのです。そこでまず、自分で作ったアイコンに変えてみましょう。
 ということは、アイコンを作らなければならないので、Visual C++の開発環境を使用することになります。まず、『ファイル』をクリックして『新規作成』を指定して下さい。そうすると、作成するファイルの種類を聞いてきますので、『アイコンファイル』を指定します。
 アイコンエディタが起動しますので、適当にアイコンをデザインして下さい。終了は『ファイル』をクリックして『名前を付けて保存』を指定し、アイコンファイルの名称を指定します。ここでは、myapp.ico としておきましょう(別のファイル名でも構いません)。
 悲しいかな、アイコンファイルが出来上がったからといっても、これを直接プログラムで使用することができないのです。Windowsのプログラムを始めたばかりの頃は、このファイルをどうやってプログラムで使用するのかが分からず、無駄に時間を費やしたものでした(この無駄が大切なのかもしれませんが)。
  アイコンファイルが直接利用できないということは、何か他の手段があるはずです。
 それがリソースファイルです。ファイルの拡張子は .res のファイルですがこのファイルがバイナリファイルですので、直接テキストエディタでみることはできません。Visual C++はこのファイルを直接作成することもできますが、私はテキスト形式のリソースファイルを作成しておいて、リソースコンパイラを使用してこのファイルに変換しています。好みの問題なのですが、テキスト形式の場合はその内容がテキストエディタで直接見ることも、編集することもできるので私はこの方法を使用しています。
 それではそのリソースファイルを作成してみましょう。再びVisual C++の『ファイル』をクリックして、『新規作成』を指定します。先ほどと同じく作成するファイルの種類を聞いてきますので、『リソース スクリプト』を指定します。そうすると『Script1』というホルダーが表示されます。ここでまた何をしていいのかが分からず、途方に暮れてしまうと思います。まず、右ボタンをクリックして下さい。するとメニューが表示されますので、『インポート...』を指定して下さい。そうすると、ファイル名を選択するダイアログが開きますので、先ほど作成したアイコンファイルを選択します。
 再びアイコンエディタが起動しますが、これは終了させて下さい。そうすると、先ほどのホルダーに『Icon』と言うホルダーが追加され、『ID_ICON1』という名前のアイコンが追加されます。実際にはこの名前は文字列の名前ではなく、定数名です。このまま『ID_ICON1』とVisual C++が勝手に付けた名前を使用してもいいのですが、ある程度大きいプログラムを作るのであれば、このままだと後になってプログラムを見ると意味が分かりずらくなるので、この名前を自分で変更しましょう。
 アイコンの名前の他、ダイアログの名前なども同じで、自由に名前を付けることができます。名前は整数の定数の定数名か、文字列のどちらかにすることができます。ここでは定数名に『ID_MYAPP_ICON』にすることにします。まず、表示されているアイコン上にカーソルを移動して、右ボタンをクリックします。すると、メニューが表示されますので『プロパティ』を指定します。プロパティのダイアログが表示されますので、『ID』ののエディットボックスの内容を、『ID_MYAPP_ICON』として下さい。もし文字列で名前を指定するときには、"MYAPPICON" などとダブルクォーテーションで囲んで指定します。
 これで、アイコンを追加することができましたので、『ファイル』をクリックし、『名前を付けて保存』を指定し、リソースファイル名を指定して保存して下さい。ここでは、myapp.rc とします。

 このリソースファイルはテキストエディタでみることができます。見てみると、色々と意味の不明なものが記述されていますが、とりあえずはあまり気にしないでいて下さい。このファイルの他に、resource.h と resource.fd の2つのファイルが作成されています。resource.h は実際にアプリケーションプログラムもリソースのID番号を使用するときにインクルードして使用します。resource.fd はVisual C++が使用するだけですので、あまり気にしないで下さい。

 ここまでの手順は説明の都合でアイコンファイルを先に作成しましたが、リソースファイルを先に作成して、アイコンを追加定義する順序が一般的です。

 さて、リソースファイル(ソース)はできましたが、このファイルをバイナリのリソースファイルに変換しなければなりません。それには次のように行ないます。

 rc /r myapp

rc というのはVisual C++に付いているリソースコンパイラです。これを実行すると、

 myapp.res

というファイルが作成されます。このファイルが実際にアプリケーションプログラムを作成するときに使用されるファイルです。だからと言ってプログラムの実行時にこのファイルを読み込むのではなく、プログラムのリンク時に一緒にリンクしてしまうのです。前回ちょっと触れたリンクの方法が次のものだったことを思い出して下さい。

 link /incremental:no /subsystem:windows /release
       オブジェクトファイル名 [ライブラリファイル名] リソースファイル名

このコマンドラインのリソースファイル名に myapp.res を指定すれば一緒にリンクされます。

 それでは、リソースファイルを一緒にリンクして実行してみましょう。前回と同じ様にウインドウが開きます。が、しかし、アイコンは変わっていません。ガッカリして下さい。Windowsのプログラムはだいたいこんなものです。アイコンはプログラムに組み込まれたのですが、そのアイコンを使用するとは何もまだプログラムには記述していないので、当然といえば当然です。

 アイコンリソースが組み込まれていても、プログラムはそのままでは利用することができません。アイコンリソースを実行時に使えるようにするには、それをロードする必要があります。そのロードを行なえるのが、CWinApp クラス(またはそれから派生したクラス)です。このクラスには、

 HICON LoadIcon(UINT nIDResource) const;

 HICON LoadIcon(LPCTSTR lpszResourceName) const;

の2種類のメンバー関数が用意されています。リソースファイルのアイコンに整数の定数名を付けたときには前者を、文字列の名前を付けたときには後者を使用してリソースからアイコンをロードします。ここでは前者ですので、MyApp クラスの Initinstanceで、

 BOOL MyApp::InitInstance()
 {
  HICON my_icon;

  m_pMainWnd = new class MyWnd;

  my_icon=LoadIcon(ID_MYAPP_ICON);

  return TRUE;
 }

とすればロードできますが、ロードはできても実際のウインドウにはまだ生かされません。次に CWnd クラス(またはその派生クラス)にロードしたアイコンを結び付けるには、CWnd クラスのメンバー関数 SetIcon を使用します(詳しいことはヘルプを見て下さい)。
 もう1つ忘れていました。このプログラムは ID_MYAPP_ICON という定数のことはまだ知らないので、Visual C++が勝手に作った resource.h にその定数が記述してありますので、このファイルもインクルードするようにします。

 HICON SetIcon(HICON hIcon,BOOL bBigIcon);

この第1引数にロードしたアイコンのハンドル番号(Windowsが勝手に付ける実行時のID番号で、この場合は CWinApp::LoadIconの戻り値)を指定し、2番目の引数には TRUE を指定します。そこで、上の InitInstance を次のように書き換えると、プログラム全体は、

 #include <afxwin.h>
 #include "resource.h"

 class MyApp : public CWinApp
 {
  public:
   virtual BOOL InitInstance();
 };

 class MyWnd : public CFrameWnd
 {
  public:
   MyWnd();
 };

 class MyApp MyApp;

 BOOL MyApp::InitInstance()
 {
  m_pMainWnd = new class MyWnd;

  m_pMainWnd->SetIcon(LoadIcon(ID_MYAPP_ICON),TRUE);

  return TRUE;
 }

 MyWnd::MyWnd()
 {
  Create(NULL,"",WS_OVERLAPPEDWINDOW | WS_VISIBLE ,rectDefault);
 }

 となります。このプログラムをコンパイル、リンクして実行してみて下さい。これで、ウインドウのアイコンが自分の作ったものになりました。

 ウインドウのアイコンを設定する方法には他にもありますが、多分これが最も簡単な方法だと思います。簡単と言っても、実際にウインドウのアイコンが変更できるまでには、たくさんの手続きを行なわなければならないので、面倒と言えば面倒です。

 今回の説明で、プログラムのコードとリソースの関係が少しは理解できたでしょうか。WindowsのプログラムはDOSなどの文字ベースのプログラムと比べて、プログラムの本体の他に行なうことが段違いに多くなりますが、結構これも楽しい部分かも知れません。

 それではまた次回。


そのお悩み、
アポロ技研に話してみませんか?

アポロ技研でワンランク上の物創りへ!
そのお悩み、アポロ技研に話してみませんか?