Just like modeless forms, modal forms often contain information needed by other forms. The most common example is when form A launches modal form B. When form B is closed, form A needs to know what the user did with form B to decide how to proceed with the processing of form A. If form B is still in memory, it can be queried through properties or member functions just as in the modeless forms example above. But how do you handle situations where form B is deleted from memory upon closing? Since a form does not have an explicit return value, you must preserve important information from the form before it is destroyed.
To illustrate, consider a modified version of the ColorForm form that is designed to be a modal form. The class declaration is as follows:
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); };
The form has a listbox called ColorListBox with a list of names of colors. When pressed, the button called SelectButton makes note of the currently selected color name in ColorListBox then closes the form. CancelButton is a button that simply closes the form.
Note that a user-defined constructor was added to the class that takes a Pointer argument. Presumably, this Pointer points to a string that the form launching ColorForm knows about. The implementation of this constructor is as follows:
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 = ""; }
The constructor saves the pointer to a private data member FColor and initializes the string to an empty string.
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(); }
Notice that the event handler stores the selected color name in the string referenced by the pointer that was passed to the constructor.
To use ColorForm effectively, the calling form must pass the constructor a pointer to an existing string. For example, assume ColorForm was instantiated by a form called ResultsForm in response to a button called UpdateButton on ResultsForm being clicked. The event handler would look as follows:
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 creates a String called MainColor. The address of MainColor is passed to the GetColor function which creates ColorForm, passing the pointer to MainColor as an argument to the constructor. As soon as ColorForm is closed it is deleted, but the color name that was selected is still preserved in MainColor, assuming that a color was selected. Otherwise, MainColor contains an empty string which is a clear indication that the user exited ColorForm without selecting a color.
This example uses one string variable to hold information from the modal form. Of course, more complex objects can be used depending on the need. Keep in mind that you should always provide a way to let the calling form know if the modal form was closed without making any changes or selections (such as having MainColor default to an empty string).
Copyright(C) 2009 Embarcadero Technologies, Inc. All Rights Reserved.
|
What do you think about this topic? Send feedback!
|