Load a CString from DLL within that DLL





4.00/5 (1 vote)
Aug 9, 2000

89262
CString::LoadString(), resource will not load under certain conditions.
Introduction
While we were designing the plugin architecture for epAssist, we discovered an interesting problem with the MFC implementation of CString::LoadString()
. The string resource will not load under certain conditions.
Our plugin architecture is basically re-named DLLs with a standardized interface where the plugins provide a dictionary, grammar, and actions for the main language parser to parse sentences. On a successful parsing match, the program will invoke the proper action.
The main application loads the plugins (DLLs) using LoadLibrary
, then locates and calls a function to get the description, copyright, and so forth.
The Problem
All the plugins are created with a Visual Studio AppWizard. Resources are already in place with strings for description, copyright, etc. Thus, every plugin has the same ID for the string.
CString::LoadString
will first use the instance handle of the main application to search for a string with the given ID. Failing that, it will look in DLLs in the order they were loaded until there is a match.
If DLL A is loaded, then B and C, calling LoadString
from DLL C will first find a matching resource in DLL A before finding its own resource.
The end result of this is that all plugins show the same description and other properties.
The Solution
The function LoadStringFromDLL()
was created. It takes an instance handle (can be the main application, any DLL, or any other application) and the resource ID.
Using this as a starting point, you can also create LoadIconFromDLL
, or any other resource type.
There is an artificial limit of 255 characters for the string resource. You can change the memory allocation scheme to suit your own needs.
// Load a resource from a given instance #pragma once #ifndef RESOURCE_TO_CSTRING #define RESOURCE_TO_CSTRING // Comments Doxygen compatible /** Load a resource from a given instance * It seems that if you are in a DLL, the standard MFC checks the instance of the App, then each DLL in the order loaded. This is no good if someone else is using the same ID! * @param hInst the instance to load from * @param ids the id to load. * @ingroup global */ inline CString LoadStringFromDLL(HINSTANCE hInst, int ids) { // (c) 1998-2000 Golden Crater Software, All rights reserved. // You may freely use this code // You may freely redistribute this code, provided this comment block remains // intact. // The body of this function is from the epAssist EAX SDK: // Use plain English to control your PC over email, AppBar, and soon // voice telephone. // Check out this free SDK that allows you to interface to epAssist. // Easily add natural language functionality to your application and // provide your users with access to your program from anywhere they // can send and receive email (2-way pagers, public terminals and email // enabled telephones included.) MFC AppWizard and HTML Help, and sample // source included. http://www.goldencrater.com/software if (!hInst) { ASSERT(0); return "Error loading resource."; } CString str; TCHAR szTemp[256]; // Raise limit of 255 char if needed. int nLen; LPCTSTR lpszName = MAKEINTRESOURCE((ids>>4)+1); if (::FindResource(hInst, lpszName, RT_STRING) != NULL && (nLen = ::LoadString(hInst, ids, szTemp, 255) != 0)) { str = szTemp; } return str; } #endif