Solved

Dynamic Docuemnt Templates in MDI

Posted on 1999-01-17
16
220 Views
Last Modified: 2013-11-20
I'm writing an MFC app that can handle a number of different file types.

I want the user to be able to decide which file formats they want to use.

The easiest way I thought of doing this is to place each document template and view document classes in separate DLLs, like a sort of MFC extension DLL, and the user can place the ones they require in the app directory.

Doing it this way means that the DLLs can't be linked to the app when it is compiled as the DLLs that will be used aren't know at this time.

Is this the best way of doing it and is it possible?

Thanks

Gavin Rouse
0
Comment
Question by:gav061697
  • 9
  • 7
16 Comments
 
LVL 86

Accepted Solution

by:
jkr earned 100 total points
Comment Utility
It is possible. I'm not sure whether it is the best way, but it's at least a good one.
>>Doing it this way means that the DLLs can't be linked to the
>>app when it is compiled as the DLLs that will be used aren't
>>know at this time.
As 'CMultiDocTemplate' is always known, you can do it this way:
Implement a function in the DLL that does the following:

__declspec (dllexport)
CMultiDocTemplate* DllGetDocTemplate()
{
      CMultiDocTemplate* pTemplate;
      pOeTemplate = new CMultiDocTemplate(
            IDR_MYTEMPLATE,
            RUNTIME_CLASS(CMyTemplate),
            RUNTIME_CLASS(CChildFrame), // custom MDI child frame
            RUNTIME_CLASS(CMyTemplatesView));

return ( pTemplate);
}

0
 
LVL 86

Expert Comment

by:jkr
Comment Utility
Ooops, i forgot about the apllication's part:

