2013年12月25日水曜日

チラ裏(個人的な事を振り返る)

Delphi Advent Calendar 2013 の 12/25 の記事です。

ということで、ブログで初めて個人的な事を書くよ!!
Delphi Advent Calendar の最後の記事がチラ裏でごめんね!!

今年あった大きな事は
  1. Delphi iOS の本を出した
  2. Embarcadero MVP になった
  3. LL祭りに出た
ってことです。

まず、本については、非常に僥倖でした。
お話を頂いて、毎晩+土日を使って書いたんですけど、まだベータ版の段階だったので、メソッドが変わったり、動作が変わるwww
何度、書き直した事か……!
そして、査読してくださった方々や、エンバカデロの皆さん、CUTT SYSTEM の皆さんのご協力があって、完成しました。
人生で本を出すのは2度目ですが、やっぱり、大変な作業でしたよ…。



次は、エンバカデロ MVP になりました、というお話です。
エンバカデロ MVP になるためには、デベロッパーキャンプなどのイベントに出演していること、ブログなどで情報を発信していること、などがあります。
そして、誰かが推薦して認められると、MVPになります。
MVP は年に1回9月に任命されます。

ここで、凄いのは、エンバカデロ本社の MVP 担当部署から直接連絡が来るところです。
エンバカデロ日本法人は関与していません!

僕は英語のメールは全部 SPAM だと思っているので、危うく MVP 任命のメールを捨てるところでした!
ちなみに、推薦してくれたのもエンバカデロの人では無いですし、MVP 担当部署は僕の知らない所ですし、誰かが便宜を図ってくれたとかは無いです。

で、多分誰も知らないと思うので、MVPに任命されると何が起こるのか、を言えるところだけ言うと
  • RAD Studio Enterprise 版の1年間限定ライセンスが貸与される
  • MVP オンライン・ミーティングに出席のお願いがくる(基本向こうの時間なので厳しい)
  • CodeRage などのイベントがあると、イベントの宣伝のお願いが来る
  • FieldTest のお願いがくる
といったところです。
あとは、言えない部分でいくつかありますが、そこは察して!!
あ、ちなみに、悪口を言ってはいけないとかも無いです。



3つめは「LL まつり」という、Lightweight Language のイベントに出席したことです。
Delphi なんで、いままでクライアントサイドのイベントにしか出たこと無かったですが、ちょっとしたご縁により、出させて貰いました。
これで、Delphi について話せたのが個人的には凄く嬉しい出来事でした。
というのも、Delphi 知らない人にも Delphi という言葉を伝えられたのと、昔 Delphi 使ってた人達に Delphi を思い出して貰えたからです!

今の Delphi は、iOS / Android / Win / OS X と4つのプラットフォームに対応していますが、これを伝えられたのは本当に大きくて、色々と反響をいただきました。



最後に、来年のこと。
LL まつりの縁で、来年の CROSS 2014 にも登壇します。これも、どちらかといえば LL 系言語のイベントですが、言語同士のバトルが見たいwwwということでお話を頂きました。
が、バトルはしません!宗教戦争になるので!それぞれの言語について、色々紹介するイベントになります。

さらに、その後「Developers Summit」にも出ます!
こちらでは、モバイル開発に対して、ちょっと話してきます。

と、いうことで、2014年も色々活動できたらなーと思っています。

あ、そうそう、Delphi Android の本も書いているので、今しばらくお待ちを……

それでは、良いお年を!!

2013年12月23日月曜日

FireMonkey の TWebBrowser を Win/Mac で使えるようにする!

Delphi Advent Calendar 2013 12/23 の記事です。

なんだか、結構需要があるっぽい FireMonkey 用の TWebBrowser を作りました!というお話です。

FireMonkey で複数 Platform に対応するコントロールを作るためには「共通の要素を Interface 化する」という作業が必要になります。
そして、それぞれの Platform で、その Interface を実装してやります。
今回は、iOS / Android 用の TWebBrowser が継承しているのと同じ ICustomBrowser を継承して、Win/Mac 用の TWebBrowser を作りました。

また、FireMonkey のファイル名は、FMX.コントロール名.Platform.pas とする慣習があります。
ということで、今回は
  • FMX.WebBrowser.Win.pas
  • FMX.WebBrowser.Mac.pas
という名前にしました。

