簡単そうなことなのに、ちょっとハマったのでメモ。
FireMonkeyでTImageに文字や図形などを初めて描く場合は、先にImage->Bitmapのサイズを指定する必要がある。
ImageとBitmapのサイズが異なってもよいが(WrapModeで描画結果が変わる)、ここはシンプルに同じ大きさを指定したい場合の話。たとえば以下のように書けば何の問題もない。
1 2 |
Image->Bitmap->Width = Image->Width; Iamge->Bitmap->Height = Image->Height; |
だがちょっとまだるっこしいので1行で書きたい。こうも書ける。
1 |
Image->Bitmap->SetSize( Image->Width, Image->Height ); |
Imageの名前(この例では”Image”だが)を3回も書くのも面白くない。TImageにもTBitmapにもSizeプロパティがある。これを使おうと、以下のように書いてみると、エラーになる。
1 |
Image->Bitmap->Size = Image->Size; //エラー |
TSizeとTSizeF
FireMonkeyの場合、TImageに限らず、TMemoやTButtonなどTControl派生のコンポーネントは、位置やサイズ情報を実数値(float)でも持つ。VclのTSizeでなくTSizeF、TPointでなくTPointF、そしてTRectの代わりにTRectF。
ところがTControl派生でないTBitmapの場合、Sizeプロパティは整数型のTSize。このため単純な代入は出来ない。
たとえば、四角形の領域を、指定されたビットマップから現在のビットマップへコピーするCopyFromBitmapメソッドの宣言。RectもPoint(X,Y)も整数になっている。
1 2 3 |
void __fastcall CopyFromBitmap(TBitmap* const Source, const System::Types::TRect &SrcRect, int DestX, int DestY) |
で、こうした実数型のクラスには整数型に変換するメンバ関数Round/Trunk/Ceilingが用意されている。それぞれ四捨五入、切り捨て、切り上げ。
・
というわけで、以下のように書き換えてみる。
1 |
Image->Bitmap->Size = Image->Size.Round(); // エラー |
やはりエラー。
TSizeFとTControlSize
実はTControl派生クラスのSizeプロパティはTSizeFでなくTControlSizeだった。
このTControlSizeはPixel値(整数)のメンバHeight / Widthと、TSizeF型のメンバSizeを持つ。ややこしい。
というわけで、ImageのサイズにImage->Bitmapのサイズを合わせるシンプルなコードは以下の通り。
1 |
Image->Bitmap->SetSize( Image->Size->Size.Round() ); |
微妙にシンプルでもない気もする。