![]() ![]() |
Tip #2 - Non-FDX Form Communication
When using FDX to communicate between forms, there is a certain amount of design overhead involved, and is very useful with complex form communication requirements. However, when dealing with basic form communication requirements, there is a simple way of achieving the required communication that may be more appropriate than FDX.
Consider a circumstance in which you would like to set up two forms, the parent with a label and control button, and a child with a text box and control button. The parent will have a button which will create an instance of the second form. After entering text in the text box of the second form and pressing the control button, this will fill the parent's label to the contents of its text box, and will then close. Below are the steps for achieving this without FDX.
- Start by creating the two forms as they look above, with the the first form having a label and a control button, and the second having a text box and a control button. Keep the first form as the default form type (Modeless Dialog) and make the second form a Modal Dialog. Name the first form Form1 and the second Form2.
- The next step is to allow the first form to create an instance of the second when the Change Label control button is clicked - this is done in the Click event for that button. However before being able to create an instance of the child form, the parent form must know what the child form is - it must "see" the child. This can be accomplished by including the header file for the child form in the header of the parent as shown below.
Now that Form1 can see Form2, an instance of Form2 may be created from Form1 at any point after the inclusion of its header file. In this particular example, the instance of Form2 will be created as shown at right. By creating Form2 as a modal dialog, we have avoided multi-threading issues by ensuring that the line form2->Create() will not return until _form2 calls its Close() method.
- To this point, however, we only have only established a one-way communication from Form1 to Form2 through Form1::_form2 - we still have no way to communicate with Form1 from Form2 to pass the result back. However, the most obvious solution of inserting the line #include "Form1.hpp" in the Form2 header file and creating a class attribute such as Form1 *_form1 will cause problems. This is due to the fact that two classes cannot fully understand each other simultaneously, which arises when each is trying to include an instance of the other within its class definition.
To rectify this, we need to include something called a forward declaration. A forward declaration is simply a line that will let the compiler know that a class exists, without being required to actually define it. Thus, two classes can have references to each other without knowing exactly how each other is built, only that they in fact exist, and can be referenced and created at runtime. A forward declarator would appear as follows:
Simply modify your Form1 source to contain the class Form1; line, and a similarly modified line in your Form2 source, and then each class will be able to see that the other exists without having to know its structure.
Now that Form2 can see the Form1 type, our next objective is to allow the instantiated Form2 object to keep track of its specific parent. To do this, the Form1 object (main window) must pass a pointer to itself to the Form2 object it is instantiating. The best time to do this is when we create our Form2 object, so we need to create a new overloaded constructor to fulfill this purpose. To create a new constructor: choose the View|Classes menu option from the main Power++ menu, and select the File|Create User Function... menu option. Fill in the dialog as shown to the right, click OK.By then adding a Form1 *_form1 private attribute to the Form2 class in the same manner as the Form2 *_form2 in Form1 and assigning it the value of the passed parameter in our new constructor (see left), we have accomplished the creation of two form classes which can directly access each other's public attributes and methods. At left is a sample of how the new constructor might appear. Remember to change the constructor call in the cb_1_click event to call the new constructor! This can be done by passing this as the constructor's argument, so that it becomes _form2 = new Form2 ( this )
- Although Form2 can now access Form1 objects, there is not much to access since only constructors and destructors exist, and all visual objects on the form are created as protected attributes (i.e. we cannot change the label directly from the child window). Thus, we need to provide a public method in the Form1 class to perform the label update based on passed parameters. We will then get the Form2 object to call this method, thus completing our objective. By creating a new user function as in the previous step with a prototype of UpdateLabel ( const WString &str ); and defining the body as
Form1::UpdateLabel ( const WString &str ) {
label_1->SetText( str );
}
we can now change the label in the parent form by having the child form call this method with the contents of its text box as the argument.
To get the child to call this newly created method, the code for the Click event of the control button must be modified as shown to the right.
- Now run your new application!
Click here to see Tip#3Return to Power++ Home Page.
to top of page
Copyright © 1999 Sybase, Inc. All Rights Reserved.
Privacy Policy
Legal