In Windows programs, user input is often collected using edit controls. In this section you will also learn about
Every identifier used to name a variable or function has a specific scope when it is created, and this scope determines how and where that name can be used. If a variable is "in scope" at a certain point in a program, it is visible and can be used in most circumstances. If it is "out of scope," it is not visible, and your program will not be capable of using that variable.
One simple type of scope is shown in the following code sample. The following code is not legal because the variable myAge is used before it is declared:
myAge = 12; int myAge;Because the identifier myAge is not in the current scope, it cannot be assigned a value.
Just a Minute: The preceding example illustrates one simple property about visibility: it almost always runs "downward," beginning at the point where the variable is declared. There are also several different types of scope, ranging from very small to very large.
Time Saver: In general, your program should use variables that have as small a scope as possible. The smaller the scope, the less chance that an identifier will be accidentally misused or subjected to side effects. For example, passing objects as parameters to a function is always better than relying on global variables. Using variables that are local to the function helps make the function more reusable.
int foo;
int main()
{
return 0;
}
In this example, the variable foo is in scope from the point of
its declaration to the end of the source file. For this reason, this type
of local scope is sometimes called file scope. All declarations
that occur outside class or function definitions have this type of scope.
Variables declared inside a function body have local scope and are visible only within the function.
Another type of local scope is block scope, where a variable within a compound statement or other block is visible until the end of the block, as shown in Listing 6.1.
if( bPrinting == true)
{
int nMyAge = 42;
cout << "My age is " << nMyAge << endl;
}
// nMyAge is not in scope here.
The variable nMyAge has block scope and can be used only between
the curly braces.
None of the labels declared in a function are visible outside the function. This means that the C++ language does not directly support jumping to a label outside the current function. It also means that you can reuse labels in different functions.
If a class or variable name is used to qualify access to the identifier, it also is visible outside the class. For example, if a class is defined as follows, the variables m_myVar and m_myStaticVar are in scope for all the CFoo member functions:
// class CFoo
class CFoo
{
public:
CFoo();
int GetMyVar();
int GetStaticVar();
int m_myVar;
static int m_myStaticVar;
};
int CFoo::m_myStaticVar;
Outside the CFoo class, the variables can be accessed only through
a CFoo object, like this:
aFoo.m_myVar = 42;There is one exception to the rule that requires a member to be accessed with a variable name: A class member declared as static is shared by all objects of that class. Static members of a class exist even when no objects of a class have been created. To access a static class member without using a class object, prefix the class name to the member name, like this:
CFoo::m_myStaticVar = 1;
Just a Minute: Lifetime can be an important issue when you design your program. Large objects can be costly to create and destroy. By understanding the lifetime of objects created in your programs, you can take advantage of features in the C++ language that help your programs run more efficiently.
#include <iostream>
using namespace std;
void PrintMessage();
int main()
{
for( int nMessage = 0; nMessage < 10; nMessage++ )
PrintMessage();
return 0;
}
void PrintMessage()
{
static int nLines = 1;
cout << "I have printed " << nLines << " lines." << endl;
nLines++;
}
New Term: A single-line edit control is an edit control that enables a single line of text to be entered.
New Term: A multiple-line edit control, sometimes called an MLE, is an edit control that enables multiple lines of text to be entered.
Edit controls are usually found in dialog boxes. Almost anywhere user input is required, you can usually find an edit control.
A prompt in the form of default text can be provided for an edit control. In some situations, this can reduce the amount of typing required by a user. All edit controls also support a limited amount of editing, without any need for extra programming on your part. For example, the standard cut-and-paste commands work as expected in an edit control. Table 6.1 lists the editing commands available in an edit control.
| Command | Keystroke |
| Cut | Control+X |
| Paste | Control+V |
| Copy | Control+C |
| Undo | Control+Z |
Just a Minute: Because of the built-in editing capabilities of the edit control, it's possible to create a simple text editor using a multiple-line edit control. Although an MLE cannot replace a real text editor, it does provide a simple way to collect multiple lines of text from a user.
One difference between edit controls and the pushbutton controls you saw in Section 5, "Button Controls," is that a button control is normally used to generate events. An edit control can generate events also, but it most often is used to actually store data.
The MFC class CEdit is often used to interact with edit controls. As you will see in the next section, you can use ClassWizard to associate an edit control with a specific CEdit object. An edit control can also be associated with a CString object, which can simplify the use of edit controls in dialog boxes. You will learn about using edit controls associated with CString objects in detail beginning with the section "Passing Parameters to Dialog Boxes Using DDV and DDX Routines," later in this section.
Just a Minute: Of course, edit controls can be used in dialog box-based programs, which were discussed in Section 5. However, in this section an SDI program is used to show off some of the data exchange and validation features often used with edit controls.
2. As discussed in Section 4, "Dialog Boxes and C++ Classes," add a dialog box resource to the program. Name the dialog box IDD_TEST, and set the caption to Test Dialog. Using ClassWizard, create a dialog box class called CTestDlg for the new dialog box.
3. Add a menu choice named ID_VIEW_TEST, with a caption of Test... that brings up the Edit dialog box by adding a new menu choice on the View menu. Add a message-handling function for the new menu item using ClassWizard. The steps required to add a message-handling function that uses a CDialog-based object were discussed in Section 4. Use the source code provided in Listing 6.3 for the CMainFrame message-handling function.
4. Include the class declaration for CTestDlg in the MainFrm.cpp file by adding the following line after all the #include directives in MainFrm.cpp:
#include "testdlg.h"
6. After following these steps, make sure that the project compiles properly by pressing the Build icon on the toolbar or by selecting Build|Build EditTest.exe from the main menu. Try the menu item to make sure the IDC_TEST dialog box is displayed when View|Test... is selected.
void CMainFrame::OnViewTest()
{
CTestDlg dlg;
dlg.DoModal();
}
Figure 6.1
The dialog box used in the edit control examples.
In Figure 6.1, a static text control is located immediately to the left of the edit control. Edit controls are usually labeled with static text so a user can determine the type of input needed. Static text controls were discussed in Section 4. The ID for the new edit control is set by default to IDC_EDIT1 or a similar name. Change the ID to IDC_EDIT_TEST, leaving the other properties set to their default values.
2. Select the CDialog-derived class that manages the dialog box; in this case, CTestDlg.
3. Select the tab labeled Member Variables.
4. Select the control ID representing the control associated with the new member variable; in this case, IDC_EDIT_TEST.
5. Click the button labeled Add Variable. An Add Member Variable dialog box appears. Enter the control's name, category, and variable type, then click OK. For this example, use the values from Table 6.2.
| Control ID | Variable Name | Category | Type |
| IDC_EDIT_TEST | m_editTest | Control | CEdit |
The default value displayed in the Category control is Value. The Value category is used for some member variables later this section, when you learn about DDV and DDX routines.
void CTestDlg::OnTest()
{
CString szEdit;
CString szResult;
int nLength = m_editTest.LineLength();
m_editTest.GetWindowText( szEdit );
szResult.Format( "%s has %d chars", szEdit, nLength );
AfxMessageBox( szResult );
}
When the Test button is clicked, the text entered in the edit control is
retrieved by using the m_editTest object. Normally, you are interested
only in data contained in an edit control if OK is clicked. If the Cancel
button is clicked, the dialog box should be closed and, usually, any entered
information is simply discarded.
Time Saver: Although you can use the DDV and DDX routines in your dialog boxes directly, ClassWizard adds the code for you at the click of a button. Normally, you add the DDV and DDX routines with ClassWizard instead of trying to hand-code the necessary function calls.
Just a Minute: For example, if an edit control is used to collect an abbreviated state name, you want to limit the entered text to two characters. Using a DDV routine, it's easy to make sure that two characters have been entered.
DDX functions link member variables from the dialog box class to controls that are contained in the dialog box. DDX routines enable data to be transferred to and from the controls much easier than is otherwise possible. As discussed in Section 4, a dialog box is normally used something like this:
CMyDialog dlgMine; dlgMine.DoModal();In this example, the dialog box is created when DoModal is called, and the function does not return until the user closes the dialog box. This presents a problem if data must be passed to or from the dialog box. Because none of the controls exist until the dialog box is created, using SetWindowText, GetWindowText, or other functions to interact directly with controls contained in the dialog box is not possible. After the dialog box has been dismissed, it is too late to use those functions to collect user input.
When DDX routines are used to exchange information with a dialog box, the dialog box can be used like this:
CMyDialog dlgMine; dlgMine.m_szTest = "Hello World"; dlgMine.DoModal();The DDX routines enable you to have access to the dialog box's controls before and after the dialog box has been created. This simplifies dialog box programming because it is a much more flexible method than adding code in the InitDialog member function.
When the dialog box is initially displayed during CDialog::OnInitDialog, UpdateData(FALSE) is called to transfer data from the member variables to the dialog box's controls. Later, during CDialog::OnOk, UpdateData() is called to transfer data from the dialog box's controls to member variables.
As shown in Figure 6.2, DoDataExchange has a single parameter that controls the direction that data, in this case m_szTest, is copied.
figure 6.2
DDV and DDX routines used to handle dialog box data.
2. Select the CDialog-derived class that manages the dialog box; in this case, CTestDlg.
3. Select the Member Variables tab.
5. Click the Add Variable button. An Add Member Variable dialog box appears. Enter the control's name, category, and variable type; then click OK. For this example, use the values from Table 6.3.
| Control ID | Variable Name | Category | Type |
| IDC_EDIT_TEST | m_szTest | Value | CString |
The preceding steps are exactly like the steps used to add a control-type variable earlier in this section, except that the control type is set to Value. A member variable associated by value with an edit control can also be an int, UINT, long, DWORD, float, double, or BYTE, although it is most commonly a CString.
After closing the Add Member Variable dialog box, ClassWizard displays an edit control that you can use to specify the type of validation to be performed on the member variable. If a CString object is associated with an edit control, the maximum string length can be specified. If a numeric variable is used, the allowed range can be defined.
m_editTest.SetWindowText( "Default" );
void CMainFrame::OnViewTest()
{
CTestDlg dlg;
dlg.m_szTest = "DDX Test";
if( dlg.DoModal() == IDOK )
{
AfxMessageBox( dlg.m_szTest );
}
else
{
AfxMessageBox( "Dialog cancelled" );
}
}
Listing 6.5 sets the value of m_szTest before the dialog box is
displayed to the user. CDialog::OnInitDialog calls the CWnd::UpdateData
function, which calls UpdateData. Because UpdateData
is a virtual function, the proper version of the function is called--the
version that is part of the CDialog-derived class that handles
the dialog box.
After the dialog box closes, the CMainFrame::OnViewTest function checks the return value of DoModal. If IDOK was returned, the dialog box was closed using the OK button, and the value of m_szTest is displayed.
A You have two options. You can perform the validation yourself when accepting user input by testing for valid data before the user is allowed to close the dialog box. You can also write your own custom DDV routine. Technical Note 26 describes how to write such a routine. You can find this technical note by searching for TN026 in the Developer Studio online help.
Q Can I call UpdateData at any time? I would like to implement an Undo feature in my dialog box.
A Normally, UpdateData is called when the dialog box is initialized and when the user closes the dialog box by clicking OK. However, if you must call UpdateData at other times, it's perfectly okay.
2. What is the difference between an MLE and an SLE?
3. How are DDV and DDX routines used?
4. What member function do you call to transfer data to and from your dialog box controls?
5. What function is used to retrieve text from an edit control?
6. What function is used to set text in an edit control?
7. What property is used to hide user input in an edit control by replacing it with asterisks?
8. What keystroke is used to paste text into an edit control?
9. What keystroke is used to copy text from an edit control?
10. What keystroke is used to cut text from an edit control?
2. Change the Test project so that the edit control is used to store an integer value instead of a string.
Download Sample Programs - EditTest.zip
|
|
|
|