?? ch02.htm
字號:
<P>A member variable in the new dialog box class can be connected to a control's
value or to the control. This sample demonstrates both kinds of connection. For IDC_CHECK1,
fill in the variable name as <B>m_check</B>, and make sure that the Category drop-down
box has Value selected. If you open the Variable Type drop-down box, you will see
that the only possible choice is BOOL. Because a check box can be either selected
or not selected, it can be connected only to a BOOL variable, which holds the value
TRUE or FALSE. Click OK to complete the connection.</P>
<P><A HREF="javascript:popUp('02uvc08.gif')"><B>FIG. 2.8</B></A><B> </B><I>You choose
the name for the member variable associated with each control.</I></P>
<P>Here are the data types that go with each control type:</P>
<P>
<UL>
<LI><I>Edit box.</I> Usually a string but also can be other data types, including
int, float, and long
<P>
<LI><I>Check box.</I> int
<P>
<LI><I>Radio button.</I> int
<P>
<LI><I>List box.</I> String
<P>
<LI><I>Combo box.</I> String
<P>
<LI><I>Scrollbar.</I> int
</UL>
<P>Connect IDC_EDIT1 in the same way, to a member variable called m_edit of type
CString as a Value. Connect IDC_LIST1 as a Control to a member variable called m_listbox
of type CListBox. Connect IDC_RADIO_1, the first of the group of radio buttons, as
a Value to an int member variable called m_radio.</P>
<P>After you click OK to add the variable, ClassWizard offers, for some kinds of
variables, the capability to validate the user's data entry. For example, when an
edit control is selected, a field under the variables list allows you to set the
maximum number of characters the user can enter into the edit box (see Figure 2.9).
Set it to 10 for m_edit. If the edit box is connected to a number (int or float),
this area of ClassWizard is used to specify minimum or maximum values for the number
entered by the user. The error messages asking the user to try again are generated
automatically by MFC with no work on your part.</P>
<P><A HREF="javascript:popUp('02uvc09.gif')"><B>FIG. 2.9</B></A><B> </B><I>Enter
a number in the Maximum Characters field to limit the length of a user's entry.</I></P>
<P><I></I>
<H2><A NAME="Heading6"></A>Using the Dialog Box Class</H2>
<P>Now that you have your dialog box resource built and your dialog box class written,
you can create objects of that class within your program and display the associated
dialog box element. The first step is to decide what will cause the dialog box to
display. Typically, it is a menu choice, but because adding menu items and connecting
them to code are not covered until Chapter 8, "Building a Complete Application:
ShowString," you can simply have the dialog box display when the application
starts running. To display the dialog box, you call the DoModal() member function
of the dialog box class.</P>
<BLOCKQUOTE>
<P>
<HR>
<B>Modeless Dialog Boxes</B><BR>
</P>
<P>Most of the dialog boxes you will code will be modal dialog boxes. A modal dialog
box is on top of all the other windows in the application: The user must deal with
the dialog box and then close it before going on to other work. An example of this
is the dialog box that comes up when the user chooses File, Open in any Windows application.<BR>
</P>
<P>A modeless dialog box enables the user to click the underlying application and
do some other work and then return to the dialog box. An example of this is the dialog
box that comes up when the user chooses Edit, Find in many Windows applications.<BR>
</P>
<P>Displaying a modeless dialog box is more difficult than displaying a modal one.
The dialog box object, the instance of the dialog box class, must be managed carefully.
Typically, it is created with new and destroyed with delete when the user closes
the dialog box with Cancel or OK. You have to override a number of functions within
the dialog box class. In short, you should be familiar and comfortable with modal
dialog boxes before you attempt to use a modeless dialog box. When you're ready,
look at the Visual C++ sample called MODELESS that comes with Developer Studio. The
fastest way to open this sample is by searching for MODELESS in InfoViewer. Searching
in InfoViewer is covered in Appendix C, "The Visual Studio User Interface, Menus,
and Toolbars."
<HR>
</BLOCKQUOTE>
<H3><A NAME="Heading7"></A>Arranging to Display the Dialog Box</H3>
<P>Select the ClassView in the project workspace pane, expand the SDI Classes item,
and then expand CSdiApp. Double-click the InitInstance() member function. This function
is called whenever the application starts. Scroll to the top of the file, and after
the other #include statements, add this directive:</P>
<P>
<PRE>#include "sdidialog.h"
</PRE>
<P>This ensures that the compiler knows what a CSdiDialog class is when it compiles
this file.</P>
<P>Double-click InitInstance() in the ClassView again to bring the cursor to the
beginning of the function. Scroll down to the end of the function, and just before
the return at the end of the function, add the lines in Listing 2.1.</P>
<P>
<H4>Listing 2.1  SDI.CPP--Lines to Add at the End of CSdiApp::InitInstance()</H4>
<PRE> CSdiDialog dlg;
dlg.m_check = TRUE;
dlg.m_edit = "hi there";
CString msg;
if (dlg.DoModal() == IDOK)
{
msg = "You clicked OK. ";
}
else
{
msg = "You cancelled. ";
}
msg += "Edit box is: ";
msg += dlg.m_edit;
</PRE>
<PRE> AfxMessageBox (msg);
</PRE>
<BLOCKQUOTE>
<P>
<HR>
<B>Entering Code</B><BR>
</P>
<P>As you enter code into this file, you may want to take advantage of a feature
that makes its debut in this version of Visual C++: Autocompletion. Covered in more
detail in Appendix C, Autocompletion saves you the trouble of remembering all the
member variables and functions of a class. If you type dlg. and then pause, a window
will appear, listing all the member variables and functions of the class CSdiDialog,
including those it inherited from its base class. If you start to type the variable
you want--for example, typing m_--the list will scroll to variables starting with
m_. Use the arrow keys to select the one you want, and press Space to select it and
continue typing code. You are sure to find this feature a great time saver. If the
occasional pause as you type bothers you, Autocompletion can be turned off by choosing
Tools, Options and clicking the Editor tab. Deselect the parts of Autocompletion
you no longer want.
<HR>
</BLOCKQUOTE>
<P>This code first creates an instance of the dialog box class. It sets the check
box and edit box to simple default values. (The list box and radio buttons are a
little more complex and are added later in this chapter, in "Using a List Box
Control" and "Using Radio Buttons.") The dialog box displays onscreen
by calling its DoModal() function, which returns a number represented by IDOK if
the user clicks OK and IDCANCEL if the user clicks Cancel. The code then builds a
message and displays it with the AfxMessageBox function.</P>
<BLOCKQUOTE>
<P>
<HR>
<strong>NOTE:</strong> The CString class has a number of useful member functions and operator
overloads. As you see here, the += operator tacks characters onto the end of a string.
For more about the CString class, consult Appendix F, "Useful Classes."
<HR>
</BLOCKQUOTE>
<P>Build the project by choosing Build, Build or by clicking the Build button on
the Build toolbar. Run the application by choosing Build, Execute or by clicking
the Execute Program button on the Build toolbar. You will see that the dialog box
displays with the default values you just coded, as shown in Figure 2.10. Change
them, and click OK. You should get a message box telling you what you did, such as
the one in Figure 2.11. Now the program sits there, ready to go, but because there
is no more for it to do, you can close it by choosing File, Exit or by clicking the
- in the top-right corner.</P>
<P><A HREF="javascript:popUp('02uvc10.gif')"><B>FIG. 2.10</B></A><B> </B><I>Your
application displays the dialog box when it first runs.</I></P>
<P><A HREF="javascript:popUp('02uvc11.gif')"><B>FIG. 2.11</B></A><B> </B><I>After
you click OK, the application echoes the contents of the edit control.</I></P>
<P>Run it again, change the contents of the edit box, and this time click Cancel
on the dialog box. Notice in Figure 2.12 that the edit box is reported as still hi
there. This is because MFC does not copy the control values into the member variables
when the user clicks Cancel. Again, just close the application after the dialog box
is gone.</P>
<P><A HREF="javascript:popUp('02uvc12.gif')"><B>FIG. 2.12</B></A><B> </B><I>When
you click Cancel, the application ignores any changes you made.</I></P>
<P>Be sure to try entering more characters into the edit box than the 10 you specified
with ClassWizard. You will find you cannot type more than 10 characters--the system
just beeps at you. If you try to paste in something longer than 10 characters, only
the first 10 characters appear in the edit box.</P>
<P>
<H3><A NAME="Heading8"></A>Behind the Scenes</H3>
<P>You may be wondering what's going on here. When you click OK on the dialog box,
MFC arranges for a function called OnOK() to be called. This function is inherited
from CDialog, the base class for CSdiDialog. Among other things, it calls a function
called DoDataExchange(), which ClassWizard wrote for you. Here's how it looks at
the moment:</P>
<P>
<PRE>void CSdiDialog::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CSdiDialog)
DDX_Control(pDX, IDC_LIST1, m_listbox);
DDX_Check(pDX, IDC_CHECK1, m_check);
DDX_Text(pDX, IDC_EDIT1, m_edit);
DDV_MaxChars(pDX, m_edit, 10);
DDX_Radio(pDX, IDC_RADIO1, m_radio);
//}}AFX_DATA_MAP
}
</PRE>
<P>The functions with names that start with DDX all perform data exchange: Their
second parameter is the resource ID of a control, and the third parameter is a member
variable in this class. This is the way that ClassWizard connected the controls to
member variables--by generating this code for you. Remember that ClassWizard also
added these variables to the dialog box class by generating code in the header file
that declares them.</P>
<P>There are 34 functions whose names begin with DDX: one for each type of data that
might be exchanged between a dialog box and a class. Each has the type in its name.
For example, DDX_Check is used to connect a check box to a BOOL member variable.
DDX_Text is used to connect an edit box to a CString member variable. ClassWizard
chooses the right function name when you make the connection.</P>
<BLOCKQUOTE>
<P>
<HR>
<strong>NOTE:</strong> Some DDX functions are not generated by ClassWizard. For example,
when you connect a list box as a Value, your only choice for type is CString. Choosing
that causes ClassWizard to generate a call to DDX_LBString(), which connects the
selected string in the list box to a CString member variable. There are cases when
the integer index into the list box might be more useful, and there is a DDX_LBIndex()
function that performs that exchange. You can add code to DoDataExchange(), outside
the special ClassWizard comments, to make this connection. If you do so, remember
to add the member variable to the class yourself. You can find the full list of DDX
functions in the online documentation. n
<HR>
</BLOCKQUOTE>
<P>Functions with names that start with DDV perform data validation. ClassWizard
adds a call to DDV_MaxChars right after the call to DDX_Text that filled m_edit with
the contents of IDC_EDIT1. The second parameter of the call is the member variable
name, and the third is the limit: how many characters can be in the string. If a
user ever managed to get extra characters into a length-validated string, the DDV_MaxChars()
function contains code that puts up a warning box and gets the user to try again.
You can just set the limit and count on its being enforced.</P>
<P>
<H3><A NAME="Heading9"></A>Using a List Box Control</H3>
<P>Dealing with the list box is more difficult because only while the dialog box
is onscreen is the list box control a real window. You cannot call a member function
of the list box control class unless the dialog box is onscreen. (This is true of
any control that you access as a control rather than as a value.) This means that
you must initialize the list box (fill it with strings) and use it (determine which
string is selected) in functions that are called by MFC while the dialog box is onscreen.</P>
<P>When it is time to initialize the dialog box, just before it displays onscreen,
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -