| Tenouk C++ & C | MFC Home | C++, MFC & DLL 1 | C++, MFC & DLL 3 | Download | Site Index |


 

 

 

 

 

 

 

Module 16a:

Windows Dynamic Link Libraries - DLL 2

 

 

 

 

 

 

 

 

This is a continuation from the previous module... Program examples compiled using Visual C++ 6.0 (MFC 6.0) compiler on Windows XP Pro machine with Service Pack 2. Topics and sub topics for this Tutorial are listed below. If you think the terms used in this DLL tutorial quite blur, you can try studying the Win32 DLL first.

  1. Updating the MYMFC22B Example: Adding Code to Test mymfc22C.dll

  2. A Custom Control DLL

  3. What Is a Custom Control?

  4. A Custom Control's Window Class

  5. The MFC Library and the WndProc() Function

  6. Custom Control Notification Messages

  7. User-Defined Messages Sent to the Control

  8. The MYMFC22D Example: A Custom Control

  9. Revising the Updated MYMFC22B Example: Adding Code to Test mymfc22D.dll

 

 

The MYMFC22B Project Example: A DLL Test Client Program

 

This example starts off as a client for mymfc22A.dll. It imports the CPersistentFrame class from the DLL and uses it as a base class for the SDI frame window. Later you'll add code to load and test the other sample DLLs in this module. Here are the steps for building the MYMFC22B example:

 

Run AppWizard to produce \mfcproject\mymfc22B. This is an ordinary MFC EXE program. Select Single Document. Otherwise, accept the default settings. Be absolutely sure that in Step 5 you accept the As A Shared DLL option.

 

AppWizard step 5 of 6, selecting As a shared DLL option.

 

Figure 10: AppWizard step 5 of 6, selecting As a shared DLL option.

 

MYMFC22A SDI project summary.

 

Figure 11: MYMFC22A SDI project summary.

 

Copy the file persist.h from the \mfcproject\mymfc22A directory to \mfcproject\mymfc22B. Note that you're copying the header file, not the source file, persist.cpp.

 

Copying the Persist.h header file from the MYMFC22A project directory.

 

Figure 12: Copying the Persist.h header file from the MYMFC22A project directory.

 

To \mymfc22B directory.

 

The MYMFC22B project directory.

 

Figure 13: The MYMFC22B project directory.

 

Also insert the following line into MainFrm.h:

 

#include "persist.h"

 

MFC Visual C++ code segment

 

Listing 2.

 

Change the CFrameWnd base class to CPersistentFrame as you did in MYMFC14. Replace all occurrences of CFrameWnd with CPersistentFrame in both MainFrm.h and MainFrm.cpp.

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Using the find and replace menu.

 

Figure 14: Invoking the find and replace menu.

 

Replacing all the CFrameWnd with CPersistentFrame in MainFrm.h and MainFrm.cpp files.

 

Figure 15: Replacing all the CFrameWnd with CPersistentFrame in MainFrm.h and MainFrm.cpp files.

 

Add the mymfc22A import library to the linker's input library list. Choose Settings from Visual C++'s Project menu. Select All Configurations in the Settings For drop-down list. Then fill in the Object/Library Modules control on the Link page as shown below.

You must specify the full pathname for the mymfc22A.lib file unless you have a copy of that file in your project directory.

 

Adding the mymfc22A.lib (import) library to the linker's input library list.

 

Figure 16: Adding the mymfc22A.lib (import) library to the linker's input library list.

 

Build and test the MYMFC22B program. If you run the program from the debugger and Windows can't find the mymfc22A.dll, Windows displays a message box when MYMFC22B starts. If all goes well, you should have a persistent frame application that works exactly like the one in EX15A. The only difference is that the CPersistentFrame code (Persist.h and Persist.cpp) is in an extension DLL.

 

MYMFC22B program output, using the CPersistentFrame class through the DLL.

 

Figure 17: MYMFC22B program output, using the CPersistentFrame class through the DLL.

 

 

MFC Regular DLLs: The CWinApp Derived Class

 

When AppWizard generates a regular DLL, the DllMain() function is inside the framework and you end up with a class derived from CWinApp (and a global object of that class), just as you would with an EXE program. You can get control by overriding CWinApp::InitInstance and CWinApp::ExitInstance. Most of the time, you don't bother overriding those functions, though. You simply write the C functions and then export them with the __declspec(dllexport) modifier (or with entries in the project's DEF file).

 

Using the AFX_MANAGE_STATE Macro

 

When mfc42.dll is loaded as part of a process, it stores data in some truly global variables. If you call MFC functions from an MFC program or extension DLL, mfc42.dll knows how to set these global variables on behalf of the calling process. If you call into mfc42.dll from a regular MFC DLL, however, the global variables are not synchronized and the effects will be unpredictable. To solve this problem, insert the line:

 

AFX_MANAGE_STATE(AfxGetStaticModuleState());

 

at the start of all exported functions in your regular DLL. If the MFC code is statically linked, the macro will have no effect.

 

The MFC Regular DLL Resource Search Sequence

 

