Link to home
Start Free TrialLog in
Avatar of qocarlos
qocarlosFlag for Saint Kitts and Nevis

asked on

How to implement an import command

I need to implement an import command in my MDI application but I cannot figure out how to do it using the MFC serialization mechanism.  My application needs to import files coming from different machines (these  files have no extension). I have tried to follow the tips given in the  Technical note 22:

"One common customization of ID_FILE_OPEN is to customize the FileOpen
dialog or add additional file filters. The recommended way to customize
this is to replace the default implementation with your own FileOpen
dialog, and call CWinApp::OpenDocumentFile with the document's file or path
name. There is no need to call the base class."

I have followed this procedure but without success. This is the code:
void CMyApp::OnFileOpen()
{
      CMyCustomFileOpenDlg dlg(TRUE);
      
      int nResponse=dlg.DoModal();
      //In this dialog, the user must set in the m_fileType member variable
      //the file format.
      //Later, the MyDoc::Serialize function will use this variable to proceed.
      
      
      CWinApp::OpenDocumentFile(filename);
      
}

I have discovered that when   CMyApp::OnFileOpen is overrided, the CMyDoc::Serialize function is not called so I cannot do something as follows:
void MyDoc::Serialize (CArchive& ar)
 {
  if (ar.IsStoring())
  {
   // Storing code
 
  }
  else
  {
   // Reading code
   if (m_FileType== FILE_TYPE_A)
   {
    //import doc A
 
   }
   if (m_FileType== FILE_TYPE_B)
   {
    //import doc B
 
   }
  }
 }

What am I doing wrong?
Might be there is a best way to implement an import option, but I don't really know how.
ASKER CERTIFIED SOLUTION
Avatar of snoegler
snoegler

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of qocarlos

ASKER

I need to customize the standar FileOpen dialog because the user must select more than one file by selecting the file and then adding each file to a list box (this is because the files to be opened are in separate folders). I have also added to the customized File Open dialog a combo box where the user can select the file type. I store all the files in a CStringList member variable.
All these external  files must be converted then in one internal document.
I cannot use something like:

if(extension==".myd") // mydocument type
         ....
if(extension==".xls") // excel document type

because these files has no extension.

I'm still very confused...
Avatar of snoegler
snoegler

I don't understand your problem.
Take a look at this:

void CMyApp::OnFileOpen()
    {
    CMyCustomFileOpenDlg dlg(TRUE);

    int nResponse=dlg.DoModal();
    //In this dialog, the user must set in the m_fileType member variable
    //the file format.
    //Later, the MyDoc::Serialize function will use this variable to proceed.

   // *dlg.m_FileListBox contains the files the user selected*
   int i,size=dlg.m_FileListBox.GetCount();
   for(i=0;i<size;i++) {
      CString cur_file;
      m_FileListBox.GetText(i,cur_file);
      // m_pMainWnd points to the main CFrameWnd of your app( i.e. CMainFrame)
      ((CFrameWnd*)m_pMainWnd)->GetActiveDocument()->ImportFile(cur_file,dlg.m_fileType);
    }
}

And the CDocument::ImportFile() reads in the data, with m_fileType specifying the type of the
file to import.
Does this solve your problem? If not, please give a bit more information about what is to be
done ...
Thanks for your help but I'm still have problems!
This is what I have tried using your previous advice:

void CMyApp::OnFileOpen()
{
     (...)
      CMyDoc *pDoc=CMyDoc::GetDoc();
      pDoc->ImportFile(cur_file,dlg.m_fileType);
}

where
CMyDoc * CMyDoc ::GetDoc()
{
      CMDIChildWnd * pChild =
          ((CMDIFrameWnd*)(AfxGetApp()->m_pMainWnd))->MDIGetActive();
 
      if ( !pChild )
          return NULL;
 
      CDocument * pDoc = pChild->GetActiveDocument();
 
      if ( !pDoc )
         return NULL;
 
      // Fail if doc is of wrong kind
      if ( ! pDoc->IsKindOf( RUNTIME_CLASS(CMestreCProDoc) ) )
         return NULL;
 
      return (CMyDoc *) pDoc;
}

but after calling CMyDoc:: ImportFile(cur_file,dlg.m_fileType) and reading
the files, how should I create the window? (all the files contained indlg.m_FileListBox must be opened in the same document).

My idea is to add a CMultiDocTemplate point to CMyApp derived class:
Class CMyApp:public CWinApp
{
   ...
   public CMultiDocTemplate* m_pDocTemplate;
   ...
}
In the InitInstance() function, remove the creation of the CMultiDocTemplate from the call to AddDocTemplate , set the pointer to point to the new CMultiDocTemplate and use the pointer to call AddDocTemplate.

So the OnFileOpen would be now:

void CMyApp::OnFileOpen()
{
     (...)
      CMyDoc *pDoc=CMyDoc::GetDoc();
      pDoc->ImportFile(cur_file,dlg.m_fileType);
      m_pDocTemplate->OpenDocumentFile(NULL);//create the new window
}

Probably this is a wrong way.
Can you give me  solution that will allow me to correctly import the files?

Thanks




The code below creates a new document and associated view.
I am assuming that there's only one CDocTemplate in your app, but if there are more, just
iterate using GetNextDocTemplate() until you have the right one (see docs).
The line with 'pNewDoc->OnNewDocument()'  you could replace with the code which opens
the file dialog window, and call perhaps the pNewDoc->OnImportFile() for each file or so.
I hope this time i got you right =o)


void  CMestreCProApp::OnFileOpen()
{
  // TODO: Add your command handler code here
  // 1st.: Get the appropriate CDocTemplate()
  // I am assuming that there's only one CDocTemplate()
 
  POSITION pos=GetFirstDocTemplatePosition();
  if(pos==NULL) {
    // error //
    return;
  }
  CDocTemplate *pdTemp=GetNextDocTemplate(pos);
 
  // 2nd.: Create Doc&Frame
  CDocument *pNewDoc;
  CChildFrame *pChildFrm;
 
  pNewDoc =pdTemp->CreateNewDocument();
  pChildFrm =(CChildFrame*)pdTemp->CreateNewFrame(pNewDoc,NULL);
  pdTemp->SetDefaultTitle(pNewDoc);

  // 3rd: Notify Doc of its existence  
  // *you could also do here the CFileDialog() and then pNewDoc->OnImportFiles(CListBox ...)
  pNewDoc->OnNewDocument();
  pdTemp->InitialUpdateFrame(pChildFrm,pNewDoc,TRUE);
}
Snoegler,
I have tried your code and it worked great! Thanks a lot.
I'd just like to know if my code (see my previous comment) has any disavantage compared with your code.
I think what you wrote is exactly the same as what i proposed.
I didn't read your whole comment, sorry for that ... I don't like reading code, especially if it isn't
formatted at all like here at experts exchange. The way you want to do it should work - the
way i used is just an alternative way to that what you've done (i think so, but i didn't try what
you posted).

I have also tried my code and it worked!!
Thanks again for your help