Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people, just like you, are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
Solved

Unable to load bitmaps from extension DLL

Posted on 1998-03-17
10
673 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
Free Tool: Port Scanner

Check which ports are open to the outside world. Helps make sure that your firewall rules are working as intended.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

 

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
 

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

Free Tool: ZipGrep

ZipGrep is a utility that can list and search zip (.war, .ear, .jar, etc) archives for text patterns, without the need to extract the archive's contents.

One of a set of tools we're offering as a way to say thank you for being a part of the community.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

Title # Comments Views Activity
Getting IP address 8 89
Unable to start eclipse ? 17 153
c++ reading data from file into two dimensional array 3 117
show out valin of json for debugging in visaul c++ 1 41
Introduction This article is the first in a series of articles about the C/C++ Visual Studio Express debugger.  It provides a quick start guide in using the debugger. Part 2 focuses on additional topics in breakpoints.  Lastly, Part 3 focuses on th…
Go is an acronym of golang, is a programming language developed Google in 2007. Go is a new language that is mostly in the C family, with significant input from Pascal/Modula/Oberon family. Hence Go arisen as low-level language with fast compilation…
The viewer will learn how to user default arguments when defining functions. This method of defining functions will be contrasted with the non-default-argument of defining functions.
The viewer will learn additional member functions of the vector class. Specifically, the capacity and swap member functions will be introduced.

856 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