![]() |
Edit Text-Based Controls |
|
Edit Boxes |
|
Introduction |
|
An edit box is a Windows control used to get or display text for the user’s interaction. At its most regular use, an edit box serves as a place to fill out and provide information. Such a use is common on employment applications, login dialog boxes, etc. Like most other controls, the role of an edit box is not obvious at first glance; that is why it should be accompanied by a label that defines its purpose. From the user’s standpoint, an edit box is named after the label closest to it. Such a label is usually positioned to the left or the top side of the edit box. From the programmer’s point of view, an edit box is a placeholder used for various things. For example, you can show or hide it as you see fit. You can also use it only to display text without allowing the user to change it. |
|
To create an edit box, once again, Borland C++ Builder provides a lot of choices. The most fundamental edit box is designed with the Edit control
The most important aspect of an edit box is its text, whether it is displaying or requesting it. This is the Text property. When you add an edit control, C++ Builder initializes it with the name of the control; this would be Edit1 for the first edit box, Edit2 for the second, etc. If you want the control to display some text when the form launches, type the text in the Text property field in the Object Inspector. Otherwise, if you want the edit box to be empty when it comes up for the first time, delete the content of the Text field. By default, a newly created edit box is used to both display and receive text from the user. If you want to user to read text without being able to change it, set the ReadOnly Boolean property to true. Its default value is false. As mentioned already, an edit box should be accompanied by a label that indicates what it is used for. To support this relationship, the Label control provides various properties. An accelerator character is a symbol of the label that provides easy access to its edit box. On the label, such a character is underlined. An example would be First Name. The idea is that, if the user presses Alt key in combination with the label’s underlined characters, the edit box it accompanies would receive focus. To create an accelerator key, choose one of the label’s characters and precede it with an ampersand character when setting its caption. An example would be &First Name. If you want a label to display the accelerator character instead of a plain ampersand, set the label’s ShowAccelChar property to true. If you set it to true but need to display an ampersand, type two & characters where the ampersand would be shown. The ShowAccelChar property of a label is only used to indicate that the label will display an accelerator character and the & symbol typed on the label creates that accelerator character. To indicate which edit box would receive focus when the accelerator character of the label is invoked; the label control provides the FocusControl property. To use this property, select the label on the container. Then, on the Object Inspector, click the FocusControl field to display its combo box. From there, you can select one of the existing controls. The control, such as an edit box, must be able to receive focus. The CharCase property of an edit box control allows the content of an Edit control to apply a character case of your choice. The CharCase property is controlled by the TEditCharCase enumerator defined as follows: enum TEditCharCase { ecNormal, ecUpperCase, ecLowerCase };
By default, it is set to ecNormal, which respects whatever character case is typed in an edit box. Otherwise, you can set it to ecUpperCase or ecLowerCase to set the edit box’ characters to uppercase or lowercase respectively. Text typed in an edit box appears with its corresponding characters unless you changed the effect of the CharCase property from ecNormal. This allows the user to see and be able to read the characters of an edit. If you prefer to make them un-readable, you can use the PasswordChar property. Although this property is a char type of data, changing it actually accomplishes two things. Its default value is #0, which means that the characters typed in it will be rendered in their alphabetic corresponding and readable characters. If you change it, for example to *, any character typed in it would be un-readable and be replaced by the value of this property. You can use any alphabetic character or digit to represent the characters that would be typed but you must provide only one character. Alternatively, you can specify an ASCII character instead. To do this, type # followed by the number representing the ASCII character. For example, #98 would display b for each character. When using a form, the user can press Tab to move from one control to another. By default, when such a control receives focus from the user pressing Tab, the whole text in an edit control is selected. This is controlled by the AutoSelect property. If you do not want that, you can set the AutoSelect Boolean property to false. One of the actions the user may be asked to perform on an edit box is to type text in it. If the control already contains text, the user can read it. Another common action the user performs is to select text contained in the control. The user must have the option to select only part of the text or its whole content. To do this, the user can click and hold the mouse on one end of the selection and drag to the desired end. This allows for partial selection. The area where the user start dragging during selection is represented by the SelStart property. When the user ends the selections, the length of the text selected is represented by the SelLength property. The portion of text selected is represented by the SelText property, which is an AnsiString type. These properties allow you either to programmatically select text or to get information about text that the user would have selected in the edit box.
The edit control is based on the TEdit class whose immediate parent is TCustomEdit. Like every VCL class, it has a constructor and a destructor. The constructor can be used to dynamically create an edit control. The TEdit class provides other methods derived from the control’s parent or from ancestor classes. We saw earlier the properties related to the selection of text from an edit control performed either by you or by a user. Alternatively, the user may want to select the whole content of the control. To programmatically select the whole text of an edit control, call the SelectAll() method. Its syntax is: void __fastcall SelectAll(); The contents of an edit box can be empty or contain some text. If you want it empty, use the Clear() method. This would delete the whole contents of the control: //---------------------------------------------------------------------------
void __fastcall TForm1::btnClearClick(TObject *Sender)
{
Edit1->Clear();
}
//---------------------------------------------------------------------------
If the user or another control or action had selected text on the edit control, you can delete the selection using the ClearSelection() method. This method first finds if some text is selected. If so, the selected text would be discarded. If nothing is selected, the method would not do anything. To delete a selected text, you can write: //---------------------------------------------------------------------------
void __fastcall TForm1::btnClearSelectionClick(TObject *Sender)
{
Edit1->ClearSelection();
}
//---------------------------------------------------------------------------
The Edit control is equipped with many events. Some of these events are from its parent class the TCustomEdit class and some others are from ancestor classes. The OnEnter() event occurs when a text-based control receives focus. This happens when the user clicks the edit box, after previously pressing Tab, to give focus to the control. The OnChange() event occurs as the user is typing text in the control. This happens as the user is changing the content of an edit control; this sends a message that the content of the edit box has changed or has been updated. You can use this event to check, live, what the user is doing in the edit box. For example, if you create a dialog with a first and last names edit boxes, you can use another edit box to display the full name. The controls could be drawn as follows:
You can implement the OnChange event of the first name edit box as follows: //---------------------------------------------------------------------------
void __fastcall TfrmPersInfo::edtFirstNameChange(TObject *Sender)
{
edtFullName->Text = edtFirstName->Text + " " + edtLastName->Text;
}
//---------------------------------------------------------------------------
When the second edit box is being edited, you can implement its OnChange event as follows: //---------------------------------------------------------------------------
void __fastcall TfrmPersInfo::edtLastNameChange(TObject *Sender)
{
edtFullName->Text = edtFirstName->Text + " " + edtLastName->Text;
}
//---------------------------------------------------------------------------
The OnExit event occurs when the control loses focus. In the case of an edit box, this could happen if the control has focus and the user presses Tab; the edit box would lose focus.
It is by an unavoidable habit that almost every edit control is accompanied by a label. The reason is that, as stated already when reviewing the edit control, a text box has no mechanism of indicating what it is used for. That precision is usually handled by a label. To make it easy, starting with C++ Builder 6, Borland created a control that combines an edit control and its accompanying label: the LabeledEdit control. To create a LabeledEdit control, click its button
The LabeledEdit control is an object of type TLabeledEdit. This control shares its ancestry with the edit control: their parent is the TCustomEdit class. The TLabeledEdit class itself is derived from the based on the TCustomLabeledEdit class. Based on its ancestry, the LabeledEdit control inherits the same functionality as the edit control. After adding a LabeledEdit control to your application, you notice that it is accompanied by a label but both are treated as one control. By default, the (accompanying) label is positioned above the edit control. The position of the label is controlled by the LabelPosition property. This property is type TLabelPosition, which is an enumerator. It can have one of four values:
If you use a separate label and edit controls in your application, you know that you can decide about the distance between both controls. For a LabeledEdit object, this characteristic is handled by the LabelSpacing property, which is an integer. The default value of this property is 3. In most cases, and especially if you decide to position the label to the left, this value would be too little. We mentioned that the TLabeledEdit class, on which the LabeledEdit control is based, derived from the TCustomEdit class, which provides functionality only for an edit control. To respect the avoidance of double-inheritance in a VCL control, the LabeledEdit control is equipped with a property called EditLabel. The role of this property is to identify or represent the label part of the LabeledEdit. To support the whole functionality of a label, the EditLabel property is of type TBoundLabel. The TBoundLabel class is derived from the TCustomLabel class, which is the same immediate class of the Label control. Based on this, to perform any label-related operation on a LabeledEdit control, first invoke its EditLabel property and then access any of the properties and characteristics we reviewed for the label control. At design time, the EditLabel property is represented with a + field in the object inspector. As such, you can click the + button:
This allows you to manipulate the label side of the control.
The MaskEdit is a special Edit object that provides more control over text entered or displaying in an edit box. The biggest difference between the Edit and the MaskEdit controls is the masking possibilities available on the latter.
To add a MaskEdit control to your form, from the Additional tab of the Tool Palette, click the MaskEdit button
The most important property of a MaskEdit control, which sets it apart from the (traditional) Edit control, is its ability to control what the user can and cannot enter in the text side. To configure this text, on the Object Inspector, click the EditMask field to reveal its ellipsis button. You have two options:
Create a new file following the example. Each mask is typed on its own line and press Enter at the end of each mask. To save the file, locate the C:\Program Files\Borland\Cbuilder5\Bin folder. In the Save dialog box, change the Save As Type to All Files. Type a name in one-word followed by an extension .dem extension. To use your list of masks, invoke the Input Mask Editor, click Masks… Locate the C:\Program Files\Borland\Cbuilder5\Bin folder. Change the Files of Types to All files. Click the file you created and click Open. You can also set a mask programmatically using the symbols appropriate for the masks. Here is an example: //---------------------------------------------------------------------------
void __fastcall TForm1::FormCreate(TObject *Sender)
{
// Mask for an 8 character file name + 3-character extension
// The first character is automatically converted to uppercase
// After the first character, the user can enter an alphabetical
// character or a digit to complete the 8 characters.
// The other 7 characters and the extensions are converted to lowercase
edtFileName->EditMask = ">L<aaaaaaa.<LLL;1;_";
}
//---------------------------------------------------------------------------
As a text-based control, the content of the MaskEdit control is represented by the Text property, which is an AnsiString object. Following the EditMask you had set in the Input Mask Editor editor, you can use a default text that would display when the control opens. To set this text, on the Object inspector, click Text and type a value that abides by the rules of the EditText field. At design time, C++ Builder will assist you and make sure that the value you type is appropriate. At runtime also, the user will have to follow the rules of the mask. When a mask is configured for a MaskEdit control, the compiler reinforces the rule to make sure the user would follow number and types of characters allowed in the edit box. If you add a MaskEdit control but do not apply a mask to it, you can limit the number of characters that the user can enter in the box. The maximum number of characters allowed is set using the MaxLength property. This property has any effect only if no mask is applied to the control. At design time, type an integer value for the property. At runtime, assign an appropriate value to the control. The IsMasked Boolean property can be used to check whether a MaskEdit control has been configured with a mask already.
On its own, the MaskEdit control has only two methods: the constructor and the destructor. The TMaskEdit constructor is used to dynamically create a MaskEdit object. This requires an instance of a TMaskEdit class. Using the new operator, specify the owner of the control. You must also specify the parent of the variable. Here is an example: //---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
TMaskEdit *Mascot = new TMaskEdit(Form1);
Mascot->Parent = Form1;
}
//---------------------------------------------------------------------------
A MaskEdit object created like this is just a classic Edit control. If you want to make a true MaskEdit object, set its properties as needed, namely an EditMask and possibly a Text properties. This time, not only will you have to work in a non-visual setting but you should also make sure that the EditMask and the Text properties are synchronized. Sometimes, this would involve trial-and-error.
The main event of the MaskEdit control occurs when the content of the control has been altered. The compiler takes care of validating the characters and symbols while the user is editing the edit box. When the user has finished and presses Enter or Tab to possibly shift the focus to another control, a notification is sent to the operating system. If the value entered in the control does not conform to the EditMask property, an error is thrown and the application may stop responding. For this reason, you should use the MaskEdit control only when appropriately needed; or you should write an event handler or function that would deal with errors of this control.
To make it easy to edit single-line text values of a database, the VCL provides the DBEdit control implement through the TDBEdit class that is part of the DBCtrls.hpp library. This control is explicitly made to interpret the value of a database field created using the Alpha, the Date, or the Time data types of a Paradox database. It can also recognize character-based data types of SQL or ADO. The TDBEdit class is derived from the TCustomMaskEdit class. To add a DBEdit control to your application, click the DBEdit button in the Data Controls tab of the Tool Palette and click the container that would hold it.
The database edit control is meant to hold one line of text. Probably the first action you take to configure it is to specify the source of its value. This is done using the DataSource property, which is a TDataSource value. After pointing out the source of its value, you can specify the particular database field that would feed its value. This done by assigning the name of a field to the DataField property. If you had properly created your database, these two properties may be the only ones you would need to configure. When a DBEdit control is not empty, the value it holds is represented by the Text property it inherits from the TCustomerMaskEdit class. You can use this property either to change the value in the control or to retrieve the value held by the control. In most cases, you create an edit control to let the user enter and view data. If you want to prevent the user from entering values in the DBEdit control, you can set its ReadOnly property to false. If you had created the field as a date-based, time-based, or a specific type of value, and you want to assist the user during data entry, the DBEdit control is equipped with various masks inherited from its parent, exactly like those used on the MaskEdit control. To configure the mask for this control, you must open the table's Field Editor and display the field's properties in the Object Inspector. At any time, to find out if the DBEdit control holds a mask, you can check the value of the Boolean IsMasked property. Keep in mind that this property only lets you know whether the control has a mask. If you want to find what that mask is, in case there is one, you can get the value of the EditMask property of the control through its Field property.
The DBEdit control inherits most of its methods and properties from its parents: The TCustomMaskEdit and the TCustomEdit classes. We had already reviewed them for the Edit control.
The IP Address control is an object that allows the user to enter an IP address or you to retrieve one. The control appears like an edit box or a masked edit box divided in four (semi-independent) sections:
The IP Address control is aware of the basic rules of IP address formatting. To proceed with the control, the user can click the first field and start typing. Each section allows only digits. By default, the control is configured to allow only numbers that range from 0 to 255 but you the programmer can change this allowed range. It does not allow a negative character. If the user enters a value higher than the allowed, the number is reset. Each field can allow only three digits. Once a valid value has been entered in a field, the focus shifts to the next section to the right.
To create an IP Address control, you can either use the traditional Win32 approach or create your own component that would implement the behavior set by the Win32 API. Because in this book we will not create custom components, we will use the Win32 technique. Therefore, to create an IP Address control, call the CreateWindow() or the CreateWindowEx() function and specify the class name as WC_IPADDRESS. Here is an example:
Some of the jobs you will perform on an IP Address control consist of checking whether the control contains an address, setting an IP address in its fields, retrieving the current address from its fields, or deleting an address from its fields. Before doing anything on an IP Address control, you may want to check whether its fields are filled with some entries. To do this, you can send an IPM_ISBLANK message using the SendMessage() function. Because you are only checking the contents of the control, the wParam and the lParam parameters are not used and must be passed with 0 values. Here is an example: //---------------------------------------------------------------------------
void __fastcall TForm1::FormDblClick(TObject *Sender)
{
BOOL IsThereAnAddress = SendMessage(hWndIPAddress, IPM_ISBLANK, 0, 0);
if( IsThereAnAddress == True )
ShowMessage("There is no IP address");
}
//---------------------------------------------------------------------------
On the other hand, if the control already contains an IP address, whether it is complete or not, before performing such operations as changing its values or else, you may want to completely delete the current IP address. This is done by sending an IPM_CLEARADDRESS message to the control using the SendMessage() function. The wParam and the lParam parameters are not used and will be passed as 0. Here is an example: //---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
SendMessage(hWndIPAddress, IPM_CLEARADDRESS, 0, 0);
}
//---------------------------------------------------------------------------
By default, when the IP Address control is created, it is blank: its field do not contain values. Whether the control is empty or not, if you want to fill it up, you must first create an address. This is done by calling the MAKEIPADDRESS macro. Its syntax is: LPARAM MAKEIPADDRESS(BYTE b0, BYTE b1, BYTE b2, BYTE b3); This macro simply requires 4 byte values as arguments. Each value should range from 0 to 255. Here is an example: MAKEIPADDRESS(212, 56, 198, 92); The MAKEIPADDRESS macro is only used to create an address. If you want to pass that address to an IP Address control, you can send it an IPM_SETADDRESS message using the SendMessage() function. The wParam argument is not used and must be passed as 0. The address to be set is passed as the lParam argument, which results from a call to the MAKEIPADDRESS macro. Here is an example:
If the control already contains an address and you want to retrieve it, send it an IPM_GETADDRESS message using the SendMessage() function. The syntax you would use is: lResult = SendMessage((HWND) hWndControl, (UINT) IPM_GETADDRESS, 0, (LPARAM) lParam); This version of the SendMessage() function returns the number of non-empty fields of the address. Each one of the four fields of an IP address has a particular value. The values of these fields can be identified using the following macros: BYTE FIRST_IPADDRESS(LPARAM lParam); BYTE SECOND_IPADDRESS(LPARAM lParam); BYTE THIRD_IPADDRESS(LPARAM lParam); BYTE FOURTH_IPADDRESS(LPARAM lParam); Each one of these macros retrieves the value stored in their respective fields. Here is an example:
When the fields of an IP Address control are empty, the user can fill them up with some vales. To use it, the user must give it focus and start typing. Once he has provided the three digits of a field, the caret moves to the next field. This is automatically done. If you want to programmatically set the focus to a particular field in response to some user’s action, you can send an IPM_SETFOCUS message to the control. The fields of the control are in a zero-based array where the most left field has an index of 0 and the most right field has an index of 3. To set focus to a field, pass its index as the wParam parameter. The lParam parameter is not used. By default, each field of an IP address has a range of values from a minimum whose default value is 0 and a maximum whose default value is 255. The control is so much aware of these values that, if the user tries entering a value that is lower than the set range, the control would not respond. For example if the user tries typing – for a negative value, it would not be accepted. On the other hand, if the user tries to enter a value that is higher than the range, the control would reset the field to the set maximum. If you want to control the range of values allowed in a particular field, create it using the MAKEIPRANGE macro. Its syntax is: LPARAM MAKEIPRANGE(BYTE low, BYTE high); The MAKEIPRANGE macro is only used to create a range of values. In order to actually assign this range to an IP Address control, send an IPM_SETRANGE message to the control using the SendMessage() function. The wParam parameter is used to specify the index of the field whose range you want to set. The lParam parameter contains the new range set by the return value of the MAKEIPRANGE macro. Here is an example: //---------------------------------------------------------------------------
void __fastcall TForm1::FormCreate(TObject *Sender)
{
LPARAM wRangeForField3 = MAKEIPRANGE(52, 212);
hWndIPAddress = CreateWindowEx( 0,
WC_IPADDRESS,
NULL,
WS_CHILD | WS_VISIBLE | WS_TABSTOP,
90, 14, 120, 20,
Handle,
NULL,
HInstance,
NULL );
SendMessage(hWndIPAddress, IPM_SETRANGE, 2, wRangeForField3);
}
//---------------------------------------------------------------------------
Normally, you will usually need to control the range of values for a field in response to the user’s entry in the previous field. This assignment is not handled by the control because it lets the programmer take this role and responsibility.
Although the IP Address control is not an edit box, both share a few characteristics such as their appearance. Like every visual and non-static control, in order to use an IP Address control, the user must give it focus. This can be done by clicking a field in the control. When the IP Address control receives focus, it sends an EN_SETFOCUS message, which produces an event similar to the Edit control’s OnEnter() event. Like the edit control, when the user starts typing a new value in the IP Address control, it sends an EN_CHANGE message which produces an OnChange() event (similar to that of the Edit control). If the user starts changing the value of a field, the control sends the IPN_FIELDCHANGED notification message. If the user clicks away, which causes the control to lose focus, it sends an EN_KILLFOCUS message. This produces an event similar to the OnExit() event of the VCL’s Edit control.
|
| Previous | Copyright © 2005 Yevol | Next |