また、元々の TWebBrowser は iOS / Android 用なので Parent を設定するという処理がありません。
Parent が設定されたら ICustomBrowser を継承した WebBrowser を表示する必要があるので、それらを処理する TWebBrowserEx というコンポーネントも作りました。

また、もう一つ FireMonkey の慣習があって、各プラットフォーム用の Interface は、implementation 部に書き、interface 部には、それを登録する関数だけ宣言する、というモノがあります。
あまり好きでは無いのですが、今回は、それに習って Win/Mac 用のユニットには RegisterWebBrowserService と UnregisterWebBrowserService という関数だけ用意しました。

unit FMX.WebBrowser.Win;
interface
procedure RegisterWebBrowserService;
procedure UnRegisterWebBrowserService;
implementation

unit FMX.WebBrowser.Mac;
interface
procedure RegisterWebBrowserService;
procedure UnRegisterWebBrowserService;
implementation

この関数を呼ぶと、TPlatformServices に Win/Mac 用の WebBrowser コントロールを「生成するクラスのインスタンス」が登録される仕組みです。
ここで、WebBrowser コントロールのインスタンスを登録してはいけません!そうすると1個しかインスタンスが作れませんからね!
WebBrowser コントロールを生成するクラスのインスタンスを登録しておけば、そのインスタンスを取り出して、いくらでも WebBrowser を生成できます。

登録したインスタンスは TPlatformServices.Current.SupportsPlatformService メソッドで取り出せます。

RegisterWebBrowserService は initialization で呼ぶようにします。

initialization
RegisterWebBrowserService;
end.

これで、それぞれの Platform 用のユニットを読み込むと、Platform に適したコンポーネントが使えるようになります。
もちろん、それぞれの Platform 用のユニットは IFDEF を使って、どれを読み込むか制御します。
今回は、Win/Mac 用なので、下記のように制御しました。

uses
System.Rtti
{$IFDEF MSWINDOWS}
, FMX.WebBrowser.Win
{$ENDIF}
{$IFDEF MACOS}
, FMX.WebBrowser.Mac
{$ENDIF}
;

これで、Win/Mac 用の WebBrowser を使えるようになりました。
しかし、WebBrowserEx には、WebBrowser を生成しているコードはありません!
生成するコードは、親の親である TCustomWebBrowser の Create で生成されています。
TPlatformServices に登録してあるので、こちらでは何もせずに、正しいインスタンスが生成されます。すばらしい!

ちなみに、軽く各 Platform の実装を説明すると、

Windows 用は、VCL の TWebBrowser を使っています。
IWebBrowserX を取り出したりとか、めんどくさいから!!
FireMonkey でも別に VCL のコントロールも使えてしまうのです。
FireMonkey は TForm だけが Window Handle を持っています。
Windows 用 WebBrowser は、VCL なので、独自に WindowHandle を持っています。
そのため、VCL の TWebBrowser より 上に FireMonkey のコントロールを載せることはできません!
今回は、TForm の指定された(Parent で)場所にコントロールが載っているように見せています。
単純に、Parent の Left,Top,Right,Bottom に合致するように TWebBrowser を作っているだけです。

OS X 用も基本的には同じ仕組みです。
ただ、こちらは VCL の TWebBrowser などないので、自分で WebView を実装しました…超大変だった…Obj-C から Delphi 用のファイルを作るのが
これができたら、あとは実直に WebView を作るだけです。
で、結構はまってる人が居るみたいですが、StackOverflow に提示してあるコードは間違っています
なぜか setHostWindow を使っていますが、これはレシーバ用の Host を決めるためのもので、Parent を設定するモノではありません!
実際には、下記のように addSubView を使って親を設定します。

procedure TMacWebBrowserService.UpdateContentFromControl;
var
View: NSView;
Bounds: TRectF;
begin
if (FWebView <> nil) then begin
if
(FWebControl <> nil)
and not (csDesigning in FWebControl.ComponentState)
and (FForm <> nil)
then begin
Bounds := GetBounds;
View := WindowHandleToPlatform(FForm.Handle).View;
View.addSubview(FWebView);
if (SameValue(Bounds.Width, 0)) or (SameValue(Bounds.Height, 0)) then
FWebView.setHidden(True)
else begin
FWebView.setFrame(GetNSBounds);
FWebView.setHidden(not FWebControl.ParentedVisible);
end;
end
else
FWebView.setHidden(True);
end;
end;

これで、表示されるようになります。

実際に使うと、こんな感じ!






2013年12月22日日曜日

FireMonkey で閉じるボタン付きの TabItem を作る

Delphi Advent Calendar 2013 12/22 の記事です。

FireMonkey で「閉じるボタン付きの TabItem」を作ってみました。
これは、そもそもは facebook の Delphi Talks グループで田中さんが「格好いい?「PageControl 」を探しています」というスレッドを立てたので、僕が FireMonkey で作るのはいかがですか!とオススメした所から始まっています。
ということで、FireMonkey でコンポーネントをるのは大変ではないので、作りました
でも、うかうかしているうちに、やましょうさんの前日の Advent Calendar

> Fmxで作成してみるとわかるのですが、
> delphi+fmxって
> 本当に凄い!!
>
> だってこんなコンポーネントが簡単にできるんですよ。。
> しかも、携帯端末(iosなど)で動くのですから。。

と、言いたいことを言われてしまいました!!/(^o^)\
これが Delphi Advent Calendar の怖いところ!!早い者勝ちなので、来年からは書きたいことがあったら、もっと早く書こう…

まあ、それはそれとして、FireMonkey で、コンポーネントを作る方法は大きく分けて次の3段階が必要です。
  1. スタイルを作る
  2. コンポーネントを作る
  3. コンポーネントエディタを作る
VCL のコンポーネントと大きく違うのは1番目のスタイルを作る部分です。
FireMonkey の場合、見た目の制御は、ほとんど全部スタイルに任せます。
ですが!スタイルを1から作るのはメンドクサイ!
大体が TShape から派生した TRectangle とか TCircle とか TText とかを組み合わせて作るのですが、そういった簡単な図形以外は TPath を使って作ります。
TPath は SVG とか XAML のパスデータを描画してくれるコントロールです。
今回の「閉じるボタン」は「×」の形をしているので、単純な Shape を組み合わせて作るのは大変です!
なので、今回はズルします!
既に「×」ボタンを持っているコントロールからスタイルを盗みましょう。
そのコントロールとは TClearingEdit です。



ということで、方針が定まったのでスタイルを作っていきます。まずは、TStyleBook をフォームに貼ります。



そして、TStyleBook をダブルクリックしてスタイルエディタを開きます。



そして、デフォルトのスタイルから、まあ、なんでもいいんですが、ここでは構造が簡単な Dark スタイルを読み込みました。

「適用して閉じる」を押して、Style エディタを閉じます。
そして、TForm の StyleBook に StyleBook1 を設定します。



次に TTabControl を Form に貼ります。TTabControl は Common Controls にあります。
貼ったら右クリックしてコンポーネントエディタを開いて TTabItem を1つ作りましょう。
そして、できた TTabItem を右クリックして「カスタムスタイルの編集...」を押します。



すると!先ほど作った TabItem1 専用の Style が自動的に作られます。



これを編集していきます。
そして、先ほど盗んでくる!と言った TClearingEdit の「×」印を盗みます!



これを、そのまま TTabItem に移動しちゃいます。



そして、「適用して閉じる」を押して、スタイルエディタを閉じます。



フォームに戻ってみると……切れてる!!
そうです。「×」印が増えた分、文字が切れてしまったのです。

これは、ソースを修正しないと直せないので、スタイルの編集はここまでにして、次にソースを作っていきます……と、その前に作った Style を保存します。

StyleBook をダブルクリックして、スタイルエディタを開き、「保存」ボタンを押します。



すると、Style がテキストで保存されます。
なので、できあがった tabitem1style1 の "object TLayer" で表されるブロックを残して、あとは消します。



そして、これを保存しておきます。

さて、ではソースを作っていきます。
閉じるボタンが付いている TabItem を、TTabItemWithClose という名前にしました。

unit FMX.TabItemWithClose;
 
interface
 
uses
System.Classes
, FMX.Controls
, FMX.TabControl
, FMX.StdCtrls
;
 
type
[ComponentPlatformsAttribute(pidWin32 or pidWin64 or pidOSX32)]
TTabItemWithClose = class(TTabItem)
public type
TCloseEvent = procedure (Sender: TObject; var ioDoClose: Boolean) of object;
private const
STYLE_COLOR_BUTTON = 'closebutton';
STYLE_TEXT = 'text';
STYLE_TABITEM = 'tabitemstyle';
private var
FCloseBtn: TCustomButton;
FTabControl2: TTabControl;
FOnClose: TCloseEvent;
protected
procedure ChangeParent; override;
procedure ApplyStyle; override;
procedure FreeStyle; override;
procedure DoCloseBtnClick(Sender: TObject);
function DoSetWidth(
var ioValue: Single;
iNewValue: single;
var ioLastValue: Single): boolean; override;
public
class function Make(const iParent: TTabControl): TTabItemWithClose;
property TabControl: TTabControl read FTabControl2;
published
property OnClose: TCloseEvent read FOnClose write FOnClose;
end;
一番最初の「[ComponentPlatformsAttribute」はこのコンポーネントがどのプラットフォームで動作するのかを示すモノです。
ここでは、Win32, Win64, OSX32 で動作するとしています。

あとは、閉じるボタンが押されたときのイベントとか、必要な変数・メソッドを定義しています。

ちなみに、StyleLookup をクリックすると出てくるデフォルトの Style は TStyledControl.GetDefaultStyleLookupName で取得します。
なので、ここを Override すると、デフォルトの名前も変わります。
今回の TTabItemWithClose は GetDefaultStyleLookupName を Override しないので、

TabItemWithCloseStyle

という名前のスタイルがデフォルトになり、このスタイルを StyleBook から探すようになります。
なので、先ほど作った Style の名前を TabItemWithCloseStyle とする必要があります。

それでは、まず、DoSetWidth というメソッドを見てみます。
ここを修正すると Tab の大きさを変更できます。

function TTabItemWithClose.DoSetWidth(var ioValue: Single; iNewValue: single;
var ioLastValue: Single): boolean;
begin
if (FCloseBtn <> nil) then
iNewValue := iNewValue + FCloseBtn.Width * 1.5;
 
Result := inherited;
end;

このように変更すると CloseButton の幅の 1.5 倍が足された幅が新しい Tab の幅になります。
それでは、CloseButton はどこで取得するかというと ApplyStyle で取得します。

procedure TTabItemWithClose.ApplyStyle;
var
CloseBtn: TFmxObject;
begin
inherited;
 
CloseBtn := FindStyleResource(STYLE_COLOR_BUTTON);
if (CloseBtn <> nil) and (CloseBtn is TCustomButton) then begin
FCloseBtn := TCustomButton(CloseBtn);
FCloseBtn.OnClick := DoCloseBtnClick;
end;
end;

ApplyStyle は、スタイルを適用するときに呼ばれるメソッドです。
そして、FindStyleResource を使うことで、指定したスタイルを「コントロールとして」取得できます。
なので、ソースのように TCustomButton にキャストしてやって、閉じるボタンのインスタンスを保存します。

あとは、FreeStyle メソッドが呼ばれると Style が無効になるので、ここで FCloseButton に nil を代入しています。
また、initialization 部でコンポーネントを登録します。

initialization
begin
RegisterFmxClasses([TTabItemWithClose], [TTabControl]);
end;

登録しないと、IDE で作成された TTabItemWithClose が起動時やプロジェクト読み込み時にエラーになります。

基本的には、これでできあがりです。

他のメソッドは、僕が Style を一々作り直すのがメンドクサイので、そのための機構が入っています。
これについては、ソースをご覧ください。

そして、最後に、コンポーネントエディタを作らなくてはなりません。
作らないと、IDE で編集すると、TTabItemWithClose は作成されず TTabItem しか作成されません!

ということで、コンポーネントエディタを作りますが……これも DEKO さんが Advent Calendar で発表されているので、そちらをご覧ください!
僕が書くより、よっぽど詳しいです!!
コンポーネントとして登録する方法なども、リンクがあります!

では、できたコンポーネントが登録されたとして、これを使うためには、先ほど保存した TabItemWithCloseStyle を StyleBook に「追加」を押して、読み込ませます。



それで、適用して閉じたあと、コンポーネントエディタから TTabItemWithClose を作ると……



できました!!!

ちょっと駆け足になったり、はしょったりしましたが、こんな感じで FireMonkey のコンポーネントを作り出せます!
また、記事にすると長いですが、このコンポーネントを作るのに、実質1時間も掛かっていません!

簡単に作れるので、みなさんも、是非 FireMonkey でコンポーネントを作ってみて下さい!

2013年12月19日木曜日

Delphi の Interface

Delphi Advent Calendar 2013 12/19 の記事です。

※本文最後に追記あり(2013-12-20)

Delphi の Interface が使えないとほざいているのは誰だぁっ!

ということで、とりあえずできることを、つらつらっと書いてみましたよ。
詳しくは、コメントを見てください!

program Project1;
 
uses
System.SysUtils;
 
type
// GUID を指定すると Interface と GUID を結びつけることができます。
// これは主に COM をサポートするための機能です。
// (COM は Interface を GUID で管理します)
// にも関わらず GUID を付けることが推奨されています。
// 例えば GUID をキーに Dictionary として管理したりするためです。
// TPlatformServices.AddPlatformService のソースが参考になります。
IFoo = interface
['{174C7089-888D-4B3A-A348-DBAEC0AA70A5}']
// Property も宣言できますが、Interface は変数を宣言できないので
// reader / writer はメソッドのみ指定できます
function GetBar: String;
property Bar: String read GetBar;
end;
 
IDummy = interface
['{7820C3D8-0DBC-4506-81FF-4FB9B21F6959}']
function GetBar: String;
end;
 
// IFoo を実装するクラス
// TAggregatedObject は後述する TInterfacedObject の Reference Counter を
// 共有するクラスです
TFooImpl = class(TAggregatedObject, IFoo)
private
function GetBar: String;
end;
 
// IFoo を実装するクラス2
// IDummy という実験のためのダミークラスも実装してみています。
// 異なる Interface が同じメソッド名を持つ場合は、こんな風に解決できます。
TFooImpl2 = class(TAggregatedObject, IFoo, IDummy)
private
function IFooGetBar: String;
function IDummyGetBar: String;
function IFoo.GetBar = IFooGetBar; // IFoo と IDummy の GetBar に
function IDummy.GetBar = IDummyGetBar; // それぞれの実装を代入している
end;
 
// TFooImpl か TFooImpl2 に IFoo の実装を委譲してるクラス
// 委譲すると自身は IFoo を実装しなくていい!
// TInterfacedObject を継承すると RefCounter によって自動的に破棄されるよ
// 流行りの ARC と同じ仕組みを随分前から実装してたんだよ!
// (COM がそうなんだけど)
TBaz = class(TInterfacedObject, IFoo)
private
FFoo: IFoo;
public
constructor Create; reintroduce;
property FooIntf: IFoo read FFoo implements IFoo;
end;
 
{ TFooImple }
function TFooImpl.GetBar: String;
begin
Result := 'Bar';
end;
 
{ TFooImple2 }
function TFooImpl2.IDummyGetBar: String;
begin
Result := 'Dummy !';
end;
 
function TFooImpl2.IFooGetBar: String;
begin
Result := 'Bar 2!';
end;
 
 
{ TBaz }
constructor TBaz.Create;
begin
inherited;
 
Randomize;
 
// (ここではランダムだけど)目的に応じて委譲先を変更できる!
if (Random(2) = 0) then
FFoo := TFooImpl.Create(Self) // TAggregatedObject は RefCounter を
else // 共有するインスタンスを要求するよ
FFoo := TFooImpl2.Create(Self);
end;
 
{ Main }
var
Foo: IFoo;
GUID: TGUID;
Obj: TObject;
begin
// Inteface に代入, TBaz 自体は IFoo を実装していないのに代入できる!
Foo := TBaz.Create;
Writeln(Foo.Bar);
 
// Inteface を TGUID に代入できる!
GUID := IFoo;
Writeln(GUIDToString(GUID));
 
// Inteface から元の型を調べてみる
Writeln((Foo as TObject).ClassName); // Implements からでも元の型が取れる!
 
// Inteface から元の型を取りだして、再生成したりもできちゃう
// (まあこれは Inteface 関係ないけど…)
Obj := (Foo as TObject).ClassType.Create;
Writeln(Obj.ClassName);
 
Readln;
(* 実行結果 - Bar 2! と出ているところは Bar と出ることもあるよ
 
Bar 2!
{174C7089-888D-4B3A-A348-DBAEC0AA70A5}
TBaz
TBaz
 
*)
end.

個人的に面白いなあと思うのは「委譲」の仕組みと「Interface から元の型を取り出せる」ところかな-。
Java では Interface から元の Class を取り出すなんて不可能だからね!(間違ってました。本文最後に追記)
※ヘルプには「委譲は Win32 のみ」と書いてあるけど、普通に Win/OSX/iOS/Android で動作しました。

あと、今回の iOS / Android 対応で TinterfacedObject の仕組みが非常に活きているのが感慨深い…
COM のために実装した様々なことがここに来てすごく活きている!
同じく COM のために実装した dispinterface は、プラットフォーム依存ですと警告が出るようになってたよ…
ちなみに、Interface は FireMonkey でも使われまくっていてるんですよ!!
各 Platform 依存部と、それを一般化する部分では Interface 無しには実装できませんぜ!

追記:0213-12-20
Java でも、次のようにすれば Interface から元の Class を取り出せるよ!と教えていただきました。
MyInterface intf = new MyClass();
System.out.println(((Object)intf).getClass().getName());
僕の Java スキルもまだまだです……

2013年12月1日日曜日

VCL も地味に進化しているんですよ!

Delphi Advent Calendar 2013 12/01 の記事です。

FireMonkey にばかり目が行きがちですが、VCL も地味に進化しているんですよ!!

ということで、2007 以降に追加された機能で、僕がつい最近まで知らなかった機能をランキングでご紹介!


第3位
TLinkLabel



HTML リンク形式でクリックできるラベル!
みんな自分で作っていたよね!!
いつ追加されたのか、ちょっと判りませんでしたが……

使い方はすごく簡単で、Caption プロパティに A タグを使ってリンク先を書くだけです。
例えば…
" 右をクリック→ <a href="http://www.serialgames.co.jp/">株式会社シリアルゲームズ</a>"
こんな感じです。
下線部をクリックすると OnLinkClick イベントが発生するので、そこに↓こんな感じの処理を記述してやればOKです。
procedure TForm1.LinkLabel1LinkClick(
Sender: TObject;
const Link: string;
LinkType: TSysLinkType);
begin
// Link は id か href の中身
// LinkType は Link の種類
// sltID は id 属性が指定されていた場合
// sltURL は id 以外
 
ShellExecute(
Handle,
'open',
PChar(Link),
nil,
nil,
SW_SHOW);
end;
ここでは、ブラウザを開くようにしましたが、もちろんアプリケーションのナビゲートにも使えるわけです!

DEKO 氏よりご指摘を頂きましたので、追記いたします!
TLinkLabel が追加されたのは Delphi 2009 からとのこと!
そして、Xp でも使えるけど、テーマが有効である必要があるということです。
テーマは、プロジェクトオプション→アプリケーション→ランタイムテーマ→ランタイムテーマを有効にする、ですね!


第2位
TButton 驚愕の進化!



VCL のボタンは色が変えられないだとか、画像が載せられないだとか、そんな時代は終わっていました!(色については後述の1位をご覧ください)
むしろ、TBitButton の時代が終わっていた!
上の画像を見ていただければ一目瞭然ですが、色々と機能が拡張されています。

これらは、TButton.Styleプロパティで実現されています。
TButton.Style はTButtonStyle 型になっていて以下の3つがあります。

bsPushButton いわゆる普通のボタン
bsCommandLink  コマンドアイコンが付くボタン(インストーラなんかで見ます)
bsSplitButton 右側をクリックすると TPopupMenu を表示するボタン

そして、その他にも Images プロパティImageIndex プロパティを組み合わせると画像を表示できます!(他のプロパティで画像の位置を指定したり、Disable 時の画像を指定したりできます)
しかも画像をご覧頂くとわかるとおり、きちんとα値(透明度)も効きます!

FireMonkey を使わなくても、かなり美麗なアプリケーションを組めますね。
ただし!Vista 以降で有効!つまり! Xp では使えません!!
あれぇ…じゃあ VCL の機能というより Windows 機能なんじゃあ…


第1位
当然の VCL Style!

以下をご覧ください
えええええー!最後それえええええ!?
知らなかった機能を、って書いてあったのに、知ってる機能だしいいいいい!

そんなこんなで、2013年もあと少し。
今後とも、僕とブログと男と女、Delphi をよろしくお願いいたします。