MFC .DLL TUTORIAL, PART 3

Environment: Visual C++

In part 1 of this series, I covered what types of .DLLs you can make with MFC and how to build MFC regular and extension .DLLs. In part 2, I covered potential problems that can arise when you use .DLLs and suggested several ways to avoid them. In this article, I'll build upon the first two articles by providing more coding examples and technical details.

Exporting Resources From a .DLL

You may wish to create a .DLL which exports resources such as dialog templates, bitmaps, icons or strings. You may, for example, wish to make your application multilingual, with one .DLL for English strings and dialog templates, another with Spanish strings, etc. Exporting resources is relatively easy to do.

Your first step in building a .DLL which exports resources is (of course) to build a .DLL and give it some resources. You can use a regular or extension .DLL. Use the App Wizard to create your .DLL, as described in Article 1. To add a resource using the Visual C++ menu, select "Insert" and "Resource" and then select the type of resource you wish to add.

Once you've built your .DLL and given it all the resources it is to import, you must build a header file to be used by the client application. You can add a new header file using the Visual C++ menu by selecting "File | Add To Project | New | C/C++ Header File." Now open your .DLL's Resource.h file. Assuming you have compiled your .DLL, the top of this file will look something like this:

#define IDS_SOME_STRING1                1
#define IDS_SOME_STRING2                2
#define IDS_SOME_STRING3                3
#define IDD_SOME_DIALOG                 11000
#define IDB_SOME_BITMAP                 11001

As you can see, each of these #defines gives one of your resources an identifying integer value. Copy the complete #define for each resource you wish to export into your newly created header file.

At this point, your .DLL is almost ready to go. Only one more step is required. In articles 1 and 2, I demonstrated how to use a .DLL with implicit linking. When you are using implicit linking, the client application will attempt to connect to your .DLL automatically. If it cannot do so, the client application won't run. When you use implicit linking, it is important to remember that the client application will not attempt to connect to your .DLL unless your .DLL exports at least one class or function which is used by the client. So even if your .DLL's only purpose is to provide resources, you still must export at least one function or class which is used by the client. It doesn't matter whether your exported class or function does anything useful. It simply has to be there in order to force the client to connect to the .DLL. So all that's left to make your .DLL complete is to export a "do-nothing" function. See Article 1 for an explanation of how to export a function.

Setting Up the Client Application

Article 1 describes how to build a client application which will connect to your .DLL. Remember, your client application must actually call at least one function from your .DLL or create at least one instance of an imported class. If not, your client application will not automatically connect to your .DLL at runtime. Be sure to add a copy of the header file you created earlier to your client application project.

In some respects, an extension .DLL is easier to use when you are importing resources. This is because an extension .DLL will try to find a resource in your .DLL if it cannot find it in its own resources. Suppose your client application included the following code:

CString str;
str.LoadString(IDS_SOME_STRING1);
AfxMessageBox(str);

The first thing your client application will do is look for a definition of IDS_SOME_STRING1. Suppose the header file you imported defines IDS_SOME_STRING1 as 1. The client application will look in its own resources for resource #1. If it cannot find resource #1 in its own resources, it will next look in the extension .DLL. If you built a regular .DLL, the client application won't take this extra step.

Note that there is a big potential for problems here. If your client application has some other resource which is also defined as resource 1, it will attempt to load its own resource. The client only looks to your extension .DLL if it can't find the properly numbered resource within its own resources. One way to avoid this problem is to renumber your resources to avoid conflicts.

When you use a regular .DLL, the client application must be told explicitly to look to the .DLL to find the resource. Here's how you do it:

//Store the current resource handle
HINSTANCE hClientResources = AfxGetResourceHandle();

//Tell the client to use the .DLL's resources
AfxSetResourceHandle(::GetModuleHandle("SomeDll.dll"));

//Do something with the .DLL's resources
CString str;
strRes.LoadString(IDS_SOME_STRING1);

//Restore the client application resource handle
AfxSetResourceHandle(hClientResources);

You can use this technique in your client application even if you are using an extension .DLL. With a regular .DLL it is necessary. While not absolutely necessary with an extension .DLL, it gives you the certainty that the right resources will be loaded.

