Borland's OWL uses transfer buffers to transfer data between a program and a dialog box. For example if you wish information to be displayed in a TEdit box, you would place that information in the corresponding transfer buffer before calling on the dialog box to Execute. Similarly if you wish to retrieve data, you simply look in the transfer buffer after the call to Execute and information entered by the user is found in the transfer buffer. The structure of a transfer buffer is created automatically by ClassExpert when you add instance variables for features in a dialog box.
Each transfer buffer is a struct (public class) whose fields are instance variables associated with features of the dialog box. Different features have instance variables of different types. These types are listed here.
| Type of Dialog Item | Type of the Instance Variable |
| TEditBox | Char* (array of char) |
| TListBox | TListBoxData |
| TCheckBox/TRadioButton | bool (true or false) |
When you create instance variables for any of your dialog box features using ClassExpert you automatically get much of the mechanism needed to use Transfer Buffers.
You may use the static transfer buffer created for you by ClassExpert, but it is much more useful to add a constructor to your dialog class that has a pointer to a transfer buffer as a parameter. In our grocery example the header file contains the definition the transfer buffer struct and I have added a second constructor. Make sure to add this constructor as the second constructor, or you will cause ClassExpert's data base to be corrupted and it will no longer work properly.
//{{TDialog = NewGroceryItem}}
struct NewGroceryItemXfer {
//{{NewGroceryItemXFER_DATA}}
char _cost[ 255 ];
char _id[ 255 ];
char _inStock[ 255 ];
char _name[ 255 ];
//{{NewGroceryItemXFER_DATA_END}}
};
class NewGroceryItem : public TDialog {
public:
NewGroceryItem (TWindow* parent, TResId resId = IDD_NEW_GROCERY_ITEM, TModule* module = 0);
// I added this
NewGroceryItem (NewGroceryItemXfer *tb,TWindow* parent, TResId resId = IDD_NEW_GROCERY_ITEM, TModule* module = 0);
virtual ~NewGroceryItem ();
//{{NewGroceryItemXFER_DEF}}
protected:
TEdit *_cost;
TEdit *_id;
TEdit *_inStock;
TEdit *_name;
//{{NewGroceryItemXFER_DEF_END}}
}; //{{NewGroceryItem}}
The new constructor is almost identical to the original. The main difference is that the transfer buffer pointer passed in as a parameter replaces the static transfer buffer.
NewGroceryItem::NewGroceryItem (NewGroceryItemXfer *tb,TWindow* parent, TResId resId, TModule* module):
TDialog(parent, resId, module)
{
//{{NewGroceryItemXFER_USE}}
_cost = new TEdit(this, IDC_COST, 255);
_id = new TEdit(this, IDC_IDENT, 255);
_inStock = new TEdit(this, IDC_INITSTOCK, 255);
_name = new TEdit(this, IDC_NAME, 255);
// At this point nothing has been changed. Here we replace
// SetTransferBuffer(&NewGroceryItemData); with
SetTransferBuffer(tb); // tb is a pointer so do not put &tb here
//{{NewGroceryItemXFER_USE_END}}
// INSERT>> Your constructor code here.
}
When the user enters values in _cost and _instock you will want to restrict the data types to double and int respectively. To do that you simply add a validator to each when you define them in the constructor.
_cost = new TEdit(this, IDC_COST, 255);
_cost->SetValidator ( new TFilterValidator ( "0-9." ) ); //Restrict to double
_inStock = new TEdit(this, IDC_INITSTOCK, 255);
_inStock->SetValidator ( new TFilterValidator ( "0-9" ) ); //Restrict to int
To use a transfer buffer with this added constructor parameter, we first create an instance of the transfer buffer. Next we initialize this instance with whatever values we want. When we make the call to execute, we use the dialog box class constructor that has the pointer to the transfer buffer. If Execute returns ok, we then retrieve the values and use them as needed. Compare the code below with that created using a TInputDialog.
void Exam5Window::cmAddItem ()
{
// INSERT>> Your code here.
NewGroceryItemXfer tb;
tb._name[0]='\0'; / /null string for name
tb._id[0]='\0'; // null string for id
strcpy(tb._cost,"0.00"); // set cost to zero
strcpy(tb._inStock,"0"); // set inStock to zero
if (NewGroceryItem(&tb,this).Execute()==IDOK)
{
string name(tb._name);
string id(tb._id);
double cost = atof(tb._cost);
int howMany = atoi(tb._inStock);
GroceryItem g(name,id,cost,howMany);
groceries.addItem(g);
}
}