Creating an MDI Application (C++ 5.0 and later)

Take the following steps to start an MDI (Multiple Document Interface) project and to add some code that positions, scales, and displays an image in a dialog box.

1.

Start the Microsoft Developer Studio for Visual C++, version 5.0.

2.

Select the File >New menu option, select Project Workspace, and click the OK button.

3.

In the New Project Workspace dialog box, do the following:

 

a.

In the Type list box, select MFC AppWizard (exe).

 

b.

In the Name text box, specify mditutor.

 

c.

In the Location text box, specify the path of the project.

 

d.

In the Platforms list box, check Win32 Platforms.

 

e.

Click the Create button.

4.

In the Step 1 dialog box, do the following:

 

a.

Select Multiple Documents.

 

b.

Click the Next button.

5.

In the Step 2 of 6 dialog box, do the following:

 

a.

Select None for Database support.

 

b.

Click the Next button.

6.

In the Step 3 of 6 dialog box, do the following:

 

a.

Select None for OLE compound document support.

 

b.

Select ActiveX Controls for the type of OLE support.

 

c.

Click the Next button.

7.

In the Step 4 of 6 dialog box, do the following:

 

a.

Ensure that that 3D Controls and Printing and Print Preview are selected as features to include.

 

b.

Click the Next button.

8.

In the Step 5 of 6 dialog box, do the following:

 

a.

For comments, ensure that Yes, Please is selected.

 

b.

For how to use the MFC library, select As a shared DLL.

 

c.

Click the Next button.

9.

In the Step 6 of 6 dialog box, do the following:

 

a.

Select CMditutorView from the class list that AppWizard will create so that it appears in the Class name entry field.

 

b.

Change the Base class from CView to CFormView.

 

c.

Click the Finish button.

10.

Read New Project Information, and click OK. (The AppWizard creates the project files and opens the project.)

11.

Add #import and #include statements to your program so you can access the LEAD COM constants and classes:

 

a.

In the Project Workspace, click the FileView tab.

 

b.

Double-click the mditutor files folder to open it.

 

c.

Double-click the Header Files folder to open it.

 

d.

Double-click the StdAfx.h file to edit it.

 

e.

Add the following lines to the end of the file (keep in mind, you may have to change the path to where the dll's reside):

#import "c:\\winnt\\system32\\ltrvr14n.dll"  no_namespace, named_guids
#import "c:\\winnt\\system32\\ltr14n.dll" no_namespace, named_guids
#import "c:\\winnt\\system32\\ltrvw14n.ocx" no_namespace, named_guids
#import "c:\\winnt\\system32\\ltrio14n.dll" no_namespace, named_guids
#import "c:\\winnt\\system32\\ltrpr14n.dll" no_namespace, named_guids
#include "leadraster.h"

12.

Change the resource file to add a LEAD RasterView control to the mditutor dialog template form as follows:

 

a.

In the Project Workspace, click the ResourceView tab.

 

b.

Double-click the mditutor resources folder to open it.

 

c.

Double-click the Dialog folder to open it.

 

d.

Double-click IDD_MDITUTOR_FORM to design the form.

 

e.

Select the TODO... text control; then press the Delete key to delete it.

 

f.

From the main menu, select Project > Add to project > Components and Controls. (The Component Gallery appears.)

 

g.

Click the Registered ActiveX Contols.

 

h.

Double-click the LEAD RasterView Control icon. (The Confirm Classes dialog box appears.)

 

i.

Ensure that both CLEADRasterView, CLEADRaster, and CPicture are checked.

 

j.

Click OK to complete the selection; then click Close to close the Component Gallery. (The LEAD RasterView control appears in the Controls toolbar.)

 

k.

image\btnlead.gif Click the LEAD RasterView control icon; then click the mditutor dialog box to add the control to the dialog box.

 

l.

Double-click the new LEAD RasterView control to edit its properties.

 

m.

Change the ID to IDC_LEADRASTERVIEW1.

 

n.

Press Ctrl-F4 to close all windows back to the Project Workspace.

13.

Do the following to add m_LEADRasterView1 to the CMditutorView class and link the variable to the LEAD RasterView control using dynamic data exchange:

 

a.

From the main menu, select View > ClassWizard. (The MFC ClassWizard dialog box appears.)

 

b.

Click the Member Variables tab.

 

c.

In the Class Name box, select CMditutorView.

 

d.

In the Control IDs list, select IDC_LEADRASTERVIEW1.

 

e.

Click the Add Variable... button.

 

f.

Specify m_LEADRasterView1 as the variable name, and Control as the category.

 

g.

Click OK to close the dialog box.

14.

Do the following to add code to the OnInitialUpdate function:

 

a.

Click the Message Maps tab.

 

b.

In the Class Name combo box, select CMditutorView.

 

c.

In the Object IDs list box, select CMditutorView.

 

d.

In the Messages list box, select OnInitialUpdate.

 

e.

Click the Add function button.

 

f.

Click the Edit Code button to start entering the code.

15.

Edit the OnInitialUpdate() function to add the following code after the line that says //TODO: Add your specialized code here:

ILEADRasterIO *pRasterIO=NULL;
CoCreateInstance(CLSID_LEADRasterIO, NULL, CLSCTX_ALL, IID_ILEADRasterIO, (void**)&pRasterIO);
CDocument *pDoc = GetDocument();
int nRet = pRasterIO->Load(m_LEADRasterView1.GetRaster(),
                           LPCTSTR(pDoc->GetPathName()), 0, 1, 1);
pRasterIO->Release();
if(nRet)
{
   TCHAR szBuffer[30];
   wsprintf(szBuffer, TEXT("Load Error: Error code %d"), nRet);
   AfxMessageBox(szBuffer);
   m_LEADRasterView1.GetRaster().SetBitmap(0);
   // Parent of view is MDI Child frame window
   CFrameWnd *pMDIFrame = GetParentFrame(); 
   pMDIFrame->PostMessage(WM_CLOSE);
}
else
{
   m_LEADRasterView1.SetPaintPalette(PAINTPALETTE_AUTO);
   CRect rcRect; 
   GetClientRect(rcRect);
   m_LEADRasterView1.MoveWindow(rcRect);
}

16.

In the file Mditutor.CPP, find the function CMditutorApp::InitInstance() and comment out some lines as follows:

// Parse command line for standard shell commands, DDE, file open
// CCommandLineInfo cmdInfo;
// ParseCommandLine(cmdInfo);
// Dispatch commands specified on the command line
// if (!ProcessShellCommand(cmdInfo))
// return FALSE;

17.

Press Ctrl-W to go to the MFC Class Wizard; then do the following:

 

a.

Click the Message Maps tab.

 

b.

In the Class Name combo box, select CMditutorView.

 

c.

In the Object IDs list box, select CMditutorView.

 

d.

In the Messages list box, select WM_SIZE.

 

e.

Click the Add function button.

 

f.

Click the Edit Code button to start entering the code.

18.

Edit the OnSize() function to add the following code after the line that says //TODO: Add your message handler code here:

if (IsWindow(m_LEADRasterView1.m_hWnd))
  m_LEADRasterView1.MoveWindow(0, 0, cx, cy);

19.

Press Ctrl-W to go to the MFC Class Wizard; then do the following:

 

a.

Click the Message Maps tab.

 

b.

In the Class Name combo box, select CMainFrame.

 

c.

In the Object IDs list box, select CMainFrame.

 

d.

In the Messages list box, select WM_PALETTECHANGED.

 

e.

Click the Add function button.

 

f.

Click the Edit Code button to start entering the code.

20.

Edit the OnPaletteChanged() function to add the following code after the line that says //TODO: Add your message handler code here:

CMDIChildWnd* pMDIChildWnd = MDIGetActive();
if (pMDIChildWnd == NULL)
  return; // no active MDI child frame
SendMessageToDescendants(WM_DOREALIZE,
  (WPARAM)pFocusWnd->m_hWnd, (LPARAM) TRUE);

21.

Press Ctrl-W to go to the MFC Class Wizard; then do the following:

 

a.

Click the Message Maps tab.

 

b.

In the Class Name combo box, select CMainFrame.

 

c.

In the Object IDs list box, select CMainFrame.

 

d.

In the Messages list box, select WM_QUERYNEWPALETTE.

 

e.

Click the Add function button.

 

f.

Click the Edit Code button to start entering the code.

22.

Edit the OnQueryNewPalette() function so that it appears as follows:

BOOL CMainFrame::OnQueryNewPalette() 
{
  // always realize the palette for the active view
  CMDIChildWnd* pMDIChildWnd = MDIGetActive();
  if (pMDIChildWnd == NULL)
    return FALSE; // no active MDI child frame (no new palette)
  CView* pView = pMDIChildWnd->GetActiveView();
  ASSERT(pView != NULL);
  // just notify the target view
  return((BOOL) pView->SendMessage(WM_DOREALIZE, 
                         (WPARAM)m_hWnd, (LPARAM) FALSE));
}

23.

Edit the MDITUTOR.H file and add the following line after the preprocessing:

#define WM_DOREALIZE  (WM_USER + 512)

24.

Edit the MDITUTORVIEW.H file and insert the following line just before DECLARE_MESSAGE_MAP():

afx_msg LRESULT OnDoRealize(WPARAM wParam, LPARAM lParam);

25.

Edit the MditutorView.CPP file and add the following function:

LRESULT CMditutorView::OnDoRealize(WPARAM wParam, LPARAM lParam)
{
    if (!m_LEADRasterView1.m_hWnd  ||  !m_LEADRasterView1.GetRaster().GetBitmap())
         return FALSE;
    if(lParam)
    {
        return m_LEADRasterView1.SendMessage(WM_PALETTECHANGED, wParam);
    }
    else
    {
        UINT nColorsChanged = 0;
        CDC* pdc;
        pdc = theApp.m_pMainWnd->GetDC();
        HPALETTE hpal = 
           (HPALETTE)m_LEADRasterView1.GetPalette((OLE_HANDLE) pdc->m_hDC);
      if(hpal)
      {
           CPalette pal;
           pal.Attach(hpal);
          CPalette* oldPalette = pdc->SelectPalette(&pal, (BOOL) lParam);
          nColorsChanged = pdc->RealizePalette();
          if (nColorsChanged > 0)
                m_LEADRasterView1.InvalidateRect(NULL, FALSE);
          pdc->SelectPalette(oldPalette, TRUE);
      }
        theApp.m_pMainWnd->ReleaseDC(pdc);
      return ((LRESULT) (BOOL) (nColorsChanged > 0));
    }
}

26.

In the MditutorView.CPP file, look for the following lines:

BEGIN_MESSAGE_MAP(CMditutorView, CFormView)
  //{{AFX_MSG_MAP(CMditutorView)

After these lines, add the following line:

ON_MESSAGE(WM_DOREALIZE, OnDoRealize)

Also, near the top of the file, add the following line:

extern CMditutorApp  theApp;

27.

Press Ctrl-W to go to the MFC Class Wizard; then do the following:

 

a.

Click the Message Maps tab.

 

b.

In the Class Name combo box, select CMditutorView.

 

c.

In the Object IDs list box, select CMditutorView.

 

d.

In the Messages list box, select OnActivateView.

 

e.

Click the Add function button.

 

f.

Click the Edit Code button to start entering the code.

28.

Edit the OnActivateView() function so that it appears as follows:

void CMditutorView::OnActivateView(BOOL bActivate, CView* pActivateView,
                                 CView* pDeactiveView) 
{
  // TODO: Add your specialized code here and/or call the base class
  CFormView::OnActivateView(bActivate, pActivateView, pDeactiveView);
  if (bActivate)
  {
      ASSERT(pActivateView == this);
      OnDoRealize((WPARAM)theApp.m_pMainWnd->m_hWnd, 
                (LPARAM) FALSE);   // same as SendMessage(WM_DOREALIZE);
  }
}

29.

To remove the default printing functions, press Ctrl-W to go to the MFC Class Wizard; then do the following:

 

a.

Click the Message Maps tab.

 

b.

In the Class Name combo box, select CMditutorView.

 

c.

In the Object IDs list box, select CMditutorView.

 

d.

In the Messages list box, select OnPrint.

 

e.

Click Delete function and answer YES to the dialog box.

 

f.

In the Messages list box, select OnBeginPrinting.

 

g.

Click Delete function and answer YES to the dialog box.

 

h.

Click OK to exit ClassWizard.

 

i.

Go to MditutorView.CPP and manually delete the functions CMditutorView::OnPrint() and CMditutorView::OnBeginPrinting().

30.

To add new printing functions, press Ctrl-W to go to the MFC Class Wizard; then do the following:

 

a.

Click the Message Maps tab.

 

b.

In the Class Name combo box, select CMditutorView.

 

c.

In the Object IDs list box, select CMditutorView.

 

d.

In the Messages list box, select OnDraw.

 

e.

Click the Add function button.

 

f.

Click the Edit Code button to start entering the code.

31.

Edit the OnDraw() function so that it appears as follows:

void CMditutorView::OnDraw(CDC* pDC)
{
  CRect rcClip;
  CSize winext;
  CSize viewext;
  CSize paintext;
  CMditutorDoc* pDoc = GetDocument();
  ASSERT_VALID(pDoc);

  if(pDC->IsPrinting())
  {
    pDC->SaveDC();
    ::GetWindowExtEx(pDC->m_hDC, &winext);
    ::GetViewportExtEx(pDC->m_hDC, &viewext);
    paintext.cx = MulDiv((int) m_LEADRasterView1.GetRaster().GetBitmapWidth(), viewext.cx, winext.cx);
    paintext.cy = MulDiv((int) m_LEADRasterView1.GetRaster().GetBitmapHeight(), viewext.cy, winext.cy);
    ::SetMapMode(pDC->m_hDC, MM_TEXT); 
    m_LEADRasterView1.Render((OLE_HANDLE) pDC->m_hDC, (float) 0, (float) 0, (float)
                   paintext.cx, (float) paintext.cy);
    pDC->RestoreDC(-1);
  }
}

32.

To remove unused menu items, click the ResourceView tab of the Project Workspace, and do the following:

 

a.

Open the mditutor resources folder.

 

b.

Open the Menu folder.

 

c.

Double-click on IDR_MAINFRAME

 

d.

Click the File menu; then select the New menu item and press the Delete key.

 

e.

Double-click on IDR_MDITUTORTYPE.

 

f.

Click the File menu option; then select and delete the following items: New, Save, and Save As....

 

g.

Press Ctrl-F4 twice to return to the Project Workspace.

33.

On the main menu, select Build > Build mditutor.exe to build the project.

34.

On the main menu, select Build > Execute mditutor.exe to run the project.