Separating the views of an MDI application into different DLLs

Different views can be seperated into different dlls in an MDI application:

Advantages:

  • 1.Depending on the dlls (containing views)registerd in a system the application loads & shows the views.
  • 2.Need not reship the entire application in case of any bugs detected.
  • 3.Can add views at later stage with out modifying the exe.
  • I will try to explain this using an example. In my example, I have an EXE which I call Host. It is an MDI application. Then I have 2 views inside 2 DLLs. The name of these dlls are inside an INI file called HOST.INI.

    The only catch is all DLLs that the HOST application can load must export a function by called Init(). Some kind of a rudimentary COM, eh? :)

    At runtime, the HOST application loads the DLL & collects information from the INI file such as its CMultiDocTemplate pointer, the handle to the image to be displayed on the menu and string to be displayed on the menu to invoke the view.

    All of this information is stored in a simple CList of a struct I defined.

    
    struct  __VIEWINFO
    {
     int iImage;
     CString strLabel;
     CMultiDocTemplate *pDocTemp;	
    };
    
    In the OnCreate() function of the CMainFrame, the DLL is loaded.
    
     HICON hIcon;
     CString strLabel;
     CMultiDocTemplate *pDocTemplate; 
     HINSTANCE hDLL;     
     LPDLLFUNC lpfnDllFunc;   
     UINT  uReturnVal;
    
     m_List.SubclassDlgItem(IDC_LIST, &m_wndMyDialogBar);
     m_pImageList = new CImageList();
     m_pImageList ->Create(32, 32, TRUE,1, 4);
    
     int n = GetPrivateProfileInt("dll","Total",0,"host.ini");
     for (int i = 0; i < n; i++)
     {
      CString strDllName;
      strDllName.Format("dll%d",i+1);
      GetPrivateProfileString("dll",strDllName,0,strDllName.GetBuffer(15),15,"host.ini");
      strDllName.TrimRight();
      if(strDllName.IsEmpty())
       continue;
      
      hDLL = LoadLibrary(strDllName);
      lpfnDllFunc = (LPDLLFUNC)::GetProcAddress(hDLL,"Init");
      if (!lpfnDllFunc)
       FreeLibrary(hDLL);       
      else
      {
       uReturnVal = lpfnDllFunc(&hIcon,&strLabel,&pDocTemplate);
       m_pImageList ->Add(hIcon);
       __VIEWINFO *viewInfo = new __VIEWINFO;
       viewInfo->iImage = m_pImageList->GetImageCount()-1;
       viewInfo->strLabel = strLabel;
       viewInfo->pDocTemp = pDocTemplate;
       m_ViewList.AddTail(viewInfo);
      }
     }
     m_List.SetImageList(m_pImageList,LVSIL_NORMAL);
    	
     POSITION pos = m_ViewList.GetHeadPosition();
     i = 0;
     while(pos != NULL)
     {
      __VIEWINFO *viewInfo = m_ViewList.GetNext(pos);
      ASSERT(viewInfo);
      int nIndex = m_List.InsertItem(i++,viewInfo->strLabel,viewInfo->iImage);
      m_List.SetItemData(nIndex,(ULONG)viewInfo->pDocTemp);
     }
    
    When the user selects the menu item to invoke the view the view can be opened using the following code
    
    {
     int nSel = m_List.GetNextItem(-1, LVNI_SELECTED);
     if(-1 == nSel)
      return;
     CMultiDocTemplate *pDocTemplate = (CMultiDocTemplate *)m_List.GetItemData(nSel);
     pDocTemplate->OpenDocumentFile(NULL); 
    }
    
    DLLS: The DLLs are MFC extension DLLs. As I mentioned earlier, all of the DLLs that HOST will use need to export a function called Init. It is inside this function that the DLL returns it's identity to the HOST application.
    
    extern "C" AFX_EXT_API 
    UINT Init(HICON *hIcon,CString *strLabel,CMultiDocTemplate **pDocTemplate)
    {
     new CDynLinkLibrary(View1DLL);
    
     CWinApp* pApp = AfxGetApp();
     ASSERT(pApp != NULL);
    
     *pDocTemplate =  new CMultiDocTemplate(IDR_VIEW1TYPE,
      RUNTIME_CLASS(CView1Doc),
      RUNTIME_CLASS(CChildFrame),
      RUNTIME_CLASS(CView1View));
    
     pApp->AddDocTemplate(*pDocTemplate);
     *hIcon = pApp->LoadIcon(IDI_VIEW1ICON);
     *strLabel = "View 1";		
     return 0;
    }
    
    I have put togother a very simple demo, which clearly explains the whole mechanism: NOTE : Copy the ini file to the System directory

    Download demo project - 60 KB

    Date Last Updated: April 3, 1999



    Comments

    • Release Version Error

      Posted by Legacy on 09/15/2002 12:00am

      Originally posted by: sahil

      man it doesn't seems to be working with Release verrsion i m having assertion why is it.? it goes fine with debug version

      Reply
    • Resource problem can also be solved by...

      Posted by Legacy on 04/02/2000 12:00am

      Originally posted by: Kabir

      I think the resource problem of mixing and duplicating same resorce names among diff. dll's can also be solved by maintaining a single ResourceDll for the project. Any new Dll that is added needs to make modifications to this Dll only. I know this solution is not as flexible as the original idea but since for most purposes i guess the dll'd would be developed by the same organization as the one developing applications , It would be a practical solution in most cases.
      ...kabir

      Reply
    • How to ...

      Posted by Legacy on 01/23/2000 12:00am

      Originally posted by: Goran

      Hi,
      
      

      I am trying to run your demo and I keep getting
      assertion failure in appdlg.cpp on the line 35.
      What is the problem?
      Let me know please,
      Goran

      Reply
    • It's not so simple..

      Posted by Legacy on 12/21/1999 12:00am

      Originally posted by: Olivier Raoul

      It's an interesting problem.
      
      

      It's not possible to use the CDynLinkLibrary because it add the dll to the resource search list and if you have two dlls with same resource IDs, you will be in trouble.

      The sample works because you store strings in the source code, you don't have a menu, no form view, etc...

      You can't use also the AFX_MANAGE_STATE macro because the thread state which associate the WIN32 handles with C++ objects is stored in the module state. So if you switch the module state the MFC will assert because the CWnd::GetParent failed.

      The best way is the resource switching with

      #define CONTEXT_DLL() ContextSwitch resourceSaver AfxGetStaticModuleState())

      class ContextSwitch
      {
      public:
      ContextSwitch(AFX_MODULE_STATE* current)
      {
      resourceBackup=AfxGetResourceHandle();
      AfxSetResourceHandle(current}
      }
      ~ContextSwitch()
      {
      AfxSetResourceHandle(resourceBackup);
      }
      private:
      HINSTANCE resourceBackup;
      };

      You have to overload some methods to call the CONTEXT_DLL();
      like CDocument::OnCmdMsg CView::OnCmdMsg CMultiDocTemplate::LoadTemplate or before using CString::LoadString, CDialog::DoModal

      Reply
    • Very cool, but

      Posted by Legacy on 09/23/1999 12:00am

      Originally posted by: Joerg Preiss

      First tests seem to work, but I wanted to have a complete data editor with a list of items and a dialog box to edit and add items. If I have several dlls, the resources are not loaded correctly, I see in one view the dll resource of another dll. Also, I see a trace line that a dll is relocated because of a collision with another.
      The second thing: how can I connect to the menu bar inside such an extension dll?

      Reply
    • Separating the views of an MDI application into different DLLs

      Posted by Legacy on 08/28/1999 12:00am

      Originally posted by: Steve Sun

      Good idea, I love this and enjoy this code.
      Thank you.

      Reply
    • How to use SDI (Single Document, Multi View..)

      Posted by Legacy on 05/03/1999 12:00am

      Originally posted by: Sung Hoon, Cho

      How to use this methode for SDI (single document , Multi View..)

      View is CFormView....

      Let me know !!

      Reply
    • Use regular DLL?

      Posted by Legacy on 04/20/1999 12:00am

      Originally posted by: Vadim

      Any ideas how to do the same in regular DLL, so 'host' can be any MDI app, not only MFC app?

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

    Top White Papers and Webcasts

    • The impact of a data loss event can be significant. Real-time data is essential to remaining competitive. Many companies can no longer afford to rely on a truck arriving each day to take backup tapes offsite. For most companies, a cloud backup and recovery solution will eliminate, or significantly reduce, IT resources related to the mundane task of backup and allow your resources to be redeployed to more strategic projects. The cloud - can now be comfortable for you – with 100% recovery from anywhere all …

    • When it comes to desktops – physical or virtual – it's all about the applications. Cloud-hosted virtual desktops are growing fast because you get local data center-class security and 24x7 access with the complete personalization and flexibility of your own desktop. Organizations make five common mistakes when it comes to planning and implementing their application management strategy. This eBook tells you what they are and how to avoid them, and offers real-life case studies on customers who didn't let …

    Most Popular Programming Stories

    More for Developers

    Latest Developer Headlines

    RSS Feeds