Solved

Unable to load bitmaps from extension DLL

Posted on 1998-03-17
10
659 Views
Last Modified: 2012-08-14
I have created an MFC extension DLL in MSVC++ 5.0, which contains a few classes, dialogs, and bitmaps.  I have exported one of the classes, and this class calls another non-exported dialog in the dll.  The dialog works fine, but the buttons (which are supposed to be bitmap buttons) do not display their bitmaps.  The only time the bitmaps DO show up are when I define a bitmap resource with the same name in the .exe module.  How can I specify that I want to load the bitmaps from the DLL?

This is a sample of the code I use to attach the bitmap to the button:
      m_cOkButton.SetBitmap(::LoadBitmap(vInstance, MAKEINTRESOURCE(IDB_OK_BITMAP)));

This code worked fine before it was segregated into a DLL, and it works fine when the .EXE contains an IDB_OK_BITMAP resource.
0
Comment
Question by:DenMan
  • 5
  • 4
10 Comments
 
LVL 23

Expert Comment

by:chensu
ID: 1183550
What is vInstance? It should be the instance handle of the DLL, which you can get in DLLMain().

BTW, the application must call the DeleteObject function to delete each bitmap handle returned by the LoadBitmap function.
0
 

Author Comment

by:DenMan
ID: 1183551
vInstance is the HINSTANCE returned by AfxGetInstanceHandle(), which according to the docs should return an instance of the DLL (since it's called from within the DLL).

How would I get the instance handle from DLLMain()?  Should I set a member variable equal to that, so it can be passed to other classes (such as the one that's supposed to show the bitmaps)?
0
 

Expert Comment

by:jann
ID: 1183552
Try set vInstance (why don't you use hInstance) returned by AfxGetModuleHandle() instead by AfxGetInstanceHandle().
0
 

Author Comment

by:DenMan
ID: 1183553
AfxGetModuleHandle() is not a function that MSVC++ 5 recognizes.  At least, the compiler didn't recognize it and I couldn't find any references to it in the help files.

I actually have had success using AfxFindResourceHandle and searching for one of the bitmaps I know is in the DLL.  How can I load one of the DLL resources in the calling application?
0
 
LVL 23

Accepted Solution

by:
chensu earned 50 total points
ID: 1183554
I see. Have you ever read thru the following documentation? The HINSTANCE returned by AfxGetInstanceHandle() is not the instance handle of the DLL. You need to use AFX_MANAGE_STATE(AfxGetStaticModuleState( )); at the beginning of the functions.
BTW, the DLLMain() is hidden by MFC code.


For exported functions from a DLL, such as one that launches a dialog box in your DLL, you need to add the following code to the beginning of the function:




AFX_MANAGE_STATE(AfxGetStaticModuleState( ));
This swaps the current module state with the state returned from AfxGetStaticModuleState until the end of the current scope.

Problems with resources in DLLs will occur if the AFX_MODULE_STATE macro is not used. By default, MFC uses the resource handle of the main application to load the resource template. This template is actually stored in the DLL. The root cause is that MFC's module state information has not been switched by the AFX_MODULE_STATE macro. The resource handle is recovered from MFC's module state. Not switching the module state causes the wrong resource handle to be used.

AFX_MODULE_STATE does not need to be put in every function in the DLL. For example, InitInstance can be called by the MFC code in the application without AFX_MODULE_STATE because MFC automatically shifts the module state before InitInstance and then switches it back after InitInstance returns. The same is true for all message map handlers. Regular DLLs actually have a special master window procedure that automatically switches the module state before routing any message.

0
Enabling OSINT in Activity Based Intelligence

Activity based intelligence (ABI) requires access to all available sources of data. Recorded Future allows analysts to observe structured data on the open, deep, and dark web.

 

Author Comment

by:DenMan
ID: 1183555
I am exporting entire classes, not specific functions.  Do I need to put the AFX_MANAGE_STATE in each function of the class?  Also, the dialog that I was having the most trouble with is not called from outside the DLL -- it is called by one of the functions in another class that IS exported.  It should be retrieving everything internally, I would think, but it tries to look in the .exe module's resources instead of its own.

I tried putting AFX_MANAGE_STATE into the InitDialog() of the internal dialog that I have been having trouble with, and got a number of compiler errors about how "DllMain was already defined in xxxx.obj".

I have had no trouble with exporting other dialogs, even though I am not using AFX_MANAGE STATE.  Is that because this is an Extension DLL as opposed to a regular DLL?
0
 
LVL 23

Expert Comment

by:chensu
ID: 1183556
Forget it.

Since it is an MFC extension DLL, the initilization should look like this:

/////////////////////////////////////////////////////////////////////////////
// Initialization of MFC Extension DLL

#include "afxdllx.h"    // standard MFC Extension DLL routines

static AFX_EXTENSION_MODULE NEAR extensionDLL = { NULL, NULL };

extern "C" int APIENTRY
DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved)
{
      if (dwReason == DLL_PROCESS_ATTACH)
      {
            // Extension DLL one-time initialization - do not allocate memory here,
            //   use the TRACE or ASSERT macros or call MessageBox
            if (!AfxInitExtensionModule(extensionDLL, hInstance))
                  return 0;

            // Other initialization could be done here, as long as
            // it doesn't result in direct or indirect calls to AfxGetApp.
            // This extension DLL doesn't need to access the app object
            // but to be consistent with testdll1.dll, this DLL requires
            // explicit initialization as well (see below).

            // This allows for greater flexibility later in development.
      }
      return 1;   // ok
}


So, you can do this,

vInstance = extensionDLL.hModule;
m_cOkButton.SetBitmap(::LoadBitmap(vInstance, MAKEINTRESOURCE(IDB_OK_BITMAP)));

0
 

Author Comment

by:DenMan
ID: 1183557
Since the SetBitmap() function is in a different source file than the DllMain function (and the AFX_EXTENSION_ MODULE extensionDLL declaration), it doesn't recognize the reference to extensionDLL.  Should I put the AFX_EXTENSION_ MODULE in a common header file instead?

Thanks for all your help!
0
 
LVL 23

Expert Comment

by:chensu
ID: 1183558
Remove the "static" keyword before AFX_EXTENSION_MODULE and declare "extern AFX_EXTENSION_MODULE extensionDLL;" in other source files before you use it.

I didn't receive any notification when you added this comment. Until today, I received the notification of "Good answer". Is it too late?
0
 

Author Comment

by:DenMan
ID: 1183559
Nope, I got your response.  Thanks!  I'll give it a shot.
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

Article by: SunnyDark
This article's goal is to present you with an easy to use XML wrapper for C++ and also present some interesting techniques that you might use with MS C++. The reason I built this class is to ease the pain of using XML files with C++, since there is…
Many modern programming languages support the concept of a property -- a class member that combines characteristics of both a data member and a method.  These are sometimes called "smart fields" because you can add logic that is applied automaticall…
The viewer will learn how to use the return statement in functions in C++. The video will also teach the user how to pass data to a function and have the function return data back for further processing.
The viewer will learn how to clear a vector as well as how to detect empty vectors in C++.

743 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

8 Experts available now in Live!

Get 1:1 Help Now