When an EXE links to a regular DLL, resource loading functions inside the EXE will load the EXE's own resources. Resource loading functions inside the regular DLL will load the DLL's own resources. If you want your EXE code to load resources from the DLL, you can use AfxSetResourceHandle to temporarily change the resource handle. The code will be nearly the same as that shown in "The MFC Extension DLL Resource Search Sequence" topic. If you're writing an application that needs to be localized, you can put language-specific strings, dialogs, menus, and so forth in an MFC regular DLL. You might, for example, include the modules English.dll, German.dll, and French.dll. Your client program would explicitly load the correct DLL and use code such as that in "The MFC Extension DLL Resource Search Sequence" topic to load the resources, which would have the same IDs in all the DLLs.

 

The MYMFC22C Example: An MFC Regular DLL

 

This example creates a regular DLL that exports a single square root function. First you'll build the mymfc22C.dll file, and then you'll modify the test client program, MYMFC22B, to test the new DLL.

 

Here are the steps for building the MYMFC22C example:

 

Run AppWizard to produce \mfcproject\mymfc22C. Proceed as you did for MYMFC22A, but accept Regular DLL Using Shared MFC DLL (instead of choosing MFC Extension DLL) from the one and only AppWizard page.

 

MYMFC22C, new DLL project dialog.

 

Figure 18: MYMFC22C, new DLL project dialog.

 

The only step 1 of 1 AppWizard for MYMFC22C, a Regular DLL using shared MFC DLL.

 

Figure 19: The only step 1 of 1 AppWizard for MYMFC22C, a Regular DLL using shared MFC DLL.

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

----------------------------------------------------------------

MYMFC22C DLL project summary.

 

Figure 20: MYMFC22C DLL project summary.

 

Examine the mymfc22C.cpp file. AppWizard generates the following code, which includes a derived CWinApp class:

 

// mymfc22C.cpp : Defines the initialization routines for the DLL.

//

 

#include "stdafx.h"

#include "mymfc22C.h"

 

#ifdef _DEBUG

#define new DEBUG_NEW

#undef THIS_FILE

static char THIS_FILE[] = __FILE__;

#endif

 

//

//     Note!

//

//            If this DLL is dynamically linked against the MFC

//            DLLs, any functions exported from this DLL which

//            call into MFC must have the AFX_MANAGE_STATE macro

//            added at the very beginning of the function.

//

//            For example:

//

//            extern "C" BOOL PASCAL EXPORT ExportedFunction()

//            {

//                   AFX_MANAGE_STATE(AfxGetStaticModuleState());

//                   // normal function body here

//            }

//

//            It is very important that this macro appear in each

//            function, prior to any calls into MFC.  This means that

//            it must appear as the first statement within the

//            function, even before any object variable declarations

//            as their constructors may generate calls into the MFC

//            DLL.

//

//            Please see MFC Technical Notes 33 and 58 for additional

//            details.

//

 

/////////////////////////////////////////////////////////////////////////////

// CMymfc22CApp

 

BEGIN_MESSAGE_MAP(CMymfc22CApp, CWinApp)

       //{{AFX_MSG_MAP(CMymfc22CApp)

              // NOTE - the ClassWizard will add and remove mapping macros here.

              //    DO NOT EDIT what you see in these blocks of generated code!

       //}}AFX_MSG_MAP

END_MESSAGE_MAP()

 

/////////////////////////////////////////////////////////////////////////////

// CMymfc22CApp construction

 

CMymfc22CApp::CMymfc22CApp()

{

       // TODO: add construction code here,

       // Place all significant initialization in InitInstance

}

 

/////////////////////////////////////////////////////////////////////////////

// The one and only CMymfc22CApp object

 

CMymfc22CApp theApp;

 

Add the code for the exported Mymfc22CSquareRoot() function. It's okay to add this code in the mymfc22C.cpp file, although you can use a new file if you want to:

 

extern "C" __declspec(dllexport) double Mymfc22CSquareRoot(double d)

{

    AFX_MANAGE_STATE(AfxGetStaticModuleState());

    TRACE("Entering Mymfc22CSquareRoot\n");

    if (d >= 0.0)

    {

        return sqrt(d);

    }

    AfxMessageBox("Can't take square root of a negative number.");

    return 0.0;

}

 

 

MFC Visual C++ code segment

 

Listing 3.

 

You can see that there's no problem with the DLL displaying a message box or another modal dialog. You'll need to include math.h in the file containing this code because we are going to use the sqrt() pre-defined function.

 

MFC Visual C++ code segment

 

Listing 4.

 

Build the project and copy the DLL file. Copy the file mymfc22C.dll from the \mfcproject\mymfc22C\Debug directory to your system directory.

 

Generated DLL file of MYMFC22C program.

 

Figure 21: Generated DLL file of MYMFC22C program.

 

 

Continue on next module...part 3.

 

 

 

 

 

 

Further reading and digging:

  1. Win32 dynamic link library, DLL.

  2. MSDN MFC 7.0 class library online documentation.

  3. MSDN MFC 9.0 class library online documentation - latest version.

  4. MSDN Library

  5. Windows data type.

  6. Win32 programming Tutorial.

  7. The best of C/C++, MFC, Windows and other related books.

  8. Unicode and Multibyte character set: Story and program examples.

 

 

 

 


 

| Tenouk C++ & C | MFC Home | C++, MFC & DLL 1 | C++, MFC & DLL 3 | Download | Site Index |