?? ch08.htm
字號:
//{{AFX_MSG(COptionsDialog)
// NOTE: The ClassWizard will add member functions here
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
</PRE>
<PRE>};
</PRE>
<P>There are an awful lot of comments here to help ClassWizard find its way around
in the file when the time comes to add more functionality, but there is only one
member variable, m_string; one constructor; and one member function, DoDataExchange(),
which gets the control value into the member variable, or vice versa. The source
file isn't much longer; it's shown in Listing 8.6.</P>
<P>
<H4>Listing 8.6  OPTIONSDIALOG.CPP--Implementation File for COptionsDialog</H4>
<PRE>// OptionsDialog.cpp : implementation file
//
#include "stdafx.h"
#include "ShowString.h"
#include "OptionsDialog.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// COptionsDialog dialog
COptionsDialog::COptionsDialog(CWnd* pParent /*=NULL*/)
: CDialog(COptionsDialog::IDD, pParent)
{
//{{AFX_DATA_INIT(COptionsDialog)
m_string = _T("");
//}}AFX_DATA_INIT
}
void COptionsDialog::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(COptionsDialog)
DDX_Text(pDX, IDC_OPTIONS_STRING, m_string);
//}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(COptionsDialog, CDialog)
//{{AFX_MSG_MAP(COptionsDialog)
// NOTE: The ClassWizard will add message map macros here
//}}AFX_MSG_MAP
</PRE>
<PRE>END_MESSAGE_MAP()
</PRE>
<P>The constructor sets the string to an empty string; this code is surrounded by
special ClassWizard comments that enable it to add other variables later. The DoDataExchange()
function calls DDX_Text() to transfer data from the control with the resource ID
IDC_OPTIONS_STRING to the member variable m_string, or vice versa. This code, too,
is surrounded by ClassWizard comments. Finally, there is an empty message map because
COptionsDialog doesn't catch any messages.</P>
<P>
<H3><A NAME="Heading10"></A>Catching the Message</H3>
<P>The next step in building ShowString is to catch the command message sent when
the user chooses Tools, Options. There are seven classes in ShowString: CAboutDlg,
CChildFrame, CMainFrame, COptionsDialog, CShowStringApp, CShowStringDoc, and CShowStringView.
Which one should catch the command? The string and the options will be saved in the
document and displayed in the view, so one of those two classes should handle the
changing of the string. The document owns the private variable and will not let the
view change the string unless you implement a public function to set the string.
So, it makes the most sense to have the document catch the message.</P>
<BLOCKQUOTE>
<P>
<HR>
<strong>NOTE:</strong> Often the hardest part of catching these messages is deciding which
class should catch them. The decision between View and Document is frequently a very
difficult one. If the message handler will need access to a private member of either
class, that's the class to catch the message. 
<HR>
</BLOCKQUOTE>
<P>To catch the message, follow these steps:</P>
<DL>
<DT></DT>
<DD><B>1. </B>Open ClassWizard (if it isn't already open).
<P>
<DT></DT>
<DD><B>2. </B>Click the Message Maps tab.
<P>
<DT></DT>
<DD><B>3. </B>Select CShowStringDoc from the Class Name drop-down list box.
<P>
<DT></DT>
<DD><B>4. </B>Select ID_TOOLS_OPTIONS from the Object IDs list box on the left, and
select COMMAND from the Messages list box on the right.
<P>
<DT></DT>
<DD><B>5. </B>Click Add Function to add a function to handle this command.
<P>
<DT></DT>
<DD><B>6. </B>The Add Member Function dialog box, shown in Figure 8.13, appears,
giving you an op-portunity to change the function name from the usual one. Do not
change it; just click OK.
<P>
</DL>
<P><A HREF="javascript:popUp('08uvc13.gif')"><B>FIG. 8.13</B></A><B> </B><I>ClassWizard
suggests a good name for the message-catching function.</I></P>
<BLOCKQUOTE>
<P>
<HR>
<strong>TIP:</strong> You should almost never change the names that ClassWizard suggests
for message catchers. If you find that you have to (perhaps because the suggested
name is too long or conflicts with another function name in the same object), be
sure to choose a name that starts with <I>On</I>. Otherwise the next developer to
work on your project is going to have a very hard time finding the message handlers.
<HR>
</BLOCKQUOTE>
<P>Click Edit Code to close ClassWizard and edit the newly added function. What happened
to CShowStringDoc when you arranged for the ID_TOOLS_OPTIONS message to be caught?
The new message map in the header file is shown in Listing 8.7.</P>
<P>
<H4>Listing 8.7  SHOWSTRINGDOC.H--Message Map for CShowStringDoc</H4>
<PRE>// Generated message map functions
protected:
//{{AFX_MSG(CShowStringDoc)
afx_msg void OnToolsOptions();
//}}AFX_MSG
</PRE>
<PRE> DECLARE_MESSAGE_MAP()
</PRE>
<P>This is just declaring the function. In the source file, ClassWizard changed the
message maps shown in Listing 8.8.</P>
<P>
<H4>Listing 8.8  SHOWSTRINGDOC.CPP--Message Map for CShowStringDoc</H4>
<PRE>BEGIN_MESSAGE_MAP(CShowStringDoc, CDocument)
//{{AFX_MSG_MAP(CShowStringDoc)
ON_COMMAND(ID_TOOLS_OPTIONS, OnToolsOptions)
//}}AFX_MSG_MAP
</PRE>
<PRE>END_MESSAGE_MAP()
</PRE>
<P>This arranges for OnToolsOptions() to be called when the command ID_TOOLS_OPTIONS
is sent. ClassWizard also added a skeleton for OnToolsOptions():</P>
<P>
<PRE>void CShowStringDoc::OnToolsOptions()
{
// TODO: Add your command handler code here
}
</PRE>
<H2><A NAME="Heading11"></A>Making the Dialog Box Work</H2>
<P>OnToolsOptions() should initialize and display the dialog box and then do something
with the value that the user provided. (This process was first discussed in Chapter
2. You have already connected the edit box to a member variable, m_string, of the
dialog box class. You initialize this member variable before displaying the dialog
box and use it afterwards.</P>
<P>OnToolsOptions(), shown in Listing 8.9, displays the dialog box. Add this code
to the empty function ClassWizard generated for you when you arranged to catch the
message.</P>
<P>
<H4>Listing 8.9  SHOWSTRINGDOC.CPP--OnToolsOptions()</H4>
<PRE>void CShowStringDoc::OnToolsOptions()
{
COptionsDialog dlg;
dlg.m_string = string;
if (dlg.DoModal() == IDOK)
{
string = dlg.m_string;
SetModifiedFlag();
UpdateAllViews(NULL);
}
</PRE>
<PRE>}
</PRE>
<P>This code fills the member variable of the dialog box with the document's member
variable (ClassWizard added m_string as a public member variable of COptionsDialog,
so the document can change it) and then brings up the dialog box by calling DoModal().
If the user clicks OK, the member variable of the document changes, the modified
flag is set (so that the user is prompted to save the document on exit), and the
view is asked to redraw itself with a call to UpdateAllViews(). For this to compile,
of course, the compiler must know what a COptionsDialog is, so add this line at the
beginning of ShowStringDoc.cpp:</P>
<P>
<PRE>#include "OptionsDialog.h"
</PRE>
<P>At this point, you can build the application and run it. Choose Tools, Options
and change the string. Click OK and you see the new string in the view. Exit the
application; you are asked whether to save the file. Save it, restart the application,
and open the file again. The default "Hello, world!" document remains open,
and the changed document is open with a different string. The application works,
as you can see in Figure 8.14 (the windows are resized to let them both fit in the
figure).</P>
<P><A HREF="javascript:popUp('08uvc14.gif')"><B>FIG. 8.14</B></A><B> </B><I>ShowString
can change the string, save it to a file, and reload it.</I></P>
<H2><I></I></H2>
<H2><A NAME="Heading12"></A>Adding Appearance Options to the Options Dialog Box</H2>
<P>ShowString doesn't have much to do, just demonstrate menus and dialog boxes. However,
the only dialog box control that ShowString uses is an edit box. In this section,
you add a set of radio buttons and check boxes to change the way the string is drawn
in the view.</P>
<P>
<H3><A NAME="Heading13"></A>Changing the Options Dialog Box</H3>
<P>It is quite simple to incorporate a full-fledged Font dialog box into an application,
but the example in this section is going to do something much simpler. A group of
radio buttons will give the user a choice of several colors. One check box will enable
the user to specify that the text should be centered horizontally, and another that
the text be centered vertically. Because these are check boxes, the text can be either,
neither, or both.</P>
<P>Open the IDD_OPTIONS dialog box by double-clicking it in the ResourceView window,
and then add the radio buttons by following these steps:</P>
<DL>
<DT></DT>
<DD><B>1. </B>Stretch the dialog box taller to make room for the new controls.
<P>
<DT></DT>
<DD><B>2. </B>Click the radio button in the Controls floating toolbar, and then click
the Options dialog box to drop the control.
<P>
<DT></DT>
<DD><B>3. </B>Choose View, Properties and then pin the Properties dialog box in place.
<P>
<DT></DT>
<DD><B>4. </B>Change the resource ID of the first radio button to <B>IDC_OPTIONS_BLACK</B>,
and change the caption to <B>&Black</B>.
<P>
<DT></DT>
<DD><B>5. </B>Select the Group box to indicate that this is the first of a group
of radio buttons.
<P>
<DT></DT>
<DD><B>6. </B>Add another radio button with resource ID<B> IDC_OPTIONS_RED</B> and
<B>&Red</B> as the caption. Do not select the Group box because the Red radio
button doesn't start a new group but is part of the group that started with the Black
radio button.
<P>
<DT></DT>
<DD><B>7. </B>Add a third radio button with resource ID <B>IDC_OPTIONS_GREEN</B>
and <B>&Green</B> as the caption. Again, do not select Group.
<P>
<DT></DT>
<DD><B>8. </B>Drag the three radio buttons into a horizontal arrangement, and select
all three by clicking on one and then holding Ctrl while clicking the other two.
<P>
<DT></DT>
<DD><B>9. </B>Choose Layout, Align Controls, Bottom (to even them up).
<P>
<DT></DT>
<DD><B>10. </B>Choose Layout, Space Evenly, Across to space the controls across the
dialog box.
<P>
</DL>
<P>Next, add the check boxes by following these steps:</P>
<DL>
<DT></DT>
<DD><B>1. </B>Click the check box in the Controls floating toolbar and then click
the Options dialog box, dropping a check box onto it.
<P>
<DT></DT>
<DD><B>2. </B>Change the resource ID of this check box to <B>IDC_OPTIONS_HORIZCENTER</B>
and the caption to <B>Center &Horizontally</B>.
<P>
<DT></DT>
<DD><B>3. </B>Select the Group box to indicate the start of a new group after the
radio buttons.
<P>
<DT></DT>
<DD><B>4. </B>Drop another check box onto the dialog box as in step 1 and give it
the resource ID <B>IDC_OPTIONS_VERTCENTER</B> and the caption <B>Center &Vertically</B>.
<P>
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -