モーダル フォームからのデータの取得
フォームからのデータの取得 への移動
モードレス フォームと同様に、モーダル フォームにも、多くの場合、他のフォームで必要になる情報が含まれています。最も一般的な例は、フォーム A からモーダル フォーム B を起動する場合です。フォーム B が閉じられると、フォーム A では、自らの処理をどのように続行するかを決めるために、ユーザーがフォーム B で行った操作を知る必要があります。フォーム B がまだメモリ内にあれば、前記のモードレス フォームの例と同じようにプロパティやメンバ関数を使ってフォーム B に問い合わせることができます。しかし、フォーム B が閉じられたときにメモリから削除される場合は、どう対処すればよいでしょうか。フォームには明示的な戻り値がないので、フォームが破棄される前に、フォームから重要な情報を保存する必要があります。
このことを説明するために、ColorForm フォームをモーダル フォームになるように変更したバージョンについて考えてみましょう。クラス宣言は次のようになります。
TColorForm = class(TForm)
ColorListBox:TListBox;
SelectButton: TButton;
CancelButton: TButton;
procedure CancelButtonClick(Sender: TObject);
procedure SelectButtonClick(Sender: TObject);
private
FColor: Pointer;
public
constructor CreateWithColor(Value: Pointer; Owner: TComponent);
end;
class TColorForm : public TForm {
__published: // IDE-managed Components
TListBox *ColorListBox;
TButton *SelectButton;
TButton *CancelButton;
void __fastcall CancelButtonClick(TObject *Sender);
void __fastcall SelectButtonClick(TObject *Sender);
private: // User declarations
String* curColor;
public: // User declarations
virtual __fastcall TColorForm(TComponent* Owner);
virtual __fastcall TColorForm(String* s, TComponent* Owner);
};
フォームには、色の名前が一覧表示される ColorListBox というリスト ボックスがあります。SelectButton というボタンが押されると、ColorListBox で現在選択されている色の名前が記録されてからフォームが閉じられます。CancelButton は、フォームを閉じるだけのボタンです。
Pointer 型の引数を取るユーザー定義のコンストラクタがクラスに追加されている点に注意してください。このポインタは、ColorForm を起動するフォームが知っている文字列を指します。このコンストラクタの実装は次のようになります。
constructor TColorForm(Value: Pointer; Owner: TComponent);
begin
FColor := Value;
String(FColor^) := '';
end;
void__fastcall TColorForm::TColorForm(String* s, TComponent* Owner)
: TForm(Owner) {
curColor = s;
*curColor = "";
}
コンストラクタでは、このポインタを private データ メンバ FColor に保存し、その参照先の文字列を空の文字列に初期化します。
メモ: 上記のユーザー定義コンストラクタを使用するには、フォームを明示的に作成する必要があります。フォームをアプリケーション起動時に自動作成することはできません。詳細については、「フォームがメモリ内に存在する間の制御」を参照してください。
アプリケーションでは、ユーザーがリスト ボックスから色を選択し、SelectButton を押して選択内容を保存し、フォームを閉じることになります。SelectButton の OnClick イベント ハンドラは、たとえば、次のようになります。
procedure TColorForm.SelectButtonClick(Sender: TObject);
begin
with ColorListBox do
if ItemIndex >= 0 then
String(FColor^) := ColorListBox.Items[ItemIndex];
end;
Close;
end;
void __fastcall TColorForm::SelectButtonClick(TObject *Sender) {
int index = ColorListBox->ItemIndex;
if (index >= 0)
* curColor = ColorListBox->Items->Strings[index];
Close();
}
イベント ハンドラでは、選択された色の名前を、コンストラクタに渡されたポインタの参照先の文字列に格納している点に注目してください。
ColorForm を効果的に使用するには、呼び出し側のフォームから既存の文字列へのポインタをコンストラクタに渡す必要があります。たとえば、フォーム ResultsForm 上のボタン UpdateButton のクリックに応答して、ColorForm が ResultsForm によりインスタンス化されるとしましょう。イベント ハンドラは次のようになります。
procedure TResultsForm.UpdateButtonClick(Sender: TObject);
var
MainColor: String;
begin
GetColor(Addr(MainColor));
if MainColor <> '' then
{do something with the MainColor string}
else
{do something else because no color was picked}
end;
procedure GetColor(PColor: Pointer);
begin
ColorForm := TColorForm.CreateWithColor(PColor, Self);
ColorForm.ShowModal;
ColorForm.Free;
end;
void __fastcall TResultsForm::UpdateButtonClick(TObject *Sender) {
String s;
GetColor(&s);
if (s != "") {
// do something with the color name string
}
else {
// do something else because no color was picked
}
}
// ---------------------------------------------------------------------
void TResultsForm::GetColor(String *s) {
ColorForm = new TColorForm(s, this);
ColorForm->ShowModal();
delete ColorForm;
ColorForm = 0; // NULL the pointer
}
UpdateButtonClick では、MainColor という文字列(String 型)を作成します。MainColor のアドレスは GetColor 関数に渡されます。この関数では、その MainColor のポインタを引数としてコンストラクタに渡して ColorForm を作成します。ColorForm は閉じられるとすぐに削除されますが、(色が選択された場合は)選択された色の名前は MainColor にまだ保存されています。色が選択されなかった場合は、MainColor には空の文字列が格納されており、このことは、ユーザーが色を選択せずに ColorForm を閉じたことを明確に示しています。
この例では、モーダル フォームからの情報を保持する文字列変数を 1 つ使用しています。もちろん、必要に応じて、もっと複雑なオブジェクトを使用することもできます。ここでは、何も変更や選択が行われずにモーダル フォームが閉じられたかどうかを呼び出し側のフォームが判断できる手段(MainColor をデフォルトとして空の文字列に初期化しておくなど)を必ず提供しなければならないということを覚えておいてください。