Using the Document/View Architecture with a DLL

I recently needed to be able to create new document/view that were contained within a DLL. After an initial search on CodeGuru, I didn't find any artical which covered this subject. So I went ahead and tried to do it myself. It comes down to overriding two class's which MFC uses to create and manage the document templates used. These are CDocManager and CMultiDocTemplate (I am doing this in an MDI app).

The CDocManager class was inherited from to add the functionality to open a given document type without having to display the MFC "Select document type" dialog which is used when more than one document template exists in the project. The CMultiDocTemplate was inherited from and virtual functions re-written to allow the new class to load the resources from the DLL instance and not the EXE's.

Ok, so how do we go about doing this. First you need to create your DLL, and add a document/view class which will be your document type. Create a class inheriting from CView, CScrollView or CFormView etc. Do the same for a class inheriting from CDocument. You will have to write the GetDocument() function for the view, its just a copy of what you see in a regular .EXE file doc/view class but with the DLL class names.

You have to add an exported function from the DLL as follows :
CMyMultiDocTemplate* DLLNewDocTemplate()
{
 CMyMultiDocTemplate	*pTemplate = NULL ;
 
 // add our document template
 pTemplate = new CMyMultiDocTemplate(
  theApp.m_hInstance,         // the DLL's app object HINSTANCE
  IDR_DLL_TYPE,               // the document/view resource info
  RUNTIME_CLASS(CMyDLLDoc),
  RUNTIME_CLASS(CChildFrame), // custom MDI child frame
  RUNTIME_CLASS(CMyDLLView));
 
 return pTemplate ;
}
When you call this procedure, it returns a pointer to a CMyMultiDocTemplate object which can be added to the list of available document types in your main exe's InitInstance() procedure. Your DLL must have the following resources defined with the ID of IDR_DLL_TYPE : Menu - The menu that gets switched to when the doc/view type is open and selected. Dialog - A CFormView dialog template if your class inherits from CFormView. String table - Document type names in the same format as the type used in a .exe file. example "\nDLL\nDLL\n\n\nDLL.Document\nDLL Document" Icon - The icon that appears on the windows title bar What code goes in your InitInstance? In your apps InitInstance() there will be some code to add the single document template that your app will currently support. You need to do some minor modification to this as follows :
// Register the application's document templates
// Document templates serve as the connection between 
// documents, frame windows and views. need to setup 
// our own document manager before the first call of
// AddDocTemplate(...)
  
// we replace the default doc manager
m_pDocManager = new CMyDocManager ;		

// MFC only creates its own one if m_pDocManager is NULL

// change the template type to our inherited one
CMyMultiDocTemplate* pDocTemplate;		
pDocTemplate = new CMyMultiDocTemplate(
 theApp.m_hInstance, // the apps HINTANCE
 IDR_SOMECLASSTYPE,
 RUNTIME_CLASS(CSomeClassDoc),
 RUNTIME_CLASS(CChildFrame),
 RUNTIME_CLASS(CSomeClassView));
 AddDocTemplate(pDocTemplate);

// add your DLL calls here to DLLNewDocTemplate()
// e.g.
for (int i = 0 ;i < number_of_dlls ; i++)
{
 pTemplate = SomeDLL.DLLNewDocTemplate() ;
 if (pTemplate != NULL)
 AddDocTemplate(pDocTemplate) ;
}

// then call AddDoctemplate() on the returned values.
// you have to do this before the call to 
// RegisterShellFileTypes()
You also have to modify your ExitInstance to deal with the inherited CMyDocManager. If you don't do this, MFC will fail to deallocate correctly. Add these lines :
// delete doc manager before unloading dll's
delete (CMyDocManager*)m_pDocManager ;
m_pDocManager = NULL ;
// from this point you can unload your DLL's
// doing so before here will cause problems

This must be done before the call to CWinApp::ExitInstance() and before your DLL's are unloaded!

Ok thats the big work out of the way. How do you open a document of these new types ? For your regular EXE doc/view type the current mechanism will work as normal except that you will get the MFC "select document type" dialog. If you dont want this change your apps OnFileNew() as follows :

// this will open your regular .exe document type
// without using the "Select document type" dialog

//CWinApp::OnFileNew() ;

// create first document type
((CMyDocManager*)m_pDocManager)->CreateNewDocument(0); 

This command holds for any of the given document types that have been added. To create the 2nd document type :

// create 2nd document type
((CMyDocManager*)m_pDocManager)->CreateNewDocument(1);

So thats it basically. You just need to put the regular doc/view code handling stuff in your DLL and add the .h and .cpp files to your projects as required. You also have to export your CChildFrame class's to your DLL's as well to make the class accessable there.

Word of warning

Your menus could be the biggest problem after this point. If you have standard menu options like those in the default menu displayed when no documents are open, I recommend that you copy this menu across into your DLL as a base menu from which to build the menu used by your new document type, that way the ID's for all the original menu options will work without any problems. You should also check for possible clashes between any new menu items you add to the DLL menu to make sure they are not used by any in the menu's used by the exe's document.

I hope this helps.

Downloads

Download source and demo - 83 Kb


About the Author

Roger Allen

Its me!

Comments

  • good

    Posted by wsq on 07/30/2013 05:53am

    it is very good. thank you.

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

Top White Papers and Webcasts

  • Managing your company's financials is the backbone of your business and is vital to the long-term health and viability of your company. To continue applying the necessary financial rigor to support rapid growth, the accounting department needs the right tools to most efficiently do their job. Read this white paper to understand the 10 essentials of a complete financial management system and how the right solution can help you keep up with the rapidly changing business world.

  • With 81% of employees using their phones at work, companies have stopped asking: "Is corporate data leaking from personal devices?" and started asking: "How do we effectively prevent corporate data from leaking from personal devices?" The answer has not been simple. ZixOne raises the bar on BYOD security by not allowing email data to reside on the device. In addition, Zix allows employees to maintain complete control of their personal device, therefore satisfying privacy demands of valued employees and the …

Most Popular Programming Stories

More for Developers

Latest Developer Headlines

RSS Feeds