ActiveX Control using MFC Extension DLL

I created an ActiveX Control using the ActiveX Control wizard.  The control uses a MFC Extension DLL that works with .EXE applications just fine, and has been deployed at customer sites for several months.

The Extension DLL contains several classes that have member functions that return CStrings from the DLLs local stringtable resources.  It uses the CString::LoadString() function.  This works fine with the .EXE applications, but the ActiveX control does not find the strings in its search through its CDynLinkLibrary chain.

The Extension DLL framework was built by the Extension DLL wizard.  I am using VC++ 5.0

It appears that the ActiveX Control OCX is implemented like an Extension DLL and "wires" itself into the chain.

My question is:  Why don't the DLL functions find their own resources AND what can be done to correct this?

Modifying the Extension DLL, except to try some things out for debugging, is not a viable option.

Thank you
LVL 1
rhgaracciAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

galkinCommented:
First MFC ActiveX controls are implemented as shared DLL not as extension DLL. It is because ActiveX control exports 4 functions to be called by either OLE (DllGetClassObject, DllCanUnloadNow) or by utility(DllRegisterServer, DllUnregisterServer) which are not MFC applications. Extension DLL can be used only with MFC EXE. So ActiveX control doesn't insert itself into resources chain. Since ActiveX control is shared DLL it has its own CWinApp static instance and has its own internal MFC state, like global map of windows handles and objects, resource handle etc.
To allow control to load string from another dll you must supply handle of this DLL for example add hidden property and set it with the handle.
0
rhgaracciAuthor Commented:
Actually, I figured out the correct answer.  I found the solution in Knowledge Base Article Q154126.  I modified my extension dll to use the two-step initialization as described in the article (search for words "more recommended" for a description) and called the exported initialization function in the ActiveX control app initialization.  This put the extension dll properly in the chain.

Thanks for the reply anyway.

No further responses are requested.
0
dkremerCommented:
Hi, I had the same problem, here's the solution I'm using :
Create a new header file, and copy the following :

#ifndef __InstanceSwitcher_h__
#define __InstanceSwitcher_h__

/*
** *********************
** * CInstanceSwitcher *
** *********************
*/

class CInstanceSwitcher
{
public:
      CInstanceSwitcher();
      ~CInstanceSwitcher();

      static HINSTANCE m_hInstance;

private:
      HINSTANCE m_Temp;
};

#endif

Create a new cpp file and copy the following :
/*
** *********************
** * CInstanceSwitcher *
** *********************
*/

#include "StdAfx.h"
#include "InstanceSwitcher.h"

/*
** *********************
** * CInstanceSwitcher *
** *********************
*/

HINSTANCE CInstanceSwitcher::m_hInstance = NULL;

CInstanceSwitcher::CInstanceSwitcher()
{
      if(CInstanceSwitcher::m_hInstance)
      {
            m_Temp = AfxGetResourceHandle();
            AfxSetResourceHandle(m_hInstance);
      }
}

CInstanceSwitcher::~CInstanceSwitcher()
{
      if(CInstanceSwitcher::m_hInstance)
      {
            AfxSetResourceHandle(m_Temp);
      }
}

In the main file of the extention library add the following to DllMain:
extern "C" int APIENTRY
DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved)
{
      // Remove this if you use lpReserved
      UNREFERENCED_PARAMETER(lpReserved);

      if (dwReason == DLL_PROCESS_ATTACH)
      {
            TRACE0("APP8MFC.DLL Initializing!\n");
            
            // Extension DLL one-time initialization
            if (!AfxInitExtensionModule(App8MFCDLL, hInstance))
                  return 0;

            CInstanceSwitcher::m_hInstance = hInstance;
      }
      else if (dwReason == DLL_PROCESS_DETACH)
      {
            TRACE0("APP8MFC.DLL Terminating!\n");
            // Terminate the library before destructors are called
            AfxTermExtensionModule(App8MFCDLL);
      }
      return 1;   // ok
}

Ok, how you use it : Wherever you need (in your extention DLL ofcourse) to use any of it's local resources you just construct a CInstanceSwitcher in your function and voila - it's using the DLLs resources :)

Hope it works for you, it does for me :)

  Bye,
    - DKremer

0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Microsoft Development

From novice to tech pro — start learning today.