typedef CMultiDocTemplate* ( *PDLLGETDOCTEMPLATE)();
HANDLE hDll = LoadLibrary( "mydoctpl.dll");
PDLLGETDOCTEMPLATE pGetTemplate = (PDLLGETDOCTEMPLATE) GetProcAddress( hDll, "DllGetDocTemplate);

CMultiDocTemplate* pTemplate = (pGetTemplate)();

      AddDocTemplate(pTemplate);

      // Connect the COleTemplateServer to the document template.
      //  The COleTemplateServer creates new documents on behalf
      //  of requesting OLE containers by using information
      //  specified in the document template.

      m_server.ConnectTemplate( clsid, pTemplate, FALSE);


0
 
LVL 86

Expert Comment

by:jkr
Comment Utility
OK - i just noticed that there are several tasks to do (e.g. using a .def file so that 'DllGetDocTemplate()' is exported using the correct name and a function that retrieves the DLL's clsid from the DLL), so feel free to ask if you have further qestions regarding this issue...
0
 

Author Comment

by:gav061697
Comment Utility
There's actually a MFC example which I found in the help files called DLLHusk which does exactly what I want in the same way that you described.

However, my version works fine in Debug mode, but when I try the Release version my program crashes in the InitDLL function at the AddDocTemplate call (see the DLLHusk example if you're not sure what I mean).  The only difference with my code is that the classes are in separte files rather than all in one.

Do you know what might cause the problem.

My first thought was that the GetProcAddress() call was returning the wrong address as the crash seemed to occur in the RichEditCtrl source file.  However, I mangaed to partly debug my code and it gets to the AddDocTemplate call then goes to two source files which it shouldn't (BarDock.cpp and the RichEdit source file)

I can provide the source code if you want it.
0
 
LVL 86

Expert Comment

by:jkr
Comment Utility
I assume that there are problems regarding the runtime class information - if you could provide some source code, this could be a great help ;-)
0
 
LVL 86

Expert Comment

by:jkr
Comment Utility
Hmm - your DLL is created as a MFC extension DLL, isn't it?
0
 

Author Comment

by:gav061697
Comment Utility
How should I give it to you?

>> Hmm - your DLL is created as a MFC extension DLL, isn't it?
Yes
0
 

Author Comment

by:gav061697
Comment Utility
How should I give it to you?

>> Hmm - your DLL is created as a MFC extension DLL, isn't it?
Yes
0
IT, Stop Being Called Into Every Meeting

Highfive is so simple that setting up every meeting room takes just minutes and every employee will be able to start or join a call from any room with ease. Never be called into a meeting just to get it started again. This is how video conferencing should work!

 
LVL 86

Expert Comment

by:jkr
Comment Utility
The best thing would be if you post the relevant parts...
0
 

Author Comment

by:gav061697
Comment Utility
Here's my InitDLL() function

// Exported DLL initialization is run in context of running application
extern "C" void WINAPI InitDLL()
{
      TRACE0("DOCVIEW.DLL: InitDLL()\n");

      // create a new CDynLinkLibrary for this app
      new CDynLinkLibrary(DocViewDLL);

      // Register the doc templates we provide to the app
      CWinApp* pApp = AfxGetApp();
      ASSERT(pApp != NULL);

      /* Release crashes here */
      pApp->AddDocTemplate(new CMultiDocTemplate(IDR_VCTYPE,
                  RUNTIME_CLASS(CVCDoc),
                  RUNTIME_CLASS(CMDIChildWnd),
                  RUNTIME_CLASS(CVCView)));
      // add other initialization here
}
0
 
LVL 86

Expert Comment

by:jkr
Comment Utility
Hmm, seems fine at first glance... Is the app also a release version?
0
 
LVL 86

Expert Comment

by:jkr
Comment Utility
I'd suggest
CMultiDocTemplate* pTempl= CMultiDocTemplate(IDR_VCTYPE,
RUNTIME_CLASS(CVCDoc),
RUNTIME_CLASS(CMDIChildWnd),
RUNTIME_CLASS(CVCView));

if ( !pTempl) AfxMessageBox( ...);

pApp->AddDocTemplate( pTempl);

to find out whether the problem is related to the template or the call...
0
 

Author Comment

by:gav061697
Comment Utility
I think i've found the problem...in the release version pApp == NULL

I don't know why...i'll try and look into it further...if you have any ideas let me know

Thanks
0
 
LVL 86

Expert Comment

by:jkr
Comment Utility
The most common reason for this: Is the app also a release version? If not, you might want to test it using a release version of the application, as mixing debug/release usually leads into trouble...
0
 

Author Comment

by:gav061697
Comment Utility
i'll try that..

thiscode  may/may not help...it's how I load and call the InitDLL() function:

HINSTANCE hInstance = AfxLoadLibrary("docview\\release\\docview.dll");
FARPROC farproc = GetProcAddress( hInstance, "InitDLL" );
if(farproc != NULL)
     farproc();
else
     AfxMessageBox("Can't find InitDLL() function.");

0
 

Author Comment

by:gav061697
Comment Utility
just tried it...works fine now...how annoying...thanks for your help..

have some points :-)
0

Featured Post

What Should I Do With This Threat Intelligence?

Are you wondering if you actually need threat intelligence? The answer is yes. We explain the basics for creating useful threat intelligence.

Join & Write a Comment

Introduction: Hints for the grid button.  Nested classes, templated collections.  Squash that darned bug! Continuing from the sixth article about sudoku.   Open the project in visual studio. First we will finish with the SUD_SETVALUE messa…
Introduction: Dialogs (1) modal - maintaining the database. Continuing from the ninth article about sudoku.   You might have heard of modal and modeless dialogs.  Here with this Sudoku application will we use one of each type: a modal dialog …
This video will show you how to get GIT to work in Eclipse.   It will walk you through how to install the EGit plugin in eclipse and how to checkout an existing repository.
This demo shows you how to set up the containerized NetScaler CPX with NetScaler Management and Analytics System in a non-routable Mesos/Marathon environment for use with Micro-Services applications.

763 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

7 Experts available now in Live!

Get 1:1 Help Now