DLLTRACE: Writes a DLL Statically Linked to the Framework Library

Click to open or copy the DLLTRACE project files.

The DLLTRACE sample illustrates a dynamic-link library (DLL) version of the TRACER tool. DLLTRACE was introduced in Microsoft Foundation Class Library (MFC) version 1.0 to illustrate how to write a DLL that is itself statically linked to the framework library. This DLL provides a C-based program interface to the Microsoft Windows–based application to which it is dynamically linked. A DLL that is statically linked to the framework library cannot successfully export member functions of any classes that are derived from framework classes.

The technique of statically linking a custom DLL to the Foundation Class Library is discussed in Technical Note 11: Using MFC as Part of a DLL Before you decide to implement a custom DLL by statically linking to MFC, consider implementing it as an MFC extension DLL, as explained in Technical Note 33: DLL Version of MFC and as illustrated by the DLLHUSK sample.

A custom DLL that is statically linked to the MFC library needs to have a CWinApp-derived class and a single object of that application class, as does an executable MFC application. The CWinApp object of the DLL, however, does not have a main message pump, as does the CWinApp object of an application. If the DLL opens modeless dialogs or has a main frame window of its own, the application's main message pump must call a routine exported by the DLL, which in turn calls the CWinApp::PreTranslateMessage member function of the DLL's application object. This is illustrated by the FilterDllMsg function exported by Tracer.dll.

TRACEAPI.H shows that a way to provide a DLL interface to client applications is to use declare functions with extern "C". The use of extern "C" has several advantages. First, it makes your DLL usable by non-C++ client applications. Second, it reduces DLL overhead, because C++ name decoration will not be applied to the exported name. Third, it makes it easier to explicitly add to a .def file (for exporting by ordinal), without having to worry about C++ name decoration.

To run DLLTRACE, run HELLO1, which is built by the DLLTRACE makefile in the DLLTRACE sample directory. The HELLO1 window displays "Hello, Windows! (with DLL support)". Click Change Trace Flags on the Debug menu. This opens the same AFX Trace Options dialog box presented by the TRACER tool. See TRACER for an explanation of the trace options.

Converting DLLTRACE to Dynamically Link with the MFC DLL

DLLTRACE demonstrates how to create a Regular DLL with an exported function that can be called to display a modal dialog box. By default, DLLTRACE is set to statically link MFC to the DLL. In previous versions of Visual C++, this was the only option available for Regular DLLs. These kinds of DLLs were formerly known as _USRDLLs.

Now, it is possible for a Regular DLL to use MFC from the shared MFCx0 DLL. Because of the potential to reduce the size of the build, you might want to convert the DLLTRACE sample to use the shared MFC DLL. Converting the TRACE.DLL to use the Shared Library will reduce the size of a release-build DLL from around 95K to about 12K and will reduce the size of the debug build from nearly 1 megabyte to 25K. To convert DLLTRACE, it is necessary to use the macro AFX_MANAGE_STATE in order to switch the global MFC module state correctly.

Steps to Convert DLLTRACE to Use MFC in a Shared Library

     AFX_MANAGE_STATE(AfxGetStaticModuleState())

For example, Trace.dll exports only three functions: PromptTraceFlags( ), ProcessDLLIdle( ), and FilterDLLMsg( ). Here is what FilterDLLMsg( ) should look like in the converted form:

   extern "C" BOOL FAR PASCAL EXPORT FilterDllMsg(LPMSG lpMsg)
   {
      AFX_MANAGE_STATE(AfxGetStaticModuleState())
      TRY
      {
          return AfxGetApp()->PreTranslateMessage(lpMsg);
      }
      END_TRY
      return FALSE;
   }

After making these changes, rebuild the DLLTRACE project. The application will use the new DLL and work just as it did before.

This sample demonstrates the following keywords:

AfxGetApp; CDC::SetBkMode; CDC::SetTextAlign; CDC::TextOut; CDialog::DoModal; CWinApp::Enable3dControls; CWinApp::ExitInstance; CWinApp::InitInstance; CWinApp::OnIdle; CWinApp::PreTranslateMessage; CWnd::DoDataExchange; CWnd::GetClientRect; CWnd::OnPaint; MAKEINTRESOURCE; ShowWindow; UpdateWindow; afxTraceEnabled; afxTraceFlags