Using ATL to Automate an MFC Application

  1. Lets start first to make the application visible. Add a property 'Visible' as a VARIANT_BOOL. The code should look like this:
    //-----------------------------------------------
    // get & put_Visible
    //-----------------------------------------------
    //
    STDMETHODIMP
    CAutoATLApp::get_Visible(VARIANT_BOOL *pVal)
    {
     METHOD_PROLOGUE_ATL
    
     CWnd* pMainWnd = AfxGetMainWnd();
     ASSERT(pMainWnd);
     *pVal = pMainWnd->IsWindowVisible();
    
     return S_OK;
    }
    
    STDMETHODIMP
    CAutoATLApp::put_Visible(VARIANT_BOOL newVal)
    {
     METHOD_PROLOGUE_ATL
    
     CWnd* pMainWnd = AfxGetMainWnd();
     ASSERT(pMainWnd);
     pMainWnd->ShowWindow(SW_SHOW);
     pMainWnd->UpdateWindow();
    
     return S_OK;
    }
    
  2. When i document i created by a client no frame or views are created. To be able to do so we must override CreateNewDocument in CMultiDocTemplate. CreateNewDocument is called from OpenDocumentFile to create a new document. But the document already exists. CrateNewDocument should therefor be altered NOT to create a document. Create a new class that inherites from CMultiDocTemplate and override CreateNewDocument and add a member variable CDocument* m_pDocument. CreateNewDocument should look like this:
    CDocument*
    CAnotherMultiDocTemplate::CreateNewDocument()
    {
     // default implementation constructs one from CRuntimeClass
     if (m_pDocClass == NULL)
     {
      TRACE0("Error: you must override "
             "CDocTemplate::CreateNewDocument.\n");
      ASSERT(FALSE);
      return NULL;
     }
    
    //-----------------------------------------------
    //	BdL; Document has already been created!
    //
    //	CDocument* pDocument = 
    //	   (CDocument*)m_pDocClass->CreateObject();
    //-----------------------------------------------
     if (m_pDocument == NULL)
     {
      TRACE1("Warning: Dynamic create of document "
             "type %hs failed.\n",
      m_pDocClass->m_lpszClassName);
      return NULL;
     }
    
     ASSERT_KINDOF(CDocument, m_pDocument);
     AddDocument(m_pDocument);
     return m_pDocument;
    }
    

    To make your life a bit more easy, add the header file (AnotherMultiDocTemplate.h) of the new class to stdafx.h

  3. Alter in InitInstance of the application the DocumentTemplate:
    // CMultiDocTemplate* pDocTemplate;		
    // pDocTemplate = new CMultiDocTemplate(
    to
    CAnotherMultiDocTemplate* pDocTemplate;
    pDocTemplate = new CAnotherMultiDocTemplate(
    
  4. Add FinalConstruct and FinalRelease to CAutoATLDoc. FinalConstruct will continue to create Frame and View. FinalRelease will the necessary cleanup.

    Add the following lines to CAutoAtlDoc.h

    HRESULT	FinalConstruct();
    void	FinalRelease();
    

    Add the following lines to CAutoAtlDoc.cpp

    HRESULT
    CAutoATLDoc::FinalConstruct()
    {
     METHOD_PROLOGUE_ATL
    
     CAutoATLApp* pApp = (CAutoATLApp*)AfxGetApp();
     ASSERT_VALID(pApp);
    
     // Find document template
     POSITION pos = pApp->GetFirstDocTemplatePosition();
     CAnotherMultiDocTemplate* pDocClass = 
      (CAnotherMultiDocTemplate*)pApp->GetNextDocTemplate(pos);
    
     ASSERT_VALID(pDocClass);
    
     // Create view and frame
     pDocClass->m_pDocument = this;
     pDocClass->OpenDocumentFile(NULL, true);
    
     return S_OK;
    }
    
    void
    CAutoATLDoc::FinalRelease()
    {
     // Do will still have a View connected?
     // (The frame will no longer exist if the document
     // has been closed manually, because the OnClose
     // message is passed BEFORE deleting the document)
     POSITION pos = GetFirstViewPosition();
     if (pos != NULL) {
      // Prevent the document from deleting itself already.
      m_bAutoDelete = false;
      OnCloseDocument();
      m_bAutoDelete = true;
     }
    }
    
  5. In the application override OnFileOpen, OnFileNew and OpenDocumentFile. Normally OnFileOpen and OnFileNew create a document AND the frame and view. Now the frame and view are now created in the FinalConstruct of CAutoAtlDoc.
    //-----------------------------------------------
    // 
    //-----------------------------------------------
    //
    void
    CAutoATLApp::OnFileNew() 
    {
     // Dynamically create a new CFuchiaDocument.
     // The document will continue to create itself
     // in the constructor.
     IMPLEMENT_CREATE_DOCUMENT;
    }
    
    void
    CAutoATLApp::OnFileOpen() 
    {
     // prompt the user (with all document templates)
     CString _lpszPathName;
     if (!DoPromptFileName(_lpszPathName, 
                           AFX_IDS_OPENFILE,
                           OFN_HIDEREADONLY | OFN_FILEMUSTEXIST,
                           TRUE, NULL))
      return; // open cancelled
    
     OpenDocumentFile(_lpszPathName);
    }
    
    CDocument*
    CAutoATLApp::OpenDocumentFile(LPCTSTR lpszFileName) 
    {
     // Dynamically create a new CFuchiaDocument.
     // The document will continue to create itself
     // in the constructor.
     IMPLEMENT_CREATE_DOCUMENT;
    
     // Open an existing document
     CWaitCursor wait;
     if ( !pDoc->OnOpenDocument( lpszFileName ) )
     {
      // Unable to open the document.
      TRACE( "Unable to open the document \
      in %s at %d.\n", THIS_FILE, __LINE__ );
      // We must delete the document instance.
      pDoc->Release();
      return NULL;
     }
    
     // Set the document file path and name.
     pDoc->SetPathName(lpszFileName);
     return pDoc;
    }
    
  6. IMPLEMENT_CREATE_DOCUMENT is a macro you can put on top in the document header file.
    //-----------------------------------------------
    // Call this MACRO when you need to create a new Document.
    // The document will construct itself further inside
    // FinalConstruct.
    #define IMPLEMENT_CREATE_DOCUMENT \
     CComObject* pDoc; \
     HRESULT hr = CComObject::CreateInstance(&pDoc); \
     ASSERT(SUCCEEDED(hr)); \
     pDoc->InternalAddRef();
    //-----------------------------------------------
    

Downloads

Download demo project - 44 Kb


Comments

  • There are no comments yet. Be the first to comment!

Leave a Comment
  • Your email address will not be published. All fields are required.

Top White Papers and Webcasts

  • Live Event Date: May 18, 2015 @ 1:00 p.m. ET / 10:00 a.m. PT While the idea of using facial and or gesture recognitions to create a modern, intuitive game seems attractive, some developers may want to leverage Unity 3D as a way to accelerate their development. There are many different ways in which Intel and Unity Technologies have been working together to helps speed the develop of games with the Intel® RealSense™ SDK (Software Developer Kit), so come hear from a panel of experts on what we've done …

  • There has been growing buzz about DevOps. DevOps is a methodology that unites the often separate functions of software development (Dev) and production and operations (Ops) into a single, integrated, and continuous process. DevOps is about breaking down the barriers between Dev and Ops. It leverages people, processes, and technology to stimulate collaboration and innovation across the entire software development and release process. Dev and Ops should always be part of an integrated process, but that's not …

Most Popular Programming Stories

More for Developers

RSS Feeds

Thanks for your registration, follow us on our social networks to keep up-to-date