【T1】Delphi/C++テクニカルセッション「VCL ユーザーのためのFireMonkey入門」
株式会社シリアルゲームズ
アプリケーション第３開発部
取締役 細川淳

アジェンダ• はじめに• 画像付きエディットを作る• アニメーションを見る
• まとめ

2

本文書の一部または全部の転載を禁止します。本文書の著作権は、著作者に帰属します。

はじめに

3

本文書の一部または全部の転載を禁止します。本文書の著作権は、著作者に帰属します。

はじめに• 今回の資料は後から見ても解るように詳しい操作手順が書いてあります！
• 時間が余った場合、複数行の TListBoxItem を作ります– ですが、このセッションを最後まで見れば、誰でも作成できるようになっているはずです！

はじめに• VCL と FMX– VCL - Visual Component Library• Windows の進化とともに発展してきたコンポーネント群– FMX - FireMonkey• マルチプラットフォームに対応したコンポーネント群

はじめに• VCL の考え方
Windows のコントロールがベース見た目は Windows が用意したものになる
最近は Style によって見た目を変更できる

はじめに• FMX の考え方
それぞれの OS でコントロールの見た目が違う…めんどくさいから全部自分で描いちゃおうZE！
Style で見た目をコントロール
OS ごとに DirectX / OpenGL / OpenGL ES で描画する

画像付きエディットを作る

9

本文書の一部または全部の転載を禁止します。本文書の著作権は、著作者に帰属します。

画像付きエディットを作る• VCLでは
1. TEdit 継承したエディットを作る→TImageEdit とします
2. TImage を作成し、Parent を TEdit にする
3. TEdit のテキストエリアを変更する

実際に作ってみます。

TImageEdit
unit uImageEdit;

Windows に特化しているのでWinapi をそのまま uses にinterfaceuses
Winapi.Windows, Winapi.Messages, System.Classes, Vcl.Graphics, Vcl.Controls,Vcl.StdCtrls, Vcl.ExtCtrls;

TEdit を継承
type
TImageEdit = class(TEdit)private
画像用 TImage
FImage: TImage;procedure ImageChange(Sender: TObject);
protected
procedure DoImageChanged; virtual;
procedure SetParent(iParent: TWinControl); override;
procedure WndProc(var Message: TMessage); override;
procedure Resize; override;
11

本文書の一部または全部の転載を禁止します。本文書の著作権は、著作者に帰属します。

TImageEdit
publicconstructor Create(iOwner: TComponent); override;
destructor Destroy; override;
published
外から変更できるように
property Image: TImage read FImage;property として公開
end;
implementation
uses
Vcl.Imaging.Jpeg, Vcl.Imaging.PngImage;

Jpeg と Png を表示するために
uses

12

本文書の一部または全部の転載を禁止します。本文書の著作権は、著作者に帰属します。

TImageEdit{ TImageEdit }constructor TImageEdit.Create(iOwner: TComponent);
begin
inherited;

画像用 TImage を生成

FImage := TImage.Create(Self);
FImage.SetBounds(1, 1, 16, 16);
FImage.Stretch := True;
FImage.Picture.OnChange := ImageChange;
FImage.Parent := Self;
end;
destructor TImageEdit.Destroy;
begin
FImage.DisposeOf;

画像用 TImage を廃棄

inherited;
end;

13

本文書の一部または全部の転載を禁止します。本文書の著作権は、著作者に帰属します。

TImageEdit

Invalidate;end;

テキストが入力できるエリアの左右のマージンを指定できるprocedure TImageEdit.ImageChange(Sender: TObject);
begin
DoImageChanged;
end;

14

マージン

SendMessage(Handle,EM_SETMARGINS,EC_LEFTMARGIN or EC_RIGHTMARGIN,MakeLong(FImage.Width + 2, 0));

画像が変更されたときに、EDIT のテキストマージンを設定
マージン

procedure TImageEdit.DoImageChanged;
begin
if Parent = nil thenExit;

本文書の一部または全部の転載を禁止します。本文書の著作権は、著作者に帰属します。

TImageEdit
procedure TImageEdit.Resize;
begininherited;

TImage の大きさをClientHeight 四方の正方形に

if Parent <> nil thenFImage.SetBounds(1, 1, ClientHeight, ClientHeight);
end;
procedure TImageEdit.SetParent(iParent: TWinControl);begin
inherited;
DoImageChanged;end;

15

本文書の一部または全部の転載を禁止します。本文書の著作権は、著作者に帰属します。

TImageEdit
procedure TImageEdit.WndProc(var Message: TMessage);
begin
case Message.Msg of
CN_CTLCOLORSTATIC,CN_CTLCOLOREDIT:
if FImage.Picture.Graphic <> nil thenExcludeClipRect(Message.WParam,
1,TImage の部分を描画しないように
1,
1 + ClientHeight,
クリッピング
1 + ClientHeight);（クリッピングしないと Text の背景
end;
inherited;end;

色で塗りつぶされてしまう）

end.

16

本文書の一部または全部の転載を禁止します。本文書の著作権は、著作者に帰属します。

TImageEdit を使う側
type
TForm1 = class(TForm)
procedure FormCreate(Sender: TObject);privateFImageEdit: TImageEdit;publicend;
implementation
procedure TForm1.FormCreate(Sender: TObject);
begin
FImageEdit := TImageEdit.Create(Self);
FImageEdit.Image.Picture.LoadFromFile('C:¥temp¥luna6.jpg');
FImageEdit.SetBounds(10, 10, 250, FImageEdit.Height);
FImageEdit.Parent := Self;end;

17

本文書の一部または全部の転載を禁止します。本文書の著作権は、著作者に帰属します。

実行結果

読み込んだ画像が確かに表示されている

画像付きエディットを作る• FMX では…

コードは書かない！

画像付きエディットを作る• FMX では、どうするか？

スタイルを使います！
実際に作ってみます。

画像付きエディットを作る
マルチデバイスアプリケー
ションを新規作成
TEdit をドロップします。

画像付きエディットを作る

TEdit を右クリックして「カスタムスタイルの編集」を選びます。

画像付きエディットを作る

TEdit の標準スタイルがコピーされます。
これに修正をしていきます。

画像付きエディットを作る
TImage を edit1style1 にドロップ！

画像付きエディットを作る
ドロップされた
TImage

ドロップされた
TImage のプロパティ
MultiResBitmap

画像を選ぶ

画像付きエディットを作る

TImage の表示をマイナス座標に置く（※）※本来なら親レイアウトに TAlignLayout.Left などで置きますが、TEdit がプレゼンテーションレイヤーなどに分かれており、正しく作らないとキャレット位置がずれたりします。
そのため、ここでは簡単にこのようしています。

画像付きエディットを作る
適用して閉じる、を押します。

StyleBook も自動的に作成され追加されます
すると！
画像が表示されたエディットができています！

画像付きエディットを作る

実行すると、正しく画像が表示されたエディットになっています。

画像付きエディットを作る
VCL と違って FMX 版は画像を変えられない？？

VCL 版は TImage がプロパティとして出ていたのでImage.Picture.LoadFromFile などが使えた！

画像付きエディットを作る
心配無用じゃ！！
スタイルをもう一度開くんじゃ
スタイルを編集するためには StyleBook1 をダブルクリックします。

＿人人人人人人人＿＞ 突然のDavid I. ＜￣Y^Y^Y^Y^Y^Y^Y^Y￣

画像付きエディットを作るTImage の StyleName を image に設定します
そして、適用して閉じる、で閉じます。

画像付きエディットを作る

OnApplyStyleLookup
イベントハンドラを書きます画像付きエディットを作る
implementation{$R *.fmx}

TImage は FMX.Objects に宣言されているので uses します

uses
FMX.Objects;
procedure TForm1.Edit1ApplyStyleLookup(Sender: TObject);var
Image: TImage;StyleName で指定した名前でbegin
Image := Edit1.FindStyleResource('image') as TImage; スタイル中のコントロールを
Image.Bitmap.LoadFromFile('C:¥temp¥LunaGiro.jpg');
取り出します。
end;

33

本文書の一部または全部の転載を禁止します。本文書の著作権は、著作者に帰属します。

画像付きエディットを作る

実行時画像が変わっています画像付きエディットを作る
TStyledControl の子孫は全てOnApplyStyleLookupを持ちます。
FindStyleResource メソッドでスタイル内のコントロールを取得できます。

画像付きエディットを作る
注意したいのは、OnApplyStyleLookup イベントより前ではスタイルのコントロールは生成されていない！ということです。
たとえば、TForm.OnCreate で FindStyleResource を呼んでも値はとれません。

画像付きエディットを作る
StyleLookup とStyleName …？

Style を理解する前、StyleLookup と StyleName の２つが存在する理由がわかりませんでした。
いかがでしょう？

画像付きエディットを作る• StyleName– その名の通り、スタイルの名前– StyleLookup や FindStyleResource で指定します• StyleLookup– 適用したいスタイルの名前を指定します画像付きエディットを作る
もう１つの冴えたやり方を紹介します…たった１つではない！！

画像付きエディットを作る２
パネルを置いてカスタムスタイルの編集をクリックして、スタイルエディタを開きます。

枠線は要らないのでStroke プロパティの Kind をNone にします

画像付きエディットを作る２
TLayout は何もしないコンテナ

TEdit も普通にスタイルにおける！！！
TImage, TLayout, TEdit を上のように置きます。
TEdit は TLayout の子供に！
FMX は全てのコントロールが親（コンテナ）になれます！！

画像付きエディットを作る２
Image のAlign を Client に

画像付きエディットを作る２

Layout のAlign を Right にLayout のMargins.Left に 4 を指定

画像付きエディットを作る２

Edit のAlign を VertCenter に画像付きエディットを作る２
TImage と TLayout の
HitTest プロパティは Flase にする！

HitTest プロパティが True の場合マウスの押下がコントロールに通知されます。
親には通知されません。
特に必要ではない時は False にします。

画像付きエディットを作る２
ここまでの操作で、次のようになります。
ついでに、TImage.MultiResBitmap に画像を読み込んでおきます。

TImageMargins.Left による空隙

TEdit

TLayout画像付きエディットを作る２
設計時

実行時

TPanel なのに！
文字が入力できている！

TPanel のスタイルにする利点はコントロールのリサイズに追随し画像のサイズも変わるところ

画像付きエディットを作る２• FMX にとってコントロールとは「素体」でしかない• スタイルが変わると「機能」も変わってしまう– TPanel のスタイルに TEdit を付与できる• VCL のコントロールは機能そのものであった！

画像付きエディットを作る２

ここで冒頭のスライドを思い出してください画像付きエディットを作る２FireMonkey.Style は見た目だけでなく機能を持たせられる！

アニメーションを使う

53

本文書の一部または全部の転載を禁止します。本文書の著作権は、著作者に帰属します。

アニメーションを使う• 最近のリッチなアプリケーションでは当たり前のマウスオーバーで色が変わる仕組みはどうやっているのでしょうか？

アニメーションを使う• VCL では
1. TTimer を置く
2. OnEnter
1. Brush.Color を初期カラーに変更し描画
2. Timer.Enabled := True にする
3. Timer.OnTimer で Brush.Color を計算し描画
4. OnLeave で TTimer.Enabled := False

このような手順が必要になります。

アニメーションを使う• FMX では！！

これもスタイルでやります！！

アニメーションを使う
ここでは、マウスオーバーで色が変わるパネルを作ります。
1. 新規にマルチデバイスアプリケーションを作ります
2. TPanel をます。
3. TPanel のカスタムスタイルを編集しますアニメーションを使う
TColorAnimation をpanel1style の下にドロップします。

ドロップ後

Animation クラスは全て親に対して働きますアニメーションを使う
TColorAnimation のプロパティ値をPropertyName
StartValueTriggerTriggerInverse

Fill.ColorBlack
IsMouseOver = True
IsMouseOver = Falseに設定します

たったこれだけで！
MouseOver 時に色を変更可能です！

アニメーションを使う

MouseOver で色がふわっと変わる！

アニメーションを使う• TAnimation– PropertyName• 親のプロパティ名が自動的にリストアップされて表示される• そのアニメーションクラスで適用可能なもの• TColorAnimation では、Fill.Color / Stroke.Color がリストアップされていた

アニメーションを使う• TAnimation– StartValue / StopValue• アニメーション開始時の値と、終了時の値• StartValue はトリガーが掛かったときだけ指定されるので、親コンポーネントの対象を StartValue と同じ値にしておくと良い– 今回は TPanel.Fill.Color を Black にしておくアニメーションを使う• TAnimation– Trigger / TriggerInverse• アニメーションを開始するきっかけ• 親コントロールの Is～ プロパティが表示されている• こちらは親コントロールに適用可能かどうかは判断されない• TPanel には IsPress プロパティは存在しないが指定できる

はじめに• FMX の考え方
それぞれの OS でコントロールの見た目が違う…めんどくさいから全部自分で描いちゃおうZE！
Style で見た目をコントロール
OS ごとに DirectX / OpenGL / OpenGL ES で描画する
Style は見た目だけではない！
色々な機能を持たせられる！！

まとめ

65

本文書の一部または全部の転載を禁止します。本文書の著作権は、著作者に帰属します。

まとめ• VCL を使っていると勘違いしやすいポイント– VCL ではこうやる、を FMX のコントロールに求めがち– その多くはスタイルで実現する– FMX のスタイルは VCL スタイルと違い、見た目だけではない！
– スタイル側に機能を持たせるため、FMX ではカスタムコントロールを作る事はほぼ無くなった

まとめ• FMX スタイルを上手に使うには– Shape カテゴリのコントロールを使う• Shape カテゴリのコントロールは Style を作るため（といってもいい）のコントロール群– TLayout を使う• TLayout ごとに Align を指定できる• TLayout を複数使うと、複雑な Align も実現できる– 今回の例でいえば、TLayout には Right で右端に寄るようにし、TEdit は VertCenter で垂直方向の真ん中に表示できた。

付録• FMX でカスタムコンポーネントを作る場合とは？
– コンポーネントのユーザーに選択権を与える場合– たとえば、画像付きエディットでは• 画像の選択• 画像の位置の選択など– ユーザーの意思が入る場合、スタイルで何とかするのは難しい– こういった場合にはカスタムコンポーネントを作成しますThank you!