Training
Certifications
Books
Special Offers
Community




 
Microsoft® Mastering: MFC Development Using Microsoft Visual C++® 6.0
Author Microsoft Corporation
Pages 624
Disk 1 Companion CD(s)
Level Intermediate
Published 02/23/2000
ISBN 9780735609259
ISBN-10 0-7356-0925-X
Price(USD) $49.99
To see this book's discounted price, select a reseller below.
 

More Information

About the Book
Table of Contents
Sample Chapter
Index
Related Series
Related Books
About the Author

Support: Book & CD

Rate this book
Barnes Noble Amazon Quantum Books

 


Chapter 4: Implementing View Classes (continued)


Creating an Explorer-Style Application

Many Windows system applications use the Explorer user interface, in which the client area is split vertically. The left side of the client area shows an overview pane, which makes navigation and browsing possible, while the right side of the client area shows details about the selection in the left pane.

You can create an Explorer-Style application by using MFC AppWizard and selecting the Windows Explorer option in Step 5.

The following illustration shows the MFC AppWizard - Step 5 dialog box.

Figure 4-15.

Figure 4-15.

MFC AppWizard generates code so that each frame window that the application creates is split vertically using the CSplitterWnd object. The left pane always contains a tree view control. The right pane contains a list view control by default. You can modify the view type of the right pane to customize the display detail of the selected item in the left pane.

The following illustration shows the MFC AppWizard - Step 6 dialog box with a list of view types.

Figure 4-16.

Figure 4-16.

If you use the MFC AppWizard default list view in the right pane, the wizard creates additional menu choices and toolbar buttons to switch the view’s style among report mode, small icon mode, and list mode.

Coordinating Multiple Interrelated Views

If your application uses two or more views of different types, you need to ensure that the display of data in the views is always synchronized.

There are two methods for coordinating the data in the views. The first method uses the UpdateAllViews function to update the views, whereas the second method updates the views without using this function. Which method you use depends on the requirements of your application.

Coordinating Data Using the UpdateAllViews Function

Using UpdateAllViews takes advantage of the document/view architecture as provided by MFC. Suppose that the user does something in a list view that causes a change in a form view. The list view packages the information it needs to pass to the form in a class derived from CObject. The list then calls UpdateAllViews, passing three parameters: a pointer to itself, NULL (0), and a pointer to the object where information is packaged.

The document object then calls the form’s OnUpdate function, and passes the second and third arguments of UpdateAllViews to the form. The document does not call the list’s OnUpdate function, because the list specified a pointer to itself in the first argument to UpdateAllViews.

Coordinating Data Without Using the UpdateAllViews Function

The second method requires you to manually control the process of coordinating the data. With this method, the document stores pointers to the two view objects. Each view initializes this pointer to itself in its OnCreate function. Each view also has as many public functions, with as many parameters as are needed, to respond to changes requested by the other view. When, for instance, the list needs to cause the form to change its display, the list obtains the pointer to the form from the document and calls a specific function in the form, passing arguments as required. Using this method may be much easier than packaging information in a class and passing that class by using the UpdateAllViews function as described in the first method.

Lab 4.2: Adding Open File Dialogs and a Rich Edit View

In this lab, you will use a Common Open File dialog box and a rich edit view in an application.

To see the demonstration "Lab 4.2 Demonstration," see the accompanying CD-ROM.

Estimated time to complete this lab: 60 minutes

To complete the exercises in this lab, you must have the required software. For detailed information about the labs and setup for the labs, see "Labs" in "About This Course."

The code that forms the starting point for this lab is located in the folder <install folder>\Labs\Ch04\Lab4.2.

The solution code for this lab is located in the folder <install folder>\Labs\Ch04\Lab4.2.

Objectives

After completing this lab, you will be able to:

  • Modify the base classes of views and documents.
  • Use a Common Dialogs Library Open dialog box.
  • Use a rich edit view in an application.
  • Process a dropped file on the edit control.

Prerequisites

There are no prerequisites for this lab.

Exercises

The following exercises provide practice working with the concepts and techniques covered in this chapter:

  • Exercise 1: Modifying the Base Classes of Views and Documents
  • In this exercise, you will use the text editors of Visual C++ to modify the Document and View classes to inherit from their respective rich edit classes.

  • Exercise 2: Handling the Common Open File Dialog Box
  • In this exercise, you will add a handler for the Open File dialog box in the ShowDiff application.

  • Exercise 3: Using the Rich Edit Views in the Application
  • In this exercise, you will use the rich edit views to display the file that the user chooses in the File dialog box. You will create a function that serializes the text data into the rich edit views, and drive that function from the OnFileOpen handler.

  • Exercise 4: Managing Drag-and-Drop Editing
  • In this exercise, you will modify the behavior of CRichEdit so that it will open a file that is dragged from Windows Explorer to the window pane of the running application.

Exercise 1: Modifying the Base Classes of Views and Documents

The code that forms the starting point for this exercise is in <install folder>\Labs\Ch04\Lab4.2\Ex01.

In this exercise, you will use the text editors of Visual C++ to modify the Document and View classes to inherit from their respective rich edit classes.

Replace CDocument with CRichEditDoc

  1. Open the file DiffDoc.cpp.
  2. Replace all instances of CDocument with CRichEditDoc.
  3. Save DiffDoc.cpp.
  4. Repeat this procedure with the file DiffDoc.h.

Replace CView with CRichEditView

  1. Open DiffView.cpp.
  2. Replace all instances of CView with CRichEditView.
  3. Save DiffView.cpp.
  4. Repeat this procedure with DiffView.h.

Add the #includes that support rich edit classes to the file Stdafx.h

  1. Open Stdafx.h.
  2. The CRichEditDoc class inherits from COleDocument, COleLinkingDoc, and COleServerDoc. The definitions for these classes and their support functions need to be included before the rich edit definitions. To the end of Stdafx.h, add:
  3. #include <afxole.h>
    #include <afxodlgs.h>

  4. The definitions for rich edit control are in the file Afxrich.h. To the end of Stdafx.h, after the file Afxodlgs.h, add:
  5. #include <afxrich.h>

  6. Save Stdafx.h.

Add the support for CRichEditCntrItem

Derived classes from CRichEditDoc need to provide a pointer to a control item (the class that contains the rich edit control itself). This simple function is implemented in DiffDoc.h.

  1. Open DiffDoc.h.
  2. Add this code to the overrides section (after the //}AFX_VIRTUAL tag):
  3. virtual CRichEditCntrItem* CreateClientItem(REOBJECT* preo) const;

  4. Save DiffDoc.h.
  5. Open DiffDoc.cpp.
  6. Add this code right after the destructor (CDiffDoc::~CDiffDoc):
  7. CRichEditCntrItem* CDiffDoc::CreateClientItem(REOBJECT* preo) const
    {
    return new CRichEditCntrItem();
    }

  8. Save DiffDoc.cpp and build the project.

The solution code for this exercise is located in the folder <install folder>\Labs\Ch04\Lab4.2\Ex01\Solution.

Exercise 2: Handling the Common Open File Dialog Box

Continue with the files you created in Exercise 1 or, if you do not have a starting point for this exercise, the code that forms the basis for this exercise is in <install folder>\Labs\Ch04\Lab4.2\Ex02.

In this exercise, you will add a handler for the Open File dialog box to the ShowDiff application.

Add an OnFileOpen handler for CDiffDoc

  1. On the View menu, click ClassWizard or press ctrl+w. Click the Message Maps tab.
  2. Select the CDiffDoc class, the ID_FILE_OPEN menu object ID, and the COMMAND message, and click Add Function, as shown in this figure.
  3. Figure 4-17.

    Figure 4-17.

  4. Accept the default OnFileOpen function name in the Add Member Function dialog box, and click OK.
  5. In ClassWizard, click OK to create the function.

Declare protected file name members

  • Right-click CDiffDoc in ClassView and add these two protected variables:
  • CString m_File1
    CString m_File2

Complete the OnFileOpen handler

  1. In the OnFileOpen handler of the file DiffDoc.cpp, define the filter for the File dialog box. In this example, you will filter for C++ source files (*.cpp and *.h) and for all files:
  2. static char BASED_CODE szFilter[] = 
    "All Files (*.*)|*.*|C++ Files (*.cpp, *.h)"\
    "|*.cpp;*.h||";

  3. Construct the File dialog box as an open dialog box with this filter:
  4. CFileDialog dlg(TRUE,NULL,NULL,NULL,szFilter);

  5. Show the File dialog box as a modal dialog box, and check to see whether OK was clicked.
  6. When the user clicks OK, assign the path to m_File1 and m_File2.
  7. Save DiffDoc.cpp.

The following sample code shows an example of how your code should look. To copy this code for use in your own projects, see "Lab 4.2.2 OnFileOpen" on the accompanying CD-ROM.

void CDiffDoc::OnFileOpen() 
{

static char BASED_CODE szFilter[] =
"All Files (*.*)|*.*|C++ Files (*.cpp, *.h)| "\
"*.cpp;*.h||";

CFileDialog dlg(TRUE,NULL,NULL,NULL,szFilter);

if (dlg.DoModal() == IDOK)
{
m_File1 = m_File2 = dlg.GetPathName();
}
}
The solution code for this exercise is located in the folder <install folder>\Labs\Ch04\Lab4.2\Ex02\Solution.

Exercise 3: Using the Rich Edit Views in the Application

Continue with the files you created in Exercise 2 or, if you do not have a starting point for this exercise, the code that forms the basis for this exercise is in <install folder>\Labs\Ch04\Lab4.2\Ex03.

In this exercise, you will use the rich edit views to display the file that the user chooses in the File dialog box. You will create a function that serializes text data into the rich edit views, and drive that function from the OnFileOpen handler.

Get the application and the main frame

  1. Open the file Diff.h.
  2. Add a forward reference to CMainFrame before the definition of CDiffApp as follows:
  3. class CMainFrame;

  4. Define a public method to return a pointer to the application as follows:
  5. public:
    static CDiffApp * GetApp()
    {
    return (CDiffApp *)AfxGetApp();
    }

  6. Define a public method to a pointer to the main frame as follows:
  7. CMainFrame * GetMainFrame() 
    {
    return (CMainFrame *)m_pMainWnd;
    }

    Note that the purpose of steps 3 and 4 is to simplify writing the code for the rest of this lab.

  8. Save Diff.h.

Initialize the file members and set the views to text only

  1. Open the file DiffDoc.cpp and scroll to CDiffDoc::CDiffDoc.
  2. Initialize m_File1 and m_File2 as empty strings as follows:
  3. m_File1 = _T("");
    m_File2 = _T("");

  4. The m_bRTF member of CRichEditDoc defines whether the streams should store formatting. Because you will only be dealing with text, set this member to FALSE as follows:
  5. m_bRTF  = FALSE;

  6. Save DiffDoc.cpp.

Add the function to display the files in the views

  1. Right-click CDiffDoc in ClassView and add the following public function:
  2. void RunComparison(LPCSTR lpszFile1, LPCSTR lpszFile2)

  3. Open DiffDoc.cpp. Include DiffView.h, the file Splitter.h, and the file MainFrm.h after the statement that includes DiffDoc.h as follows:
  4. #include "diffdoc.h"
    #include "diffview.h"
    #include "splitter.h"
    #include "mainfrm.h"

Write the code for the Run Comparison function

  1. Get the splitter:
  2. CMainFrame * pFrame = CDiffApp::GetApp()->GetMainFrame();
    CSplitter * pSplitter = pFrame->GetSplitter();

  3. Get the first pane as follows:
  4. CDiffView * pView;
    pView = (CDiffView *)pSplitter->GetPane(0,0);

  5. Stream the first file into the first pane as follows:
  6. CFile	file(lpszFile1, CFile::modeRead);
    CArchive ar(&file, CArchive::load);
    pView->Serialize(ar);

  7. Repeat the procedure for the second pane.
  8. Mark the document as "clean" so as not to save it:
  9. SetModifiedFlag(FALSE);

  10. Save DiffDoc.cpp.

The following sample code shows an example of how your code should look. To copy this code for use in your own projects, see "Lab 4.2.3 RunComparison" on the accompanying CD-ROM.

void CDiffDoc::RunComparison (LPCSTR lpszFile1, 
           LPCSTR lpszFile2)
{
CMainFrame * pFrame = CDiffApp::GetApp()->GetMainFrame();

if(pFrame)
{
CSplitter * pSplitter = pFrame->GetSplitter();

if(pSplitter)
{
CDiffView * pView;

pView = (CDiffView *)pSplitter->GetPane(0,0);

if(pView)
{
CFile file(lpszFile1, CFile::modeRead);
CArchive ar(&file, CArchive::load);
pView->Serialize(ar);
}

pView = (CDiffView *)pSplitter->GetPane(0,1);

if(pView)
{
CFile file(lpszFile2, CFile::modeRead);
CArchive ar(&file, CArchive::load);
pView->Serialize(ar);
}
//Flag as clean so that we won't get prompted to save
SetModifiedFlag(FALSE);
}
}
}
Call RunComparison from OnFileOpen

  1. Scroll to the end of CDiffDoc::OnFileOpen.
  2. Add a call to RunComparison with the two files as shown:
  3. RunComparison (m_File1, m_File2);

  4. Save DiffDoc.cpp.

Set the rich edit control to read-only

  1. Open ClassWizard.
  2. Add a handler for OnInitialUpdate to CDiffView.
  3. Open the file DiffView.cpp.
  4. Add a call to SetReadOnly to the end of OnInitialUpdate as follows:
  5. GetRichEditCtrl().SetReadOnly();

  6. Save DiffView.cpp.

Make the changes to CMainFrame

  1. Open MainFrm.h.
  2. Add a public attribute method to return the splitter object as follows:
  3. CSplitter * GetSplitter() { return &m_wndSplitter; }

  4. Save MainFrm.h.
  5. In the CMainFrame::OnCreateClient function of the file MainFrm.cpp, comment out SetActiveView as follows:
  6. //SetActiveView((CView *)m_wndSplitter.GetPane(0,1));

  7. Save MainFrm.cpp.

Build and test the application

  • Run your application and open a file. You will see that the file appears in the two panes of the window.

The solution code for this exercise is located in the folder <install folder>\Labs\Ch04\Lab4.2\Ex03\Solution.

Exercise 4: Managing Drag-and-Drop Editing

Continue with the files you created in Exercise 3 or, if you do not have a starting point for this exercise, the code that forms the basis for this exercise is in <install folder>\Labs\Ch04\Lab4.2\Ex04.

In this exercise, you will modify the behavior of CRichEdit so that it will open a file that is dragged from Windows Explorer to the window pane of the running application. For purposes of this exercise, you will process dropped files only if two files are dropped. Ignore any additional files beyond the first two.

Implement CMain Frame::OnDropFiles

  1. Add a handler for WM_DROPFILES to CMainFrame using ClassWizard.
  2. Determine the number of files being dropped:
  3. UINT nFileCount = 
    ::DragQueryFile (hDropInfo,0xFFFFFFFF, NULL, 0);

  4. Determine whether two or more files have been dropped:
  5. if (nFileCount >= 2)

Edit CMainFrame::OnDropFiles to get the first two dropped files and pass them to CDiffDoc::RunComparison

  1. Get the path of the first file:
  2. CString File1;

    ::DragQueryFile(hDropInfo,
                0,
                File1.GetBufferSetLength(_MAX_PATH),
                _MAX_PATH);
    File1.ReleaseBuffer();

  3. Repeat the process for the second file.
  4. Call CDiffDoc::RunComparison:
  5. ((CDiffDoc *)GetActiveDocument())->
                RunComparison(File1, File2);

  6. Finish drag-and-drop processing:
  7. ::DragFinish(hDropInfo);

The following sample code shows an example of how your code should look. To copy this code for use in your own projects, see "Lab 4.2.4 CMainFrame::OnDropFiles" on the accompanying CD-ROM.

void CMainFrame::OnDropFiles(HDROP hDropInfo) 
{
UINT nFileCount = ::DragQueryFile (hDropInfo,
                0xFFFFFFFF,
                NULL, 0);
ASSERT(nFileCount !=0);

// We must have at least two files for this function;
// we will grab only the first two

if (nFileCount >= 2)
{
CString File1;
CString File2;

::DragQueryFile(hDropInfo,
                        0,
                        File1.GetBufferSetLength(_MAX_PATH),
                        _MAX_PATH);
File1.ReleaseBuffer();

::DragQueryFile(hDropInfo,
                        1,
                        File2.GetBufferSetLength(_MAX_PATH),
                        _MAX_PATH);
File2.ReleaseBuffer();

((CDiffDoc *)GetActiveDocument())->
                        RunComparison(File1, File2);

::DragFinish(hDropInfo);
}
}
Add a handler for WM_DROPFILES to CDiffView

  • Use ClassWizard to add a handler for WM_DROPFILES to CDiffView.

Pass the WM_DROPFILES message to CMainFrame from CDiffView

  1. In CDiffView::OnDropFiles, get the main frame window:
  2. CDiffApp::GetApp()->GetMainFrame()

  3. Send WM_DROPFILES to it:
  4. CDiffApp::GetApp()->GetMainFrame()->SendMessage(  WM_DROPFILES,
    (WPARAM)hDropInfo );

  5. Comment out the default OnDropFiles behavior so OLE embedding will not be invoked:
  6. //CrichEditView::OnDropFiles(hDropInfo);

    The following sample code shows an example of how your code should look. To copy this code for use in your own projects, see "Lab 4.2.4 CDiffView::OnDropFiles" on the accompanying CD-ROM.

    void CDiffView::OnDropFiles(HDROP hDropInfo) 
    {

    CDiffApp::GetApp()->GetMainFrame()->
                SendMessage (WM_DROPFILES,
                            (WPARAM)hDropInfo);
    // Don't call the default—we don't want OLE embedding behavior
    //CRichEditView::OnDropFiles(hDropInfo);
    }

  7. In the file DiffView.cpp, include the file splitter.h and the file mainfrm.h after the file diffView.h:
  8. #include "splitter.h"
    #include "mainfrm.h"

Build and test the application

  1. Run the application.
  2. Invoke Windows Explorer and drag any two files from Windows Explorer to the window pane of the running application.
  3. You will see that the files appear in the two panes of the window.

The solution code for this exercise is located in the folder <install folder>\Labs\Ch04\Lab4.2\Ex04\Solution.


Previous    |    Table of Contents    |    Next


Visit Microsoft Press for more information on
Microsoft® Mastering: MFC Development Using Microsoft Visual C++® 6.0


Top of Page


Last Updated: Friday, July 6, 2001