Thư viện tri thức trực tuyến
Kho tài liệu với 50,000+ tài liệu học thuật
© 2023 Siêu thị PDF - Kho tài liệu học thuật hàng đầu Việt Nam

Visual C++ and MFC Fundamentals programming phần 3 pptx
Nội dung xem thử
Mô tả chi tiết
Visual C++ and MFC Fundamentals Chapter 5: The Document/View Architecture
© FunctionX, Inc. 143
19. Close it using its System Close button and return to MSVC
5.3 SDI Improvements
5.3.1 SDI Improvements: The Application
To make your programming experience a little faster and efficient, the framework
provides many other features for each class used in an application.
The Application: The programs we will create in this book use classes of the Microsoft
Foundation Classes (MFC) library. MFC classes are created is various libraries called
DLLs. In order to use MFC objects in your application as opposed to non-MFC objects,
you must let the compiler know. This is done by specifying that you want to Use MFC In
A Shared DLL, as we have done so far. Additionally, if you want your windows to have a
3-D appearance, call the Enable3dControls() method. If you do not want the 3-D
appearance, call the Enable3dControlsStatic() method. The best way to deal with this is
to ask the compiler to check if you had allowed using MFC in a shared DLL or not, and
then tell the compiler which of these two functions to execute. This is done using a #ifdef
preprocessor in your InitInstance() method. Here is an example:
#include <afxwin.h>
class CSimpleFrame : public CFrameWnd
{
public:
CSimpleFrame()
{
// Create the window's frame
Create(NULL, "Windows Application");
}
};
class CSimpleApp : public CWinApp
{
public:
BOOL InitInstance();
Chapter 5: The Document/View Architecture Visual C++ and MFC Fundamentals
144 © FunctionX, Inc.
};
BOOL CSimpleApp::InitInstance()
{
#ifdef _AFXDLL
Enable3dControls( );
#else
Enable3dControlsStatic();
#endif
CSimpleFrame *Tester = new CSimpleFrame ();
m_pMainWnd = Tester;
Tester->ShowWindow(SW_SHOW);
Tester->UpdateWindow();
return TRUE;
}
CSimpleApp theApp;
To provide your application the ability to create a new document, the CWinApp class
provides the OnFileNew() method. Its syntax is:
afx_msg void OnFileNew();
To use this method, create a menu item identified as ID_FILE_NEW. You should also
create a prompt for it so the menu item can be added to the string table. This menu item is
traditionally and obviously added to the File menu. After creating this menu item, in the
message table of the application's source, invoke the CWinApp::OnFileNew() method
using the ON_COMMAND() macro. This can be done as follows:
BEGIN_MESSAGE_MAP(CExoApp, CWinApp)
ON_COMMAND(ID_FILE_NEW, CWinApp::OnFileNew)
END_MESSAGE_MAP()
CWinApp also provides an application the ability to easily open a document. This is done
using the OnFileOpen() method. In the same way, it can help with printing a document.
Here is a summary:
Menu ID CWinApp Message Map
ID_FILE_NEW ON_COMMAND(ID_FILE_NEW, CWinApp::OnFileNew)
ID_FILE_OPEN ON_COMMAND(ID_FILE_OPEN,
CWinApp::OnFileOpen)
ID_FILE_PRINT_SETUP ON_COMMAND(ID_FILE_PRINT_SETUP,
CWinApp::OnFilePrintSetup
One of the last minute assignment you may need to perform when the user is closing an
application is to check if the displayed document is "dirty", that is, if the document has
been changed since it was last accessed. To help with this, simply create a menu item
identified as ID_APP_EXIT and set a caption accordingly, such as the Exit menu we
created in the previous Practical Learning section. It is always helpful to add a prompt to
a menu item.
These command messages are implemented in the CWinApp class and can be helpful for
your application. If their behavior does not fulfill your goal, you can write your own
intended implementation of these menu items.
Visual C++ and MFC Fundamentals Chapter 5: The Document/View Architecture
© FunctionX, Inc. 145
When using an application over and over, sometimes a user may want to open the last
accessed document or at least see a list of the last documents opened on an application.
To provide this functionality, create a menu item called ID_FILE_MRU_FILE1 and set
its prompt to a string such as Recent File. This menu item is usually added to the File
menu above the Exit or quit. The actual list of recent files is stored in an INI file that
accompanies your application. To make this list available, you must call the
LoadStdProfileSettings() method of the CWinApp class in your InitInstance() method.
The syntax of this method is:
void LoadStdProfileSettings(UINT nMaxMRU = _AFX_MRU_COUNT);
By default, this allows the list to display up to four names of documents. This method
takes one argument as the number of document names to be displayed in the list. If you
do not want the default of 4, specify the nMaxMRU value to your liking.
Practical Learning: Improving the Application
1. To provide new functionality to the application, in the Resource View, change the
IDentifier of the Exit menu item to ID_APP_EXIT and set its Prompt to Quit the
application
2. Add the following menu item under File:
Caption ID Prompt
&New\tCtrl+N ID_FILE_NEW Create a new document
&Open...\tCtrl+O ID_FILE_OPEN Open an existing document
-
P&rint Setup... ID_FILE_PRINT_SETUP Change the printer and printing
options
-
Recent file ID_FILE_MRU_FILE1 Open this file
-
E&xit ID_APP_EXIT Quit the application; prompt the
save document
3. To allow the application to treat documents, change the InitInstance()
implementation as follows:
BEGIN_MESSAGE_MAP(CExerciseApp, CWinApp)
ON_COMMAND(ID_FILE_NEW, CWinApp::OnFileNew)
ON_COMMAND(ID_FILE_OPEN, CWinApp::OnFileOpen)
ON_COMMAND(ID_FILE_PRINT_SETUP, CWinApp::OnFilePrintSetup)
END_MESSAGE_MAP()
Chapter 5: The Document/View Architecture Visual C++ and MFC Fundamentals
146 © FunctionX, Inc.
BOOL CExerciseApp::InitInstance()
{
#ifdef _AFXDLL
Enable3dControls( );
#else
Enable3dControlsStatic();
#endif
LoadStdProfileSettings(6);
CSingleDocTemplate* pDocTemplate;
pDocTemplate = new CSingleDocTemplate(
IDR_MAINFRAME,
RUNTIME_CLASS(CExerciseDoc),
RUNTIME_CLASS(CMainFrame),
RUNTIME_CLASS(CExerciseView));
AddDocTemplate(pDocTemplate);
CCommandLineInfo cmdInfo;
// Dispatch commands specified on the command line
if (!ProcessShellCommand(cmdInfo))
return FALSE;
m_pMainWnd->ShowWindow(m_nCmdShow);
m_pMainWnd->UpdateWindow();
return TRUE;
}
4. Test the application and click the various menu items
5.3.2 SDI Improvements: The Document
The document is actually the object that holds the contents of a file. Based on this role, it
is its responsibility to validate the creation of a new file or to store a file that is being
saved. To perform these tasks and others, the CDocument class provides various methods
you can conveniently add to your application or add and customize their behavior.
Earlier, we saw that, to give the user a convenient means of creating a new document,
you can add an ID_FILE_NEW menu identifier and connect it to your application class in
the InitInstance() method. Clicking this menu item only allows to initiate the action, the
document that is the base of file contents must be aware and validate this action. When a
user decides to create a new document or when the application opens and is about to
create a new document, you may want to make sure that there is no existing document or
you may want to delete the existing one. To take care of this, the CDocument class
provides the virtual OnNewDocument() method. Its syntax is:
virtual BOOL OnNewDocument();
When a new file is about to be created, this method is called to initiate it. If everything
goes fine and the file is created, the OnNewDocument() method returns TRUE. If the file
cannot be initialized, this method returns FALSE or 0. This method, which really behaves
like an event, does not create a new file. It is launched when a new file is going to be
created and allows you to make it happen or to prevent the creation of a new file.
Visual C++ and MFC Fundamentals Chapter 5: The Document/View Architecture
© FunctionX, Inc. 147
When a new file has been created, it displays as empty. Such a document is referred to as
"clean".
We also saw earlier that, to help the user open an existing document, you can create a
menu item identified as ID_FILE_OPEN and associate it with the
CWinApp::OnFileOpen() method in your InitInstance() method. This time also, the menu
item only provides a convenient way to perform the action. It makes the document
available to the application and not to the document. Once a user has initiated the action
of opening an existing file, you may want to check that the document not only exists but
also can be opened and make its contents available to the user. This job can be handled
by the OnOpenDocument() virtual method of the CDocument class. Its syntax is:
virtual BOOL OnOpenDocument(LPCTSTR lpszPathName);
This method usually results from the user clicking File -> Open... on the main menu,
communicating a desire to open a file. When this action is initiated, the
OnOpenDocument() method retrieves the path of the file as the lpszPathName argument.
If the path is valid, that is, if the file exists, you can then check it or perform a last minute
task before the file is opened. For example you can use this method to decide how the
contents of the file will be displayed or dealt with by the document. You can also use to
prevent the user from opening any file or to prevent the user from opening any file at all.
You can also use this method to allow the user to open a type of file that your
CDocument-derived class would not expect.
If the user has opened an existing file but has not (yet) changed anything in the
document, the file is also called "clean". As we will learn eventually, some files can be
changed and some do not allow modification. If a document allows the user to change it,
he or she can manipulate it as necessary, including adding, deleting, or moving items.
Once a user has changed anything on the document, the file is referred to as "dirty". You
may want to keep track of such change(s) so you would know eventually if the document
needs to be saved. To help you with this, the CDocument class provides the
SetModifiedFlag() method. Its syntax is:
void SetModifiedFlag(BOOL bModified = TRUE);
To mark a document as clean or dirty, call the SetModifiedFlag() method. If you pass the
bModified argument as TRUE, the document has been changed. Since the TRUE
constant is its default value, you can also call the method simply as SetModifiedFlag().
To specify that the document is clean, pass the argument as FALSE. You can call this
method whenever you judge necessary. For example, if the user saves the document
while working on it but makes another change, you can mark it clean when it has just
been saved and mark it dirty if the user changes anything again. At any time, you can
check whether the document is dirty or clean using the CDocument::IsModified()
method. Its syntax is:
BOOL IsModified();
This method simply checks the document to find out if it has been modified since the last
time it was accessed. If the document has been modified, this method would return
TRUE. If the document is clean, it returns FALSE.
Another action the user can perform on a document is to send it electronically to an email
recipient. To allow the user to send the current document as an email attachment, first an
email client (such as MS Outlook) must be installed on the user's computer. Therefore,
add a menu item IDentified as ID_FILE_SEND_MAIL. Then, in the message table of
your document implementation, add the following two macros:
Chapter 5: The Document/View Architecture Visual C++ and MFC Fundamentals
148 © FunctionX, Inc.
BEGIN_MESSAGE_MAP(CTestDoc, CDocument)
ON_COMMAND(ID_FILE_SEND_MAIL, OnFileSendMail)
ON_UPDATE_COMMAND_UI(ID_FILE_SEND_MAIL, OnUpdateFileSendMail)
END_MESSAGE_MAP
Once a user has finished using a document, he or she would need to close it, which is
done by either clicking the System Close button or using the main menu (File -> Exit). If
the user clicks the System Close button , the application would need to close the frame.
At this time, the document would call the OnCloseDocument() method. Its syntax is:
virtual void OnCloseDocument();
You can use this method (which really behave as an event) to decide what to do before a
frame is closed.
When the user decides to close an application, the document class checks the file to know
whether the file is "dirty". If the file is dirty, you may want to ask the user to save or not
save the document. As we saw earlier with the ID_APP_EXIT pre-configured menu, the
framework can check this setting for you. Also, while using a file, the user may want to
save it. If the user is working on a document that was opened from a drive, the document
may be saved immediately behind the scenes. If the user is working on a brand new
document and decides to save it, you may want to check first if this is possible and what
needs to be done in order to save the document.
To help the user save a document, you can create a menu item. Using the
Document/View architecture, add a menu item with the identifier ID_FILE_SAVE in the
IDR_MAINFRAME common resource name. It is that simple. This menu is usually
positioned under File with a caption of &Save.
If the user wants to save a document with a different name and/or a different location,
which is usually done by clicking File -> Save As... from the main menu, create a menu
item with the ID_FILE_SAVE_AS identifier. This menu item is usually placed under
Save in the File main menu. If the user is working on a new document (that has not been
saved previously), or if the user working on a document that is marked as Read-Only, or
if the user decides to close the application after working on a new document, and if the
user decides to save the document, the action would initiate the File -> Save As action.
When the user has decided to save a document, if the document is dirty, a message box
would display to the user for a decision. If the user decides to save the document, the
CDocument class provides the OnSaveDocument() method to validate the action. The
syntax of this method is:
virtual BOOL OnSaveDocument(LPCTSTR lpszPathName);
To save a document, the user must specify where the document would reside. This is
communicated as the lpszPathName argument). In reality, as its name suggests, this
method is not used to save a document. It allows you to validate the action or desire to
save a document. For example, if the user clicks File -> Save on the main menu or if the
user is attempting to close a dirty document, you can use this method to check what is
going or to deny saving the file.
Serialization is the ability to store data on a drive. Therefore, to actually save a file, the
CObject class provides the Serialize() method to its children. To store data of the file, its
information is held by a class called CArchive. When saving a file, a CArchive object is
passed to the Serialize method as reference, which modifies its value.