65.9K
CodeProject is changing. Read more.
Home

How to find a doctemplate object given its resource identifier

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.94/5 (11 votes)

Oct 30, 2003

2 min read

viewsIcon

54648

downloadIcon

593

A useful function to find the doctemplate object by its numeric resource identifier in a MFC application.

Introduction

I have developed some very large applications, with tens of different doctemplate objects. Sometimes in my applications one view must respond to the user selection by opening another document of a different template. Thanks to the CWinApp member functions, we can search among all doctemplates and their open documents but how can we recognize a particular doctemplate?

We could check a string against the string returned by the GetDocString member function of CDocTemplate, but strings may change during the development of the application. The CDocTemplate class has a member variable named m_nIDResource which contains the numeric resource identifier passed to the constructor when the doctemplate object is created. This identifier is used for loading the doctemplate string from the resource, but also for the default menu associated to those documents and the default icon of the frame of the documents. The application knows well the resource identifiers, so they would be perfect for identifying the doctemplates, but the base class CDocTemplate declares the member variable m_nIDResource as protected and does not have any member function to get the value read.

With a little C++ trick, we can extract the desired member variable without being constricted to use a custom CDocTemplate derived class for our doctemplates.

The function(s)

UINT AfxGetDocTemplateId(CDocTemplate* pDocTemplate)
{
    // Helper class to extract the m_nIDResource member
    class CHelperDocTemplate : public CDocTemplate
    {
    public:
        CHelperDocTemplate():CDocTemplate(0, NULL, NULL, NULL){}
        UINT GetResourceId(){return m_nIDResource;}
    };
    return  ((CHelperDocTemplate*)pDocTemplate)->GetResourceId();
}


CDocTemplate* AfxFindDocTemplate(UINT nIDResource)
{
    POSITION pos = AfxGetApp()->GetFirstDocTemplatePosition();
    while ( pos )
    {
        CDocTemplate* pDocTemplate = AfxGetApp()->GetNextDocTemplate(pos);
        if ( AfxGetDocTemplateId(pDocTemplate) == nIDResource )
            return pDocTemplate;
    }
    return NULL; // Not found
}

Notice that the helper class is declared in the function body, i.e. it is a local class. In this way, it does not clutter the namespace of the application. The helper class must declare a constructor because CDocTemplate does not have a default constructor. Finally a static member function in the class cannot access the protected member variables of the base class, so a non static member function and the cast are needed.

Using the code

I named the function like the MFC global functions because it really is a little function which is missing from MFC ones. Because it is a global function, you can use it anywhere in the program, just include the header file and add the implementation file to the project. I usually include such a header at the end of the StdAfx.h file and don't think to it anymore.

So just grab it and mail me know if you appreciated it!

History

  • Submitted 29 October 2003