Microsoft Knowledge Base Email Alertz

KBAlertz.com: (114376) - In the Microsoft Foundation Classes, version 2.0, CWnd::ExecuteDlgInit() incorrectly searches for dialog box resources only in the executing module.

Receive Microsoft Knowledge Base articles by E-Mail?

Every night we scan the Microsoft Knowledge Base. If technologies you're interested in are updated, we'll send you an e-mail. You only get one e-mail a day, and only when new articles are added.

Click here to create a
FREE account
Already have an account?
[Click here to Login]

Search KbAlertz

Advanced Search

Webmasters
Put kbAlertz on your website.
[ Click Here for more! ]





ASP.NET 3.5 Web Hosting with Windows 2008 and SQL 2008: Click Here!
Discount ASP.NET Hosting
ASP.NET 2.0 and 3.5
Windows2008 and SQL2008
US and UK Hosting
KBAlertz referrals get
** SIX MONTHS FREE **


Community Site



We Send hundreds of thousands of emails using ASP.NET Email


ASP.NET 3.5 Web Hosting with Windows 2008 and SQL 2008: Click Here!
Discount ASP.NET Hosting
ASP.NET 2.0 and 3.5
Windows2008 and SQL2008
US and UK Hosting
KBAlertz referrals get
** SIX MONTHS FREE **




Mentioned In








Microsoft Knowledge Base Article

This article contents is Microsoft Copyrighted material.
©2005-©2007 Microsoft Corporation. All rights reserved. Terms of Use | Trademarks




Article ID: 114376 - Last Review: November 21, 2006 - Revision: 2.1

FIX: CWnd::ExecuteDlgInit() Uses AfxGetInstanceHandle

This article was previously published under Q114376

SYMPTOMS

In the Microsoft Foundation Classes, version 2.0, CWnd::ExecuteDlgInit() incorrectly searches for dialog box resources only in the executing module.

CAUSE

In WINCORE.CPP, lines 1463 and 1464, CWnd::ExecuteDlgInit() attempts to find the specified resource using the following code:
    if ((hDlgInit = ::FindResource(AfxGetInstanceHandle(),
        lpszResourceName, RT_DLGINIT)) != NULL)
				
This forces the use of only those resources bound to the executing module. For localization and other uses, it must be possible to load resources from other sources.

RESOLUTION

This problem was fixed in the Microsoft Foundation Classes, version 2.5, which is supplied with Visual C++ for Windows, version 1.5. The fix involves defining AfxFindResourceHandle() to return the correct resource handle either by using AfxGetResourceHandle() for a single executable or by searching the list of CDynLinkLibrary objects for an application using the shared dynamic link library (DLL) version of the Microsoft Foundation Class library (compiling using _AFXDLL). This allows the application to switch between several sets of resources located in DLLs.

Applications maintain a list of the shared and extension DLLs using instances of the CDynLinkLibrary class. Each node in the list is an object of the CDynLinkLibrary class or of a class derived from the CDynLinkLibrary class. This object can also be used to hold private data for the DLL by deriving from CDynLinkLibrary and adding additional member variables. For an example of CDynLinkLibrary, please examine the Microsoft Foundation Class library DLLHUSK sample supplied with Visual C++, versions 1.0 and 1.5.

In a Microsoft Foundation Class application that does not use the shared DLL (MFC2xx.DLL), AfxFindResourceHandle() calls AfxGetResourceHandle(), which returns the current resource handle for the executable. In a Microsoft Foundation Class application that uses MFC2xx.DLL, AfxFindResourceHandle() traverses the CDynLinkLibrary object list of shared and extension DLLs, looking for the correct resource handle.