Exporting a CDialog Based Class

Exporting a class derived from the CDialog class is only slightly more complicated than exporting other classes. The extra complication comes from the fact that you must also export the dialog template, which is a resource.

When you export a class, you must provide a copy of the class header file to be used by the client application. When you export a class derived from CDialog, which has a resource, you must also export the #define for the resource ID. So the easiest thing to do is simply tack the #define onto the top of the header file like this:

#ifndef IDD_HELLO_DIALOG
     #define IDD_SOME_DIALOG      9000
#endif

As with other exported resources, you can run into problems if the client application also has a resource with the same number. Either be careful to avoid conflicts, or use the code shown above to tell the client application explicitly where to find the correct resource.

Note that the same technique used with CDialog bases classes can also be used with any other class you wish to export which uses resources. Be sure to define the resources in the header file you provide for the client application, and take whatever steps are necessary to avoid conflicts.



Comments

  • How to pass string parameter when calling a function of a dll in VB?

    Posted by zhs1987 on 02/28/2006 12:54am

    I made a Dll using VC++ (MFC App wizard,regular Dll using shared MFC dll). In my project, I declared a function like this 
        void WINAPI Myfunc(LPCTSTR para);
    as an exported function. And in the .def file, I added
         	Myfunc		@1
    The function Myfunc is called OK by other cpp programs. But when I called it in my VB program, passing a String parameter, it didn't run as expected. 
    
    I made the declaration in this way
      Declare Function Myfunc Lib "TestDll.dll" (ByVal uri As String)
    (and in some other ways). It could run, but I found the parameter para become an empty string. Could you tell me what happened. How should I declare in VB?
    
    Thank you very much in advance.

    Reply
  • i am unable to load resource from dll

    Posted by rkr.koti on 12/26/2005 07:30am

    hi, i have created a dll, where in this i have stored jpeg images with custom resource type as "BINARY". i have stored the jpg images. But when i used in the client appplication, i am unable to find resource. i have use FindResource(::LoadLibrary("testdll.dll"),MAKEINTRESOURCE(504),"JPEG"); here 504 is the resource ID of that jpg image But, i am unable to get the resource. Plz instruct how can i get it.

    Reply
  • Doesn't work for dialogs with not common MFC controls

    Posted by Legacy on 02/07/2004 12:00am

    Originally posted by: Vladimir

    When in dialog used any User Control.
    
    For example MFCGridCtrl control from this site => dll created, but dialog will not created correctly in main application.
    Tried to include all sources of control to dll, but the same result.
    Any ideas how to export such type of resouce dll correctly?

    Reply
  • Exporting an 'imported function'??

    Posted by Legacy on 03/25/2003 12:00am

    Originally posted by: urge

    Hi there,
    Thanks for great lesson. I think this will be a great help to me.
    But, can you please say, how can a DLL export a function imported from static-link library? with the same name??

    I tried, but has link-error. Can you show me any solutions for this?

    e.g. there's a function func() in static-link library, and application's using DLL which's linking the static-link library..


    [Application]

    [DLL]

    [Static-link library]
    func()

    Thanks in advance.. =)

    Reply
Leave a Comment
  • Your email address will not be published. All fields are required.

Top White Papers and Webcasts

  • Live Event Date: December 11, 2014 @ 1:00 p.m. ET / 10:00 a.m. PT Market pressures to move more quickly and develop innovative applications are forcing organizations to rethink how they develop and release applications. The combination of public clouds and physical back-end infrastructures are a means to get applications out faster. However, these hybrid solutions complicate DevOps adoption, with application delivery pipelines that span across complex hybrid cloud and non-cloud environments. Check out this …

  • CentreCorp is a fully integrated and diversified property management and real estate service company, specializing in the "shopping center" segment, and is one of the premier retail service providers in North America. Company executives travel a great deal, carrying a number of traveling laptops with critical current business data, and no easy way to back up to the network outside the office. Read this case study to learn how CentreCorp implemented a suite of business continuity services that included …

Most Popular Programming Stories

More for Developers

RSS Feeds