Characteristics of a Memo
|
|
A great deal of the functionality of a memo comes from
the TCustomEdit class, which means that all the fundamental
characteristics of a memo are the same as the edit control. Of course, the
memo adds some features to support the lines of text.
The user has the ability to type text to alter the
content of the memo box. This is possible only if the ReadOnly
property is set to true, which is the default. If you want to prevent the
user from altering the text in the memo, set the ReadOnly property to
false. You can also do this programmatically.
When a memo box opens, the compiler registers the
content of the control. If the user has the ability to change the text in
the control and if the user changes it, the compiler flags the control as
modified. To support this, the TCustomEdit class is
equipped with a Boolean property named Modified and that
its child controls inherit.
You can programmatically acknowledge that the control
has been modified by setting the Modified property to true.
If another control or some other action alters the contents of the memo, you
can make sure that this property reflects the change. You can change this
programmatically as follows:
//---------------------------------------------------------------------------
void __fastcall TForm1::Memo1KeyPress(TObject *Sender, char &Key)
{
Memo1->Modified = True;
}
//---------------------------------------------------------------------------
Like the edit control, the only event that the Memo
control can claim on its owns is the OnChange event which is a
TNotifyEvent type. This occurs when the user changes the content of the
control. This event is useful if you want to display a notification that the
text is not as it was when the form opened.
When the application focus moves from one to another
control or the application itself to a control, the OnEnter event is
fired. When the control looses focus, an OnExit event is fired.
Although the user can enter any number of characters
into a memo box, you can set a maximum number that would prevent the user
from going over this number of characters. This characteristics is
controlled by the MaxLength property of the
TCustomEdit class. At design time, you can set the maximum number
of characters in the MaxLength field. Programmatically, you can change it as
follows:
//---------------------------------------------------------------------------
void __fastcall TForm1::Memo1KeyPress(TObject *Sender, char &Key)
{
Memo1->MaxLength = 24;
}
//---------------------------------------------------------------------------
When entering text in a Memo control, the characters
start on the left side of the memo and are subsequently added on the right
side. The ability to align text is controlled by the Alignment property. For
a Memo control, the alignment is configured using the TAlignment
enumerator:
enum TAlignment { taLeftJustify, taRightJustify, taCenter };
This property works exactly as we reviewed it for the
edit control.
The TMemo class supports regular operations
performed on a text control such as undoing an action, cutting or copying
text from the control, pasting text from another control. The methods used
to accomplish these assignments are Undo(), CutToClipboard(),
CopyToClipboard(), PasteFromClipboard().
By default, the memo control is positioned where you
drop it at design time. The Align property specifies how
the memo will be aligned with regard to its container. If the memo is used
as the main area of a text editor application, you should set its
Align property to alClient.
As mentioned already, a memo is used to hold many lines
of text. To support its whole text, the TMemo class
inherits a property named Lines from its parent, the
TCustomMemo class:
__property Classes::TStrings * Lines = {read=FLines,write=SetLines};
As you can see, the TCustomMemo::Lines property
is a collection of TStrings objects. The user mostly reads and/or
enters text in the memo when interacting with the control. At design time,
you can set the text that would display when the memo comes up. To enter
this text, in the Object Inspector, click the Lines field to reveal its
ellipsis button that allows you to open the String List Editor dialog box.
If you want the control to be empty at startup, delete the content of the
String List Editor and click OK. Otherwise, type the desired text and click
OK.
To programmatically delete all lines of a memo, you can
call the Clear() methods. To select all the text in a memo, you can
call the SelectAll() method.
Practical
Learning: Using the Lines of a Memo
|
|
- On the form, double-click the Reset button
- Implement its event as follows:
//---------------------------------------------------------------------------
void __fastcall TfrmAutoRepair::btnResetClick(TObject *Sender)
{
edtCustomerName->Text = L"";
edtAddress->Text = L"";
edtCity->Text = L"";
edtState->Text = L"";
edtZIPCode->Text = L"";
edtMakeModel->Text = L"";
edtYear->Text = L"";
mmoProblemDescription->Lines->Clear();
edtTotalParts->Text = L"0.00";
edtTotalLabor->Text = L"0.00";
edtTaxRate->Text = L"5.75";
edtTaxAmount->Text = L"0.00";
edtTotalOrder->Text = L"0.00";
edtPartName1->Text = L"";
edtUnitPrice1->Text = L"0.00";
edtQuantity1->Text = L"0";
edtSubTotal1->Text = L"0.00";
edtPartName2->Text = L"";
edtUnitPrice2->Text = L"0.00";
edtQuantity2->Text = L"0";
edtSubTotal2->Text = L"0.00";
edtPartName3->Text = L"";
edtUnitPrice3->Text = L"0.00";
edtQuantity3->Text = L"0";
edtSubTotal3->Text = L"0.00";
edtPartName4->Text = L"";
edtUnitPrice4->Text = L"0.00";
edtQuantity4->Text = L"0";
edtSubTotal4->Text = L"0.00";
edtPartName5->Text = L"";
edtUnitPrice5->Text = L"0.00";
edtQuantity5->Text = L"0";
edtSubTotal5->Text = L"0.00";
edtJobDescription1->Text = L"";
edtJobCost1->Text = L"0.00";
edtJobDescription2->Text = L"";
edtJobCost2->Text = L"0.00";
edtJobDescription3->Text = L"";
edtJobCost3->Text = L"0.00";
edtJobDescription4->Text = L"";
edtJobCost4->Text = L"0.00";
edtJobDescription5->Text = L"";
edtJobCost5->Text = L"0.00";
mmoRecommendations->Lines->Clear();
edtFileOpen->Text = L"";
edtFileSave->Text = L"";
}
//---------------------------------------------------------------------------
- Press F12 to return to the form
- Double-click an unoccupied area of the form
- Implement the event as follows:
//---------------------------------------------------------------------------
void __fastcall TfrmAutoRepair::FormCreate(TObject *Sender)
{
btnResetClick(Sender);
}
//---------------------------------------------------------------------------
- Press F12 to display the form
- Save all
Supporting Carriage Return
|
|
If the memo is used to receive text, the user can press
Enter at the end of a line to move to the next line. This ability is
controlled by the Boolean WantReturns property:
__property bool WantReturns = {read=FWantReturns,write=FWantReturns};
By default, this property is set to True, which means
the user can press Enter when typing text. If you do not want to validate
the Enter key in the memo control, set this property to False. To set it
programmatically, assign the desired value to the WantReturns
property:
//---------------------------------------------------------------------------
void __fastcall TForm1::FormCreate(TObject *Sender)
{
Memo1->WantReturns = False;
}
//---------------------------------------------------------------------------
When the WantReturns property is set to false, if
the user presses Enter while the memo has focus, the Enter action would be
transferred to the form as the parent. The form in turn can find out what to
do. For example, you may have configured the form to perform a particular
action when the Enter key is pressed. The typical example is by setting a
button’s Default property to true. In this case, pressing
Enter from the memo control would cause the action associated with the
button. Even if the WantReturns of a memo is set to false, the user
can still press Ctrl + Enter to move to the next line.
The user is accustomed to pressing Tab to insert tab
characters in the text. By default, when the user presses Tab when
interacting with your application, the focus moves from one control to the
next, following the TabOrder value of the form. Even when using a
memo to perform text editing, if the user presses Tab, the focus would
switch to another control or to the form. If you want a memo to receive
focus when the user presses the Tab key, use the WantTabs Boolean
property:
__property bool WantTabs = {read=FWantTabs,write=FWantTabs};
The default value of the TCustomMemo::WantTabs property
is False, which is the right one.
As the user enters text in a memo box, the compiler
considers that a paragraph starts from the user typing a character until he
or she presses Enter. Therefore, a paragraph could be an empty space, a
character, a word, a line of text, a whole page or an entire book. Depending
on the width of the memo control, the text is incrementally added to the
right side of each previous character. If the caret gets to the right border
of the control, the text automatically continues to the next line, although
it is still considered as one paragraph. To start a new paragraph, the user
has to press Enter. The ability for the text to continue on the next line
when the caret encounters the right border of the memo is controlled by the
WordWrap property:
__property bool WordWrap = {read=FWordWrap,write=SetWordWrap};
The default value of this property is true. If you do
not want text to wrap to the subsequent line, set the WordWrap
property to false. You can also set it programmatically as follows:
//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
Memo1->WordWrap = False;
}
//---------------------------------------------------------------------------
Practical
Learning: Using a Memo
|
|
- On the form, click one of the memo controls
- In the Object Inspector, click ScrollBars, then click the arrow of
its combo box and select ssVertical
- On the form, click the other memo control
- In the Object Inspector, click ScrollBars, then click the arrow of
its combo box and select ssVertical
- On the form, double-click the Save button
- Implement its event as follows:
//---------------------------------------------------------------------------
void __fastcall TfrmAutoRepair::btnSaveClick(TObject *Sender)
{
if( edtFileSave->Text == L"" )
{
ShowMessage(L"You must enter the name of the file to save");
return;
}
else
{
// Declare a pointer to TFileStream
TFileStream *fstRepairOrder;
// Use the constructor of the TFileStream to create a file
try {
fstRepairOrder = new TFileStream(edtFileSave->Text + L".cpar", fmCreate);
fstRepairOrder->WriteComponent(edtCustomerName);
fstRepairOrder->WriteComponent(edtAddress);
fstRepairOrder->WriteComponent(edtCity);
fstRepairOrder->WriteComponent(edtState);
fstRepairOrder->WriteComponent(edtZIPCode);
fstRepairOrder->WriteComponent(edtMakeModel);
fstRepairOrder->WriteComponent(edtYear);
fstRepairOrder->WriteComponent(mmoProblemDescription);
fstRepairOrder->WriteComponent(edtTotalParts);
fstRepairOrder->WriteComponent(edtTotalLabor);
fstRepairOrder->WriteComponent(edtTaxRate);
fstRepairOrder->WriteComponent(edtTaxAmount);
fstRepairOrder->WriteComponent(edtTotalOrder);
fstRepairOrder->WriteComponent(edtPartName1);
fstRepairOrder->WriteComponent(edtUnitPrice1);
fstRepairOrder->WriteComponent(edtQuantity1);
fstRepairOrder->WriteComponent(edtSubTotal1);
fstRepairOrder->WriteComponent(edtPartName2);
fstRepairOrder->WriteComponent(edtUnitPrice2);
fstRepairOrder->WriteComponent(edtQuantity2);
fstRepairOrder->WriteComponent(edtSubTotal2);
fstRepairOrder->WriteComponent(edtPartName3);
fstRepairOrder->WriteComponent(edtUnitPrice3);
fstRepairOrder->WriteComponent(edtQuantity3);
fstRepairOrder->WriteComponent(edtSubTotal3);
fstRepairOrder->WriteComponent(edtPartName4);
fstRepairOrder->WriteComponent(edtUnitPrice4);
fstRepairOrder->WriteComponent(edtQuantity4);
fstRepairOrder->WriteComponent(edtSubTotal4);
fstRepairOrder->WriteComponent(edtPartName5);
fstRepairOrder->WriteComponent(edtUnitPrice5);
fstRepairOrder->WriteComponent(edtQuantity5);
fstRepairOrder->WriteComponent(edtSubTotal5);
fstRepairOrder->WriteComponent(edtJobDescription1);
fstRepairOrder->WriteComponent(edtJobCost1);
fstRepairOrder->WriteComponent(edtJobDescription2);
fstRepairOrder->WriteComponent(edtJobCost2);
fstRepairOrder->WriteComponent(edtJobDescription3);
fstRepairOrder->WriteComponent(edtJobCost3);
fstRepairOrder->WriteComponent(edtJobDescription4);
fstRepairOrder->WriteComponent(edtJobCost4);
fstRepairOrder->WriteComponent(edtJobDescription5);
fstRepairOrder->WriteComponent(edtJobCost5);
fstRepairOrder->WriteComponent(mmoRecommendations);
ShowMessage(L"The repair order has been saved");
btnResetClick(Sender);
}
__finally
{
delete fstRepairOrder;
}
}
}
//---------------------------------------------------------------------------
- Press F12 to return to the form
- On the form, double-click the Open button
- Implement the event as follows:
//---------------------------------------------------------------------------
void __fastcall TfrmAutoRepair::btnOpenClick(TObject *Sender)
{
if( edtFileOpen->Text == L"" )
{
ShowMessage(L"You must enter the name of the file to open ");
return;
}
else
{
// Decalre a pointer to TFileStream
TFileStream *fstRepairOrder = NULL;
try {
fstRepairOrder = new TFileStream(edtFileOpen->Text + L".cpar",
fmOpenRead | fmShareExclusive);
fstRepairOrder->ReadComponent(edtCustomerName);
fstRepairOrder->ReadComponent(edtAddress);
fstRepairOrder->ReadComponent(edtCity);
fstRepairOrder->ReadComponent(edtState);
fstRepairOrder->ReadComponent(edtZIPCode);
fstRepairOrder->ReadComponent(edtMakeModel);
fstRepairOrder->ReadComponent(edtYear);
fstRepairOrder->ReadComponent(mmoProblemDescription);
fstRepairOrder->ReadComponent(edtTotalParts);
fstRepairOrder->ReadComponent(edtTotalLabor);
fstRepairOrder->ReadComponent(edtTaxRate);
fstRepairOrder->ReadComponent(edtTaxAmount);
fstRepairOrder->ReadComponent(edtTotalOrder);
fstRepairOrder->ReadComponent(edtPartName1);
fstRepairOrder->ReadComponent(edtUnitPrice1);
fstRepairOrder->ReadComponent(edtQuantity1);
fstRepairOrder->ReadComponent(edtSubTotal1);
fstRepairOrder->ReadComponent(edtPartName2);
fstRepairOrder->ReadComponent(edtUnitPrice2);
fstRepairOrder->ReadComponent(edtQuantity2);
fstRepairOrder->ReadComponent(edtSubTotal2);
fstRepairOrder->ReadComponent(edtPartName3);
fstRepairOrder->ReadComponent(edtUnitPrice3);
fstRepairOrder->ReadComponent(edtQuantity3);
fstRepairOrder->ReadComponent(edtSubTotal3);
fstRepairOrder->ReadComponent(edtPartName4);
fstRepairOrder->ReadComponent(edtUnitPrice4);
fstRepairOrder->ReadComponent(edtQuantity4);
fstRepairOrder->ReadComponent(edtSubTotal4);
fstRepairOrder->ReadComponent(edtPartName5);
fstRepairOrder->ReadComponent(edtUnitPrice5);
fstRepairOrder->ReadComponent(edtQuantity5);
fstRepairOrder->ReadComponent(edtSubTotal5);
fstRepairOrder->ReadComponent(edtJobDescription1);
fstRepairOrder->ReadComponent(edtJobCost1);
fstRepairOrder->ReadComponent(edtJobDescription2);
fstRepairOrder->ReadComponent(edtJobCost2);
fstRepairOrder->ReadComponent(edtJobDescription3);
fstRepairOrder->ReadComponent(edtJobCost3);
fstRepairOrder->ReadComponent(edtJobDescription4);
fstRepairOrder->ReadComponent(edtJobCost4);
fstRepairOrder->ReadComponent(edtJobDescription5);
fstRepairOrder->ReadComponent(edtJobCost5);
fstRepairOrder->ReadComponent(mmoRecommendations);
}
__finally
{
delete fstRepairOrder;
}
}
}
//---------------------------------------------------------------------------
- Press F12 to return to the form
- Double-click the Close button
- Implement its event as follows:
//---------------------------------------------------------------------------
void __fastcall TfrmAutoRepair::btnCloseClick(TObject *Sender)
{
Close();
}
//---------------------------------------------------------------------------
- Save all
- Press F9 to execute the application
- Create a repair order
- Click Save
- Close the form and return to your programming environment
- To execute the application, on the main menu, click Run -> Run
- In the File Open edit control, enter the name of the repair file you
had saved
- Click Open
- Close the form and return to your programming environment
|