This is the fourth part of "deep dive into VC ++ dynamic link library (DLL) programming". Before reading this article, read the first three parts: (1), (2) and (3 ).
The content of the MFC extension DLL is the extension of the MFC. You can use the MFC extension DLL just like using the DLL of the MFC itself. In addition to MFC extension DLL, the interface between the MFC extension DLL and the application can also be MFC. We generally use MFC extension DLL to include some enhanced functions of MFC, such as CStatic and CButton extension of MFC to provide more powerful capabilities.
When you use the Visual C ++ Wizard to produce the MFC extension DLL, the MFC wizard automatically adds the DLL entry function DllMain:
Extern "C" int APIENTRY
DllMain (HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved)
{
// Remove this if you use lpReserved
UNREFERENCED_PARAMETER (lpReserved );
If (dwReason = DLL_PROCESS_ATTACH)
{
TRACE0 ("MFCEXPENDDLL. DLL Initializing! ");
// Extension DLL one-time initialization
If (! AfxInitExtensionModule (MfcexpenddllDLL, hInstance ))
Return 0;
// Insert this DLL into the resource chain
// NOTE: If this Extension DLL is being implicitly linked to
// An MFC Regular DLL (such as an ActiveX Control)
// Instead of an MFC application, then you will want
// Remove this line from DllMain and put it in a separate
// Function exported from this Extension DLL. The Regular DLL
// That uses this extension DLL shoshould then explicitly call that
// Function to initialize this extension DLL. Otherwise,
// The cdynlinklibrary object will not be attached to
// Regular DLL's resource chain, and serious problems will
// Result.
New cdynlinklibrary (mfcexpenddlldll );
}
Else if (dwreason = dll_process_detach)
{
Trace0 ("mfcexpenddll. dll terminating! ");
// Terminate the library before Destructors are called
Afxtermextensionmodule (mfcexpenddlldll );
}
Return 1; // OK
}
Because the methods for exporting functions and variables using MFC extension DLL are no different from those of other DLL, we will not explain it in detail. The following example shows how to create an MFC extension DLL and call it in an application.
6.1 create an MFC extension DLL
Next we will export a button class CSXButton (CButton class extended from MFC) in the MFC extension DLL. The class CSXButton is a class used to replace CButton, it enables you to display bitmap and text on the same button, while the MFC button can only display one of them. The source code of the class CSXbutton is widely spread on the Internet and has a good "Mass Basis". Therefore, using this class to explain the special functions of the MFC extension DLL has.
MFC contains some macros, which are expanded in different ways in the DLL and the application that calls the DLL, so that in the DLL and application, A unified macro can be used to indicate the differences between output and input:
// For Data
# Ifndef afx_data_export
# Define afx_data_export _ declspec (dllexport)
# Endif
# Ifndef afx_data_import
# Define AFX_DATA_IMPORT _ declspec (dllimport)
# Endif
// For classes
# Ifndef AFX_CLASS_EXPORT
# Define AFX_CLASS_EXPORT _ declspec (dllexport)
# Endif
# Ifndef AFX_CLASS_IMPORT
# Define AFX_CLASS_IMPORT _ declspec (dllimport)
# Endif
// For global APIs
# Ifndef AFX_API_EXPORT
# Define AFX_API_EXPORT _ declspec (dllexport)
# Endif
# Ifndef AFX_API_IMPORT
# Define AFX_API_IMPORT _ declspec (dllimport)
# Endif
# Ifndef AFX_EXT_DATA
# Ifdef _ AFXEXT
# Define AFX_EXT_CLASS AFX_CLASS_EXPORT
# Define AFX_EXT_API AFX_API_EXPORT
# Define AFX_EXT_DATA AFX_DATA_EXPORT
# Define AFX_EXT_DATADEF
# Else
# Define AFX_EXT_CLASS AFX_CLASS_IMPORT
# Define AFX_EXT_API AFX_API_IMPORT
# Define AFX_EXT_DATA AFX_DATA_IMPORT
# Define AFX_EXT_DATADEF
# Endif
# Endif
Export a class and use AFX_EXT_CLASS directly in the class declaration header file. The following is an example of exporting the CSXButton class:
# Ifndef _ SXBUTTON_H
# Define _ SXBUTTON_H
# DefineSXBUTTON_CENTER-1
Class AFX_EXT_CLASS CSXButton: public CButton
{
// Construction
Public:
CSXButton ();
// Attributes
Private:
// Positioning
BOOL m_bUseOffset;
CPoint m_pointImage;
CPoint m_pointText;
Int m_nImageOffsetFromBorder;
Int m_nTextOffsetFromImage;
// Image
HICON m_hIcon;
HBITMAP m_hBitmap;
HBITMAP m_hBitmapDisabled;
Int m_nimagewidth, m_nimageheight;
// Color Tab
Char m_bcolortab;
Colorrefm_crcolortab;
// State
Bool m_bdefault;
Uint m_noldaction;
Uint m_noldstate;
// Operations
Public:
// Positioning
Int setimageoffset (INT npixels );
Int settextoffset (INT npixels );
Cpointsetimagepos (cpoint P );
Cpointsettextpos (cpoint P );
// Image
Boolseticon (uint NID, int nwidth, int nheight );
Boolsetbitmap (uint NID, int nwidth, int nheight );
Boolsetmaskedbitmap (uint NID, int nwidth, int nheight, colorref crtransparentmask );
Boolhasimage () {return (bool) (m_hicon! = 0 | m_hbitmap! = 0 );}
// Color Tab
Voidsetcolortab (colorref crtab );
// State
Boolsetdefaultbutton (bool bstate = true );
PRIVATE:
Boolsetbitmapcommon (uint NID, int nwidth, int nheight, colorref crtransparentmask, bool busemask );
Voidcheckpointforcentering (cpoint & P, int nwidth, int nheight );
Voidredraw ();
// Overrides
// Classwizard generated virtual function overrides
// {Afx_virtual (csxbutton)
Public:
Virtual void drawitem (lpdrawitemstruct );
//} Afx_virtual
// Implementation
Public:
Virtual ~ Csxbutton ();
// Generated message map Functions
Protected:
// {Afx_msg (csxbutton)
Afx_msg lresult ongettext (wparam, lparam );
//} Afx_msg
Declare_message_map ()
};
# Endif
Add the sxbutton. cpp file directly to the project, compile the project, and obtain the "mfcexpenddll. lib" and "mfcexpenddll. dll" files. We can use the depends tool that comes with Visual Studio to view this. dll and find that it has exported many symbols (see figure 15 ).
Figure 15 a large number of symbols exported when exporting a category (+ enlarge the image)
These are symbols processed by the compiler for class constructor, destructor, and other member functions and variables. We use _ declspec (dllexport) directly) the statement Declaration class exports these symbols.
If we want to use the. Lib file to export these symbols, it is very difficult. We need to generate the. map file in the project, query the symbols of the. map file, and then export them one by one. 16. Open the settings option of the DLL project, select link, and select generate map file to generate the. Map File.
Open the. map file generated by the mfcexpenddll project and we find that it contains the symbol (Symbol) shown in Figure 15)
0001: 00000380? Hasimage @ csxbutton @ qaehxz 10001380 f I sxbutton. OBJ
0001: 000003d0 ?? 0csxbutton @ Qae @ xz 100013d0 F sxbutton. OBJ
000:00000500 ?? _ Gcsxbutton @ uaepaxi @ Z 10001500 f I sxbutton. OBJ
0001: 00000570 ?? _ Ecsxbutton @ uaepaxi @ Z 10001570 f I sxbutton. OBJ
0001: 00000630 ?? 1csxbutton @ UAE @ xz 10001630 F sxbutton. OBJ
0001: 00000700? _ Getbasemessagemap @ csxbutton @ kgpbuafx_msgmap @ xz 10001700 F sxbutton. OBJ
0001: 00000730? Getmessagemap @ csxbutton @ mbepbuafx_msgmap @ xz 10001730 F sxbutton. OBJ
0001: 00000770? Redraw @ csxbutton @ aaexxz 10001770 f I sxbutton. OBJ
0001: 000007d0? Seticon @ csxbutton @ qaehihh @ Z 100017d0 F sxbutton. OBJ
................................................................................ // Omitted
Figure 16 generate a. Map File (+ enlarge the image)
Therefore, for the MFC extension DLL, we should not export the class using the. Lib file.