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

    More by Author

    Get the Free Newsletter!

    Subscribe to Developer Insider for top news, trends & analysis

    Must Read