To get this behavior in a Microsoft Foundation Class library version 2.0 application, add the following function to the source module that contains the dialog box class code:
HINSTANCE ResourceInit(LPCSTR szResourceName,LPCSTR szResType)
{
    // first check the app
    HINSTANCE hInstApp = AfxGetResourceHandle();
    if (::FindResource(hInstApp, szResourceName,
          szResType) != NULL)
        return hInstApp;

    // check for DLLs in proper order
    CDynLinkLibrary* pDLL;
    for (pDLL = _AfxGetAppData()->pFirstDLL; pDLL != NULL;
         pDLL = pDLL->m_pNextDLL)
    {
        if (pDLL->m_hResource != NULL &&
            ::FindResource(pDLL->m_hResource,
              szResourceName, szResType) != NULL)
        {
            // found it in a DLL, use it's resource handle
            return pDLL->m_hResource;
        }
    }

    // if failed to find resource, fail initialization
    TRACE("\n Resource not found \n");
    return (HINSTANCE)NULL;
}
				
Make a call to this function in the CDialog derived class' override of OnInitDialog(). The ResourceInit() function will check the list of CDynLinkLibrary objects for the application and return the appropriate resource handle (or NULL if not found). The OnInitDialog() function may look like this:
BOOL CDerivedDlg::OnInitDialog()
{
    // attempt to find dialog box template
    HINSTANCE hResInst = ResourceInit(m_lpDialogTemplate, RT_DIALOG);
    if(NULL == hResInst) return FALSE;

    // get app's resource handle so we can set it back later
    HINSTANCE hAppInst = AfxGetResourceHandle();
    // temporarily set to DLL's resource handle
    AfxSetResourceHandle(hResInst);
    // Call base class which initializes the dialog
    // and loads the template
    BOOL bInit = CDialog::OnInitDialog();
    // restore the app's resource handle
    AfxSetResourceHandle(hAppInst);

    return bInit;
}
				
In addition, the resource handle must be set correctly before the call to DoModal(). The easiest way to do this is to:

  1. Call ResourceInit() from the constructor of the dialog box.
  2. Set the resource handle for the application appropriately.
  3. Reset it to the actual application resource handle when the dialog box is destroyed.
Here is an example of the constructor:
CDerivedDlg::CDerivedDlg(CWnd* pParent /*=NULL*/)
    : CDialog(CDerivedDlg::IDD, pParent)
{
    //{{AFX_DATA_INIT(CDerivedDlg)
    // NOTE: the ClassWizard will add member initialization here
    //}}AFX_DATA_INIT
    AfxSetResourceHandle(ResourceInit(m_lpDialogTemplate,RT_DIALOG));
}
				
Here is an example of the destructor:
CDerivedDlg::~CDerivedDlg()
{
    AfxSetResourceHandle(AfxGetApp()->m_hInstance);
    // reset resource to application's instance handle
}
				
The ResourceInit() function may be used at any point for any type of resource that may be located in a DLL or in the application's resources.

STATUS

Microsoft has confirmed this to be a problem in the Microsoft Foundation Classes, version 2.0. The problem was corrected in Microsoft Foundation Classes, version 2.5.

REFERENCES

kbNoUpdate

APPLIES TO
  • Microsoft Foundation Class Library 4.2, when used with:
    • Microsoft Visual C++ 1.0 Professional Edition
    • Microsoft Visual C++ 1.0 Professional Edition
Keywords: 
kbbug kbfix KB114376
Retired KB ArticleRetired KB Content Disclaimer
This article was written about products for which Microsoft no longer offers support. Therefore, this article is offered "as is" and will no longer be updated.
       

Community Feedback System

Very often, it takes hours to solve a problem. Very often, you've looked high and low, and have tried a lot of solutions. When you finally found it, chances are, it was because someone else helped you. Here's your chance to give back. Use our community feedback tool to let others know what worked for you and what didn't.

Please also understand that the community feedback system is not warranted to be correct, it's simply a system that we've built to let people try and help each other. If something in a feedback response doesn't make sense to you, or you're not comfortable making changes that the feedback talks about (like registry edits), please consult a professional.

Thank you for using kbAlertz.com Feedback System.

-- Scott Cate

Be the first to leave feedback, to help others about this knowledge base article.

(Optional) Name

(Optional) Public URL Or Email

Comments
No HTML -- Text Only Please