Transfer Buffers

What are Transfer Buffers

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.

Types of Fields in Transfer Buffer

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)

How to Create Transfer Buffers

Changes to the Dialog Class

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.

Using 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.

}

Adding Validators

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

Changes to Calls to the Dialog Box

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);
    }
}

Complete Example

For the complete code of this example click here.