8-3 他のフォームにあるコンポーネントの参照

【基礎課題 8-2】

それでは、いよいよコンポーネントの配置です。下のように配置してください。

コンポーネントの配置
フォーム コンポーネント Name プロパティ
Form1 「コピー」ボタン ButtonCopy
エディット Edit1
Form2 エディット Edit1

ここに、Form2Visible プロパティを True にしておいてください(そうしないと、プログラムを実行しても Form2 が表示されません)。

さて、[コピー] ボタンクリックのイベントハンドラはどのようにすればよいでしょうか? 何となく次のようになりそうですね。

procedure TForm1.ButtonCopyClick(Sender: TObject);
begin
  Edit1.Text := Edit1.Text;
end;

ところが、これで実行しても (エディットに文字列を入れ [コピー] ボタンを押しても)、何の反応もありません。それは、我々プログラムする側が、「右辺の Edit1Form1 に属するもので、左辺の Edit1Form2 に属するものだ。」と考えていても、Delphi はこれをいずれも (プログラムが書かれている) Form1 上に存在する (同一の) Edit1 だと解釈するからです。

このような問題を防ぐため、実は本来は下のように、「どのフォームに所属するコンポーネントか」なのかを明記するようになっています。

procedure TForm1.ButtonCopyClick(Sender: TObject);
begin
  Form2.Edit1.Text := Form1.Edit1.Text;
end;

ただし、プログラムが記述されているフォーム内に存在するコンポーネントに関しては、フォーム名を省略することができます。この約束事があるので、これまでのような単一フォームの場合は、コンポーネント名の前にフォーム名を付ける必要がなかった訳です。

これは、例えて言うと電話における市外局番のようなものです。Form1 の中から (その外側の) Form2 のコンポーネントを呼び出す場合には市外局番 (つまりフォーム名) が必要ですが、Form1 の中のコンポーネント同士で呼び出すのであれば、市外局番は省略しても構わないのです。

そこで、不要な市外局番 (フォーム名) を省略すると、上のプログラムは次のように書けます。

procedure TForm1.ButtonCopyClick(Sender: TObject);
begin
  Form2.Edit1.Text := Edit1.Text;
end;

作成後このプログラムを実行すると、下のように「フォーム 'Form1' は USES リストに無い〔中略〕このユニットを追加してよいですか?」というエラーメッセージが表示されると思います。この場合、「はい」を押してからもう1度実行してください。

エラーメッセージ

このメッセージは、「display というユニットにある Form2 というフォームを参照しようとしているけれども、その display ユニットは (プログラムが書かれている) control ユニット内の uses 節に登録されていませんよ。今 uses 節に追加しますか?」という意味です。

実は、Delphi では、プログラムで使用するユニットは全て uses 節にリストアップしておかなければなりません。これまで、uses 節のことを意識して来なかったのは、通常のプログラムに必要なユニットについては Delphi が自動的に uses 節に入れてくれていたからなのです。しかし、今の場合、display というユニットは、プログラマー (我々) が独自に作成したユニットです。ですから、それをこのプログラムで使用するかどうかはプログラマー自身が決めなければなりません。上のメッセージは「あなた (プログラマー) が uses 節への登録を忘れているようだから、私 (Delphi) が登録しておきましょうか?」と尋ねてくれている、いわば"親切な"メッセージなのです。これに [はい] と答えると、下のように uses 節が追加されます (挿入場所は implementation 部の下です)。

※ なお、上のような uses 節への追加に関する情報ボックスを表示させるまでもなく、最初から自分で uses 節に (使用する) ユニットを付け加えても構いません。というよりもそれがプログラマー本来の役割なのです。

コラム なぜ uses 節が必要なの?

なぜ uses 節などという面倒なものが必要なのでしょうか? その説明のために次の図を見てください。

説明図

この図は、ユニットやプロジェクトからどのように実行ファイルができるか、を示した図です。なお、図には次節以降で導入する tools ユニットも含めています。それぞれのユニットファイルは、コンパイル (翻訳) という作業によってオブジェクトファイルと呼ばれる部分的な実行プログラムになります。コンパイルとは人間が書いたプログラムをコンピュータが理解できるように機械語に翻訳することです。全てのユニットがコンパイルされてオブジェクトファイルになると、最後にこれらすべてを合成するリンク (結合)という作業によって実行ファイルが出来上がります。

ここで、control ユニットがコンパイルされる処理を考えてみましょう。control ユニットが display ユニットの中のコンポーネントや手続き・関数を利用する場合には、オブジェクトファイルには「display ユニットの中のコンポーネントや手続き・関数を利用したいので、リンクするときにはその場所 (実行ファイルの中での場所) を教えて欲しい」という情報を書き込んでおく必要があります。その情報を書き込む場所が uses 節である訳です。uses 節によってバラバラなオブジェクトファイルが結びつきあって、一つの実行プログラムにリンクされて行くのです。