[ SuperCard ] [ Delphi ] [ SmalltalkAgents ]

Building Simple Application in Delphi

[ Updated: Apr 20, 1997 ]


Delphi でデジタル時計を作る

ざっと紹介
Delphi 三位一体
VCL (Visual Component Library)
フォームを作る
コンポーネントを配置する
メニュー・バーを組み立てる
メソッドを作る
小細工を弄する
RAD ツールとしての Delphi
Delphi: ほんの少しのリンク

ざっと紹介 (for Real Mac User not loser)

Delphi とは何ですか?

一言でざっくりと言ってしまえば Delphi は Borland がリリースしている, Microsoft Windows (95/NT) 上で稼動する RAD (Rapid Application Development) ツールです。 フォーム (まぁ、カードとかウィンドウのようなものと考えといてください) を開いて、パーツを配置し、動作をちょろろっと書いて、はい出来上がり「も」可能になっています。 Mac オンリーで、かつ、なんか作ってみたいと思ったこともなく、よその世界などどーでもええと考えている人には、それこそどーでもええでしょうが (ま、そんなやつはこんなとこ読まないわな)。 現在 Windows 95 上では SuperCard は動きません。 SmalltalkAgents もまだリリースされていません。かの MetaCard もまともに2バイト文字を扱えない状態です。SuperCard のような環境を Windows 95 上に欲しいと思っている人には、選択肢の一つにあげておいてもよいでしょう。一から作り直しになりますし、 go to cd を連発してるものには向きませんが、それ以外なら、そう手間は掛からないはずです (発言内容は無保証です)。あ、 HotText はほんの少し面倒かな。 (笑)

Delphi は大きく3つの部分に別けてみることができます。
Trinity of Delphi
言語
Object Pascal
Pascal の OO 拡張としては Apple の Lisa が採用していた Clascal (まんまの名前ですね) がありますが、 Object Pascal は Steve Jobs に要請されて、 かの Niklaus Wirth が Apple Clascal チームとともに設計しました ([Schmucker86])。搭載されているのは、その由緒正しき Object Pascal の Borland 拡張版です。 Borland の Turbo Pascal シリーズは一世を風靡しました。その第 8 代正統後継者が Delphi です。
クラス・ライブラリ
VCL (Visual Component Library)
およそ 450 ほどのクラス (とコンポーネント) からなるフレームワーク。コンポーネント (部品) は特に (数は) 充実しています。版によってはソースが付属します。これは英断ですね。でもコレクション族はないの?
開発環境
IDE (Integrated Development Environment)
Code Editor, Component Palettes, Menu Designer, Object Inspector, Object Browser, Project Manager, Debugger などが結合されています。製品グレードに応じて、ヴァージョン管理ツールや SQL ツール, データベース・エンジンなども付属します。

コンポーネントとは (Delphi 用語集より)
構成要素のこと。Delphi では次の意味で使われます。
  1. Delphi アプリケーションの要素。コンポーネントパレットでアイコンの形で示されます。フォームなどのコンポーネントはユーザーが処理するオブジェクトです。フォームは他のコンポーネントを含むことができるコンポーネントです (フォームはコンポーネントパレットでアイコンの形では示されません)。
  2. Delphi では,TComponent から継承した任意のクラス自身がコンポーネントです。広い意味で,コンポーネントは Delphi のフォームデザイナで直接対話ができる任意のクラスといえます。コンポーネントは自己充足的であり,プロパティによってその機能へのアクセスを提供します。
  3. 従来の Pascal では,「レコードはいくつかのコンポーネント,つまり 3 つの文字列フィールドと 2 つのバイトフィールドで構成されます」という具合に機能の意味でも「コンポーネント」をよく使います。
コンポーネントは Delphi アプリケーション構築の基礎となります。コンポーネントをフォームに追加し,そのコンポーネントのプロパティ,メソッド,イベントを使うことにより,アプリケーションを構築します。 すべてのコンポーネントが共通して持っているプロパティ,メソッド,イベントは TComponent と呼ばれる抽象コンポーネントから継承します。

VCL (Visual Component Library) はけっこうな大きさなので、理解するには多少の時間を必要とするかも知れません。が、そこはそれ、そんなことは考えなくても、パレットから「ぽとぺた」するだけも、ある程度のものなら出来てしまいます。とりあえずやってみた方が、早く結果が出るでしょう。勉強してからやろうなんて悠長なことをやってると、おそらくいつまで経っても出来ません。 RAD ツールはスピードが命です。

7 Key Components of VCL

VCL の系図は TControl 抽象コンポーネント王の代に至って、ウィンドウハンドルを従えた本家 TWinControl と、非ウィンドウカスタムコントロール一族の開祖である分家 TGraphicControl に分裂していますが、単純に言ってしまうと、ボタン一派やフィールド家、スクロール・バー族など、フォーカスを必要とするものが前者、ラベル (スタティックなテキスト・フィールド)やシェイプ、イメージなどが後者です。こちらはフォーカスが与えられません。クラスの数としては、前者の方が圧倒的に多い。

Delphi でのもっとも簡単なアプリケーション作成手順は、 1 つないし複数のフォームを開いてコンポーネントを配置し、そのコンポーネントのプロパティ、メソッド、イベントを使うことにより、アプリケーションを構築するということになります。 インタプリタではなく完全なコンパイラ環境ですが、 Turbo Pascal, Turbo C 以来の伝統である超高速なコンパイル速度は健在です。 SuperCard ユーザにとっては、メニューの Run で実行できるので、違和感はないでしょう。ただ、そこで Run するものは本物の実行オブジェクトであり、すでにアプリケーションになっているので、変換する必要はありません。

  1. Project を作成する。
  2. 最低 1 枚のフォームを作成し、そのなかにコンポーネントを配置する。
  3. コンポーネントが応答するイベントに対応するメソッドを書く。プロパティを決める。
  4. メニュー一発で実行ファイルを作成する。必要に応じ、デバッガで動きを検討する。

それではさっそく始めてみましょう。ここでは、もっともシンプルに「フォームを開いて『ぽとぺた』」法でやってみます。環境は以下のとおりです。

対象パッケージは Delphi Client/Server Suite 2.01J ですが、このほかに Desktop 版 (VCL のソース、DB 関連、ヴァージョン管理ツール等が付属しない) と Developer 版 (DB 関連、ヴァージョン管理ツール等が付属しない。 VCL のソースは付く) があります。が、ここで作成する程度のものなら、どれでも動くはずです。

[ go to top ]

フォームを作る

Delphi を起動すると、新規フォーム編集画面が開きます。以前のプロジェクトが開かれた場合は、「ファイル」メニューから「新規作成...」を選び、ダイアログから「フォーム」を選択してください。 この時点で一度 save しておきます。Project 名は "showTime.dpr" にしておきます。 unit のファイル名は "showTimeMain.pas" とでもしておきます。


初期画面

左に見えるインスペクタからフォームを触ります。 Name プロパティを showTimeForm とします。 Caption プロパティを ShowTime とします。これはタイトルバーに表示されます。 ラベルを 1 つ置きます。 Name プロパティを showTimeLabel とします。適当な大きさにリサイズしてください。 ラベルはユーザが変更できません。 表示されるフォントを変えたい場合は、 font プロパティを適宜変更します。コンテンツの文字列表示のスタイル等も、必要があれば、そのプロパティを変更します。ここでは Alignment プロパティを中央揃えに設定しています。

ビットボタンを 1 つ作成します (ボタンでも可)。適当な大きさにリサイズしてください。 Name プロパティを quitBitBtn とします。 Caption プロパティを Quit とします (正しくは Exit とすべきです)。リターン・キーが利くようにデフォルト・ボタンにしたい場合は、ここではなく、 showTimeForm フォームの ActiveControl プロパティで、 quitBitBtn を指定します。

quitBitBtn のプロパティ設定 quitBitBtn のイベント設定

ビットボタンと通常のボタンの違いは、ボタンの表面に bitmap を表示できるか否かです。


フォームに「ぽとぺた」しているところ

メニュー・バーの作り方は、ちょっと変わっています。コンポーネント・パレットから MainMenu コンポーネントを配置します。 Name プロパティを FileMenu としたあと、コンポーネントをダブルクリックするとメニュー専用エディタのメニューデザイナが立ち上がります。新規作成時は空なので、まず File メニューを追加します。 Caption プロパティを File(&F) とします。ついで Name プロパティを FileMenu に変更します。できたメニューをクリックして下に移動し、アイテムを付加します。 Caption プロパティをExit(&X) とします。ついで Name プロパティを ExitItem に変更します。いずれも ( ) 内のアンパサンドとその後の一文字はアクセラレータキーの指定です。 alt キーと同時にタイプすることで、キーボードからメニューにアクセスできます。


メニューデザイナ

ウィンドウの中味はこれで終わりですが、このままではウィンドウをリサイズしても、そこに含まれるフォーム上のオブジェクトの配置位置は変化しません。リサイズにオブジェクトを追随させるには、リサイズに応答するメソッドを書くか、リサイズに応答するパネルをまず置いて、その上にオブジェクトを載せる、等の方法があります。むろん、後者の方が楽チンです。

この段階ですでに動かすことができます。「実行」メニューから「実行」を選べば、make が始まってすぐ動き出します。体感的には SuperCard よりも速いです (笑)。ただし、終了メソッドを書いていないので、ボタンをクリックしても何の反応もありません。終わるときは、とりあえず、ウィンドウ右端上のクローズボックスをクリックするか、タスクバーから Delphi を表に回して、「実行」メニューから「プログラムの終了」を選択します。

ここまでで、ターゲットのディレクトリに以下のファイルが作られています。

  1. showTimeMain.pas (フォーム・ソース) テキスト・ファイル
  2. showTime.dpr (プロジェクト・ソース) テキスト・ファイル
  3. showTime.exe (実行ファイル) バイナリ・ファイル
  4. showTime.res (プロジェクト・リソース) バイナリ・ファイル
  5. showTimeMain.dfm (フォーム定義) バイナリ・ファイル
  6. showTimeMain.dcu (フォームのコンパイル・ファイル) バイナリ・ファイル
  7. showTime.dof (コンパイル・オプション) バイナリ・ファイル *
  8. showTime.dsk (デスクトップ情報) バイナリ・ファイル *
  9. showTime.dsm (フォームのシンボル定義) バイナリ・ファイル *
* は、コンパイル・オプション設定によって作成されますので、存在しない場合もあります。

ここでちょっと寄り道して、「表示」メニューから「プロジェクト・ソース表示」を選んで、プロジェクトのソースを開いてみます。

program showTime;

uses
    Forms,
    showTimeMain in 'showTimeMain.pas' {showTimeForm};

{$R *.RES}

begin
    Application.Initialize;
    Application.CreateForm(TshowTimeForm, showTimeForm);
    Application.Run;
end.
Think C の TCL を使っていた人なら判ると思いますが、見た感じがまったく同じですね。 1 行目の初期化作業はクラス・ライブラリの奥底に潜んでいます。 2 行目は、 showTimeMain.pas で定義されたクラス TshowTimeForm (TForm のサブクラス) から、インスタンスを作成して、変数 showTimeForm に入れています。Delphi ではフォームの自動作成と言っていますが、なに、ソースをプログラマが書くか Delphi が書くかの違いだけです。 3 行目から走り出します。 変数 Application は TForm で宣言された TApplication 型のインスタンス変数で、プロジェクトで構築するアプリケーションのインスタンスが格納されます。この辺りはまるっきり Delphi にお任せになるので、ユーザは変数 Application が理解するもの、つまり、そのプロパティやメソッドに注目していれさえすれば佳い、ということになっています。 また begin - end ブロックがあります。拡張子こそ dpr になっていますが、これも立派な pascal source で、このファイルだけでアプリケーションを作ることも可能です。ウィンドウを必要としない、いわゆるコンソール・アプリケーションなんかがそうですね。

また、 showTimeMain.pas のクラス定義の部分も見てみましょう。

unit showTimeMain;

interface

uses
    Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
    ExtCtrls, StdCtrls, Buttons, Menus;

type
    TshowTimeForm = class(TForm)
        showTimer: TTimer;
        quitBitBtn: TBitBtn;
        showTimeLabel: TLabel;
        MainMenu: TMainMenu;
        FileMenu: TMenuItem;
        ExitItem: TMenuItem;

        

    private
        { Private 宣言 }
    public
        { Public 宣言 }
    end;

var
    showTimeForm: TshowTimeForm;

implementation
(* 以下略 *)
いくつかの自律的なコンポーネントを抱き抱えた TshowTimeForm というクラスの姿が思い浮かびますか? クラス定義は interface 部でなされており、また、 TshowTimeForm 型の showTimeForm という変数も宣言されているので、これは unit を uses すれば、どこでも使えます。 interface 部は C で言うところの header ファイルに相当します。 interface (宣言) と implementation (実装) を分離せずに一つのファイルに書くのが、 pascal の特徴です。

[ go to top ]

メソッドを作る

showTimeLabel ラベルは、外部から書き込まれるだけなので、ここでは触りません。 quitBitBtn ボタンは、クリックされたら、確認して終わるという動作を行います。ボタンをダブル・クリックすると、コードエディタにメソッドの雛形が作成されます。

procedure TshowTimeForm.quitBitBtnClick(Sender: TObject);
begin

end;
ヘルプからダイアログ関連を漁って、以下のコードをでっち上げました。
procedure TshowTimeForm.quitBitBtnClick(Sender: TObject);
begin
    if (MessageDlg('Are you sure?', mtInformation, [mbYes, mbNo], 0) = mrYes) then begin
        Close;
    end;
end;

Delphi では、特に指定しない限り、メインのウィンドウが閉じられればアプリケーションは終了します。ここで、ダイアログの返答が mbYes だった場合、 Close メッセージを受けるのは、 showTimeForm です。 quitBitBtnClick というメソッドは、 quitBitBtn が受けますが、 Close は、実は暗黙の Self が省略されており、 Self.Close という形で送られます。ここでの Self は、むろん showTimeForm です。

さて、時刻を表示し、それを更新するにはどうすればいいでしょうか。ヘルプから「日付時刻ルーチン」を見てみると、日付は date 関数で、時刻は time 関数で、それぞれ取得することができます。が、これでは、呼ばれた時でないと動きません。これを自動的に呼ぶようにするにはどうしたらいいでしょうか。

Delphi ライブラリリファレンス >> ビジュアルコンポーネントライブラリ >> ビジュアルコンポーネントライブラリのコンポーネントに答えがあります。 Timer コンポーネントを使用します。ここに当りを付けるのはかなり面倒です。本を読んで基礎をつけるか、片っ端からライブラリを見てまわることになりそうです。暇なときに、ビジュアルコンポーネントライブラリのオブジェクト、コンポーネント、コントロール、非ウィンドウコントロールを観てだいたいのところを覚えておく必要があります。

さて、 Timer コンポーネントは 1 回だけまたは指定した間隔で繰り返しイベントを発生させるのに使います。 ということなので、さっそく使ってみます。 フォームに戻って、 Timer コンポーネントを配置します。 Name プロパティをshowTimer とします。時間の表示は OnTimer イベントハンドラで指定すればよさそうです。タイマーイベントの間隔は、 Interval プロパティで指定できます。これはデフォルトが 1000 ミリ秒 (1 秒) なので、変更しないでおきます。

procedure TshowTimeForm.showTimerTimer(Sender: TObject);
begin
    showTimeLabel.Caption := FormatDateTime('yyyy/m/d, ddd', Now);
    showTimeForm.Caption := TimeToStr(Time);
end;

ここでちょっと小細工を弄しています。ラベルには日付と曜日だけを表示し、ウィンドウのタイトルバーに時刻を表示しています。なんで? ウィンドウを最小化した際にも時刻が判るように、というのが理由です。 FormatDateTime 関数についての説明は省略します。

ここまで作ったら動くでしょうか。「実行」メニューから「実行」させてみましょう。どうでしょうか。ちゃんと動いていると思います。

では File メニューから Exit を選択して編集環境に戻りましょう。あれ、何の反応もありません。そうでした。メニューアイテムを作ったはいいが、イベントハンドラを指定していませんでした。では定義しましょう。 Quit ボタンで抜けて、編集環境に戻ってください。 MainMenu コンポーネントをダブルクリックしてメニューデザイナを開きます。 Exit アイテムを選択したら、インスペクタでイベントタブを開きます。 OnClick の応答ハンドラがポップアップになっています。そこで quitBitBtnClick を指定します。これで、メニューからも終了できるようになりました。

[ go to top ]

小細工を弄する

さて、ここからはやらなくてもよい小細工です。ちゃんと動いていますが、いささか気になる点があります。不満な点は下記の 2 点です。

  1. まず、立ち上げ時にすぐ時刻が表示されない。
  2. どうせなら、立ち上げ時からウィンドウは最小化しといた方がよい。
最初のものは、イベントタイマーの Interval を細かくすればよい話ですが、たったこれだけのためにイベントを回すのも業腹ですので、フォームが開かれる直前にタイマーをセットし、かつ表示領域に書き込んでおくようにします。 2 番目は、インスペクタでフォームの WindowState を wsMinimized に変更するだけで済みます。

インスペクタでフォームのイベントタブを開きます。そこに OnCreate というイベントがあるので、ダブルクリックしてハンドラを書きます。 OnCreate イベントはフォームが表示される直前に呼ばれます。この時点でタイマーをスタートさせ、なおかつラベルに書き込んでおきます。

procedure TshowTimeForm.FormCreate(Sender: TObject);
begin
    showTimer.Enabled := true;
    showTimerTimer(nil);
end;
明示的にタイマーをスタートさせたので、フォームを閉じるときに、明示的にタイマーを止めておきます。ここで止めなくてもアプリケーション終了時に OS が止めてくれますが、忘れたわけではないということを明言するために、自分で止めます。イベントタブの OnClose ハンドラを指定します。
procedure TshowTimeForm.FormClose(Sender: TObject; var Action: TCloseAction);
begin
    showTimer.Enabled := false;
end;
さらに蛇足で、 OnClick イベントに下記を指定してみてください。フォームのクリックでシュリンクするようになります。
procedure TshowTimeForm.FormClick(Sender: TObject);
begin
    WindowState := wsMinimized;
end;

これで、Project の作成は完了しました。実行ファイルのサイズは 202KB という (SmalltalkAgents や SuperCard に比べたら) 小さなものです。もしかしたら、「けっこうデカいな」という感想を持たれる方もいるでしょう。

[ go to top ]

RAD ツールとしての Delphi

駆け足ながら、 Delphi でのアプリケーション作成を追いかけて観ました。この程度なら、ひじょうに簡単であることがお判りいただけたかと思います。実際に作成したのは、 わずか 9 ステップ程度 です。残りの 80 ステップは Delphi に書いてもらいました。

Delphi は RAD ツールとして絶大な人気を誇っています。 Pascal はやはり Borland の屋台骨ということでしょうか。同じような RAD ツールで Microsoft が提供している Visual Basic という環境もあります。幸か不幸か、わたしはこれをまったく知りません。

速い、安い、美味いと三拍子揃っているかに見える Delphi ですが、思わぬところに落とし穴があります。シンボル情報を書き出すように指定してコンパイルすると、「オブジェクト参照ブラウザ」が使えるようになるとのことですが、こりゃ一体なんですか? ただのタグ・ジャンプでしかない。おまけに、ライブラリ本体の方は見えないしね。コンパイルすれば閉じちゃうし、クラスの検索すらできない。 この「ブラウザ」は使いものになりません。 つまり、クラスのメンテナンスには使えない、という結論になります。定義してあるはずのメソッドの、インプリメントの詳細を見たいと思って、ソース開いてからどうすると思いますか? 宣言部を探して、見つかればコピーして 文字列検索 です。 grep にも劣る、恐るべき前近代的かつ有史以前の仕様。 Visual な開発環境だから、 Visual grep ですか? 洒落にもなりませんね。評判の佳さに浮かれるのはいい加減にして、早いところ、まともなツールをつけてください。 > Borland.
もし、 Delphi を OOP 環境として使いこなしている方がいらっしゃったら、ぜひそのコツを教えてください。とくにメンテナンスの仕方を。

それから。これはコンパイラ環境に慣れた人には当たり前のことなんですが、自分でカスタム・コントロール書いたとします。 これは一度ライブラリに組み込まないと使えないんですね。 「なに、当たり前のこと言ってんの、こいつ」。ほんとにそうですか? たいていの方は当たり前だと思っているかも知れませんが、やや不満です (笑)。不具合が出たら、ライブラリから外して、デバッグし、完了したら、また組み込んで、そいつを使ってるやつは全部リコンパイルするんですよ。

さらに。これは Delphi の責任ではなく特徴なんですが、ハイブリッドであること。これのどこがいけないかというと……逃げ道がある、というのが最大の欠点ですね (苦笑)。え、逃げる方が悪い? 正論で水を掛けないでください (笑)。

BGM:

[ go to top ]

Delphi: ほんの少しのリンク

[ go to top ]


[Schmucker86] K. J. Schmucker, "オブジェクト指向プログラミング for the Macintosh™" 上下巻, 大谷和利監訳, ソフトバンク, 1989., p.64.
Created: Apr 20, 1997
[ SuperCard ] [ Delphi ] [ SmalltalkAgents ]