戻る ホーム 上へ 進む

2.9 TIcon

TIcon は TGraphic の継承クラスの中で最も単純なクラスです。TIcon に出来ることは、ファイルやストリームからアイコンファイルを読む、ファイルやストリームへアイコンを書き込む、アイコンを表示する、の3点しかありません。アイコンイメージを操作するような機能は何もありません。解説する項目はあまり有りませんが、以下に TIcon の機能を解説します。

尚、本節は Delphi 5/6 の TIcon のみを扱います。Delphi 4 以前の TIcon は動作が異なりますがここでは解説しません。

2.9.1 アイコンファイルの基礎

ここでは、解説を始める前にアイコンファイルについて復習を簡単にしておきます。

アイコンの際立った特徴は、表示サイズがシステムによって決められるという点です。DIB 等のビットマップを表示する場合は、ビットマップをどのような大きさで表示するかはアプリケーションが決めることです。一方、アイコンの場合は、キャプションの左隅や、Explorerに表示される時は Windows や Exploler が表示サイズを決定します。Win32 の場合は、4種の表示サイズを Windows や Explorer が Video System の解像度等から決定します。このため、アイコンファイルには、どんな表示サイズや色数でも良い品質でアイコンが表示できるように、いろいろなサイズ/色数で描かれた複数のアイコンイメージ入っているのが普通です。以下にアイコンファイルの構造を示します。

Figure 2.9-1

図2.9-1 アイコンファイルの構造

ここでアイコンファイルの構造について詳しく説明するつもりはありません。詳しくは、MSDN や www.microsoft.com にある 「Icons in Win32」をみてください。

通常アイコンイメージはリソースの中に入れて使用しますが、Windows API は アイコンファイル(*.ico) を読むための専用 API を用意していません。逆に TIcon はファイルやストリームを入出力の対象にし、リソースとの入出力は出来ません。

リソースから LoadIcon API 等でアイコンを読む場合は、Windows が自動的に適切なアイコンイメージを選択します。一方 TIcon は アイコンファイル を読み込む時に独自のアルゴリズムでアイコンイメージを選択して読み込みます。

2.9.2 アイコンファイルの読み込みとアイコンの生成

TIcon は LoadFromStream/LoadFromFile でアイコンをストリームやファイルから読み込むことが出来ます。TIcon はLoadFromStream/LoadFromFileでアイコンファイルの内容をそのまま TIcon内のメモリストリームに格納します。これをアイコンファイルイメージと呼ぶことにしましょう。LoadFromStream/LoadFromFileが行うのはこれだけです。

TIcon が Canvas.Draw によって描画されたり、TIcon のHandle プロパティが参照されたりして、アイコンハンドルが作成されるとき、TIconはアイコンファイルイメージからアイコンを作成します。TIconはアイコンファイルイメージのアイコンディレクトリを読み込んで要求サイズに最も近い大きさで、スクリーンのビデオモードに適切な色数のアイコンイメージを選択します。

要求サイズとはアイコンファイルを読む前に TIcon の Width/Heightプロパティにセットされていた値です。Width/Height に何も設定されなかったときは System Large Size(通常 32x32。GetSystemMetrics API で SM_CXICON、SM_CYICON を指定した場合に得られるアイコンの大きさ)が要求サイズになります。

アイコンイメージの選択は、色数も選択の基準になりますが、現在の ビデオモード の色数が 2/4/16 色で同じ色数のアイコンイメージがあればそれが最も好まれます。ビデオモード が True Color(24bpp) で 8bpp 以上の色数を持つアイコンイメージが有るならばそれが好まれます。そうでなければ

8 bpp 以上 < 1 bpp < 2 bpp < 4 bpp

の優先順位に従ってアイコンイメージが選ばれます。8 bpp 以上の色数を持つアイコンイメージの優先順位が低いことに注意してください。これはアイコンがパレットをもたないため、256色以下のビデオモードでは多色のアイコンを適切に表示できないからです。

アイコンイメージの選択が終わったら

  1. 選択したアイコンから、XORイメージと ANDイメージを取り出します。
  2. CreateIcon API でアイコンハンドルを作成します.。

という手順でアイコンが作られます。

尚、蛇足ですが、カーソルファイル(*.cur) はファイルの先頭の Resource Type(図2.9-1 参照)が2になる以外は アイコンファイルと同じ形式です。しかし、TIcon はこれをチェックしてはじいてしまうため、カーソルファイルの読み込みはできません。

2.9.3 アイコンファイル(ストリーム)への書き込み

TIcon は SaveToStream/SaveToFile でアイコンをストリームやファイルへ書き込むことが出来ます。書き込む手順は以下の通りです。

  1. TIcon内にアイコンファイルイメージが無いならば、アイコンハンドルからアイコンファイルイメージ(アイコンイメージを一個だけ持つアイコンファイルのメモリイメージ)を作成します。
  2. アイコンファイルイメージをファイルやストリームに書き込みます。

アイコンファイルをファイルやストリームから読んだ場合、TIcon は読み込んだファイルのメモリイメージを TIcon 内に持っています。アイコンファイルイメージがある場合はSaveToStream/SaveToFile はこのメモリーイメージをそのまま書き込みます。但し、TIcon の Handle プロパティ に LoadIcon API 等で作成されたアイコンハンドルが代入された場合は、メモリイメージがありません。その場合は、上記の手順1に示すように、メモリイメージを作成してから書き込みます。この場合、16色アイコンのイメージが1個しか入ってないのアイコンファイルイメージが書き出されます。

2.9.4 クリップボードとの入出力

TIcon はクリップボードとの入出力はできません。クリップボードとの入出力(LoadFromClipBoardFormat/SaveToClipBoardFormat メソッド)を行おうとすると、EInvalidGraphicOperation 例外が起こります。

2.9.5 Width/Height プロパティ

TIcon の TIcon の中に アイコンハンドルが無い場合は Width/Height プロパティ は常に、システムの 'System Large Icon' の大きさを返します。つまり

Width = GetSystemMetrics(SM_CXICON)

Height = GetSystemMetrics(SM_CYICON)

となります。TIconを描画するなど、 TIcon内のファイルイメージからアイコンが TIcon 内部に作られると、2.9.2 のアルゴリズムで選択されたアイコンの大きさを返すようになります。

また、TIcon のハンドルプロパティにアイコンハンドルを代入した場合は、Width/Height プロパティの値は、アイコンの大きさに関係なく、'System Large Size'なります。

とても奇妙な動作です。注意してください。例えば TIcon にファイルからアイコンを読み込んだときは Width/Height プロパティが示すアイコンの大きさは System Large Icon ですが、TIcon を Canvas.Draw 等で表示すると、Width/Height の値が変化します。奇妙な仕様だというほか有りません。

2.9.6 アイコンの表示

TIcon の Draw メソッドは Protected なメソッドで、TCanvas の Draw メソッドや、StretchDraw メソッドで、パラメータに TIcon のインスタンスが指定した時に呼び出されます。TIcon の Draw メソッドは TIcon のインスタンス内のアイコンを指定された Canvas の指定された位置に描画する単純なメソッドです。

本来 Draw は指定された位置に指定された大きさで表示しなければならないのですが、実際には、アイコンの大きさでしか表示されません。Win32 では DrawIconEx を使って任意サイズのアイコンの描画が可能ですが、TIconはそうなってはいません。これは DrawIconEx API が無かった Win16 用の Delphi 1 からの伝統です。

2.9.7 アイコンハンドルの取り扱い

TIcon の Handle プロパティ はアイコンのハンドルです。LoadFromStream/LoadFromFile でアイコンファイルを読み込んだ場合は、Handle プロパティ はアイコンファイルから要求サイズとビデオモードに基づいて選択されたアイコンイメージから作成されたアイコンのハンドルです。

Handle プロパティ に代入を行った場合は、古いアイコンは破棄され、新しいアイコンが TIcon のインスタンスの中に取り込まれます。従って、Handle プロパティ に代入したアイコンハンドルは DestroyIcon で破棄しないでください。破棄は TIcon が行います。

逆に TIcon が作成したアイコンハンドルを、TIcon の外に取り出したい場合は ReleaseHanle メソッドを使用します。ReleaseHandle メソッドはアイコンハンドル返し、TIcon のインスタンスを空にします。

2.9.8 TIcon のバグ

2.9.2 で出てきた「要求サイズ」というものは、実は Delphi 5/6 で導入されたものです。それまでは TIcon は常にアイコンイメージの色数からアイコンを選ぶようになっていました。Delphi 5/6 では予め TIcon のWidth/Height プロパティにサイズを設定しておくにより、取り出したいアイコンサイズを指定できるようになりました。

これは大きな進歩なのですが TIcon にはこれに関連してバグがあります。というのは本来「要求サイズ」とは アイコンファイルイメージから取り出したアイコンイメージを使って、要求サイズのアイコンを作成するのが目的なのです。つまり 32x32 のアイコンが要求された場合、32X32 のアイコンが作られなければならないのです。

ところが TIcon が 16X16 のアイコンイメージしか入っていないアイコンファイルを読むと 必ず TIcon は 16x16 のアイコンを作ってしまいます。

TIcon のソースを見ると、取得したアイコンイメージを変形して、要求サイズに直す処理があるのですが、これがバグのために動かなくなってしまっています。この結果、アイコンの大きさは、選ばれたアイコンイメージと同じ大きさになってしまっているのです。これは明らかにミスなので、早急な改善を望みます。

2.9.9 まとめ

TIcon はアイコンファイルを読んで表示する機能を提供します。Window API でこれを実現するのはかなり大変なので便利な機能といえます。
TIcon はアイコンイメージをアイコンファイルイメージから選択するとき、要求サイズに近い大きさで、かつ ビデオモードに適した色数のアイコンイメージを選択します。
TIcon は アイコンを アイコンサイズでしか表示できません。これは、Delphi 1.0J からの伝統です。
TIcon の Handle propety にアイコンハンドルを代入し、SaveToStream/SaveToFile メソッドを呼ぶと、アイコンのイメージが一つしか入っていない16色のアイコンファイル(ストリーム)が書き出されます。
TIconにはバグがあり、TIcon内で作成されるアイコンは要求サイズと異なる大きさになることがあります。

 

戻る ホーム 上へ 進む inserted by FC2 system