static AFX_EXTENSION_MODULE ExtDllDLL = { NULL, NULL };
extern "C" int APIENTRY
DllMain( HINSTANCE hInstance, DWord dwReason, LPVOID lPReserved )
{
// Remove this if you use lpReserved
UNREFERENCED_PARAMETER( lpReserved );
//說明:lpReserved是一個被系統所保留的參數,對于隱式鏈接是一個非零值,對于顯式鏈接值是零
if (dwReason == DLL_PROCESS_ATTACH)
{
TRACE0( "EXTDLL.DLL Initializing!/n" );
// Extension DLL one-time initialization
if ( !AfxInitExtensionModule( ExtDllDLL, hInstance ))
return 0;
// Insert this DLL into the resource chain
new CDynLinkLibrary( ExtDllDLL );
}
else if (dwReason == DLL_PROCESS_DETACH)
{
TRACE0( "EXTDLL.DLL Terminating!/n" );
// Terminate the library before destrUCtors are called
AfxTermExtensionModule( ExtDllDLL );
}
return 1; // ok
}
struct AFX_EXTENSION_MODULE
{
BOOL bInitialized;
HMODULE hModule;
HMODULE hResource;
CRuntimeClass* pFirstSharedClass;
COleObjectFactory* pFirstSharedFactory;
};
class AFX_EXT_CLASS CExtDialog : public CDialog
{
public:
CExtDialog( CWnd* pParent = NULL );
enum { IDD = IDD_DLL_DIALOG };
protected:
virtual void DoDataExchange( CDataExchange* pDX );
DECLARE_MESSAGE_MAP()
};
// LoadExtDllDlg.cpp : implementation file
//
#include "../ExtDialog.h"
#pragma comment( lib, "ExtDll.lib" )
而“調用DLL”按鈕的單擊事件的消息處理函數為:
void CLoadExtDllDlg::OnDllcallButton()
{
CExtDialog extDialog;
extDialog.DoModal();
}
HINSTANCE AFXAPI AfxLoadLibrary( LPCTSTR lpszModuleName );
BOOL AFXAPI AfxFreeLibrary( HINSTANCE hInstLib );
void CLoadExtDllDlg::OnDllcallButton()
{
HINSTANCE hDll = AfxLoadLibrary( "ExtDll.dll" );
if(NULL == hDll)
{
AfxMessageBox( "MFC擴展DLL動態加載失敗" );
return;
}
CExtDialog extDialog;
extDialog.DoModal();
AfxFreeLibrary(hDll);
}
LoadExtDllDlg.obj : error LNK2001: unresolved external symbol "__declspec(dllimport) public: virtual __thiscall CExtDialog::~CExtDialog(void)" (__imp_??1CExtDialogUAE@XZ)
LoadExtDllDlg.obj : error LNK2001: unresolved external symbol "__declspec(dllimport) public: __thiscall CExtDialog::CExtDialog(class CWnd *)" (__imp_??0CExtDialogQAE@PAVCWnd@Z)
error LNK2001: unresolved external symbol ….......
//臨時改變宏的含義“輸出”為“輸入”
#undef AFX_EXT_CLASS
#undef AFX_EXT_API
#undef AFX_EXT_DATA
#define AFX_EXT_CLASS AFX_CLASS_IMPORT
#define AFX_EXT_API AFX_API_IMPORT
#define AFX_EXT_DATA AFX_DATA_IMPORT
//包含被調用MFC擴展DLL的頭文件
#include "CalledDLL.h"
//恢復宏的含義為輸出
#undef AFX_EXT_CLASS
#undef AFX_EXT_API
#undef AFX_EXT_DATA
#define AFX_EXT_CLASS AFX_CLASS_EXPORT
#define AFX_EXT_API AFX_API_EXPORT
#define AFX_EXT_DATA AFX_DATA_EXPORT
6.5 MFC擴展DLL導出函數和變量//global.h:MFC擴展DLL導出變量和函數的聲明
extern "C"
{
int AFX_EXT_DATA total; //導出變量
int AFX_EXT_API add( int x, int y ); //導出函數
}
//global.cpp:MFC擴展DLL導出變量和函數定義
#include "StdAfx.h"
#include "global.h"
extern "C" int total;
int add(int x,int y)
{
total = x + y;
return total;
}
#include
#include 單擊此處下載本工程)。
我們知道static控件所對應的CStatic類不具備設置背景和文本顏色的接口,這使得我們不能在對話框或其它用戶界面上自由靈活地修改static控件的顏色風格,因此我們需要一個提供了SetBackColor和SetTextColor接口的CStatic派生類CMultiColorStatic。
這個類的聲明如下:
class AFX_EXT_CLASS CMultiColorStatic : public CStatic
{
// Construction
public:
CMultiColorStatic();
virtual ~CMultiColorStatic();
// Attributes
protected:
CString m_strCaption;
COLORREF m_BackColor;
COLORREF m_TextColor;
// Operations
public:
void SetTextColor( COLORREF TextColor );
void SetBackColor( COLORREF BackColor );
void SetCaption( CString strCaption );
// Generated message map functions
protected:
afx_msg void OnPaint();
DECLARE_MESSAGE_MAP()
};
在這個類的實現文件中,我們需要為它提供WM_PAINT消息的處理函數(這是因為顏色的設置依靠于WM_PAINT消息):
BEGIN_MESSAGE_MAP(CMultiColorStatic, CStatic)
//{{AFX_MSG_MAP(CMultiColorStatic)
ON_WM_PAINT() //為這個類定義WM_PAINT消息處理函數
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
下面是這個類中的重要成員函數:
//為CMultiColorStatic類添加“設置文本顏色”接口
void CMultiColorStatic::SetTextColor( COLORREF TextColor )
{
m_TextColor = TextColor; //設置文字顏色
}
//為CMultiColorStatic類添加“設置背景顏色”接口
void CMultiColorStatic::SetBackColor( COLORREF BackColor )
{
m_BackColor = BackColor; //設置背景顏色
}
//為CMultiColorStatic類添加“設置標題”接口
void CMultiColorStatic::SetCaption( CString strCaption )
{
m_strCaption = strCaption;
}
//重畫Static,顏色和標題的設置都依靠于這個函數
void CMultiColorStatic::OnPaint()
{
CPaintDC dc(this); // device context for painting
CRect rect;
GetClientRect( &rect );
dc.SetBkColor( m_BackColor );
dc.SetBkMode( TRANSPARENT );
CFont *pFont = GetParent()->GetFont();//得到父窗體的字體
CFont *pOldFont;
pOldFont = dc.SelectObject( pFont );//選用父窗體的字體
dc.SetTextColor( m_TextColor );//設置文本顏色
dc.DrawText( m_strCaption, &rect, DT_CENTER );//文本在Static中心
dc.SelectObject( pOldFont );
}
為了驗證CMultiColorStatic類,我們制作一個基于對話框的應用程序,它包含一個如圖17所示的對話框。該對話框上包括一個static控件和三個按鈕,這三個按鈕可分別把static控件設置為“紅色”、“藍色”和“綠色”。

圖17 擴展的CStatic類調用演示
下面看看應如何編寫與這個對話框對應的類。
包含這種Static的對話框類的聲明如下:
#include "../MultiColorStatic.h"
#pragma comment ( lib, "ColorStatic.lib" )
// CCallDllDlg dialog
class CCallDllDlg : public CDialog
{
public:
CCallDllDlg(CWnd* pParent = NULL); // standard constructor
enum { IDD = IDD_CALLDLL_DIALOG };
CMultiColorStatic m_colorstatic; //包含一個CMultiColorStatic的實例
protected:
virtual void DoDataExchange(CDataExchange* pDX);//DDX/DDV support
HICON m_hIcon;
// Generated message map functions
//{{AFX_MSG(CCallDllDlg)
virtual BOOL OnInitDialog();
afx_msg void OnSysCommand(UINT nID, LPARAM lParam);
afx_msg void OnPaint();
afx_msg HCURSOR OnQueryDragIcon();
afx_msg void OnRedButton();
afx_msg void OnBlueButton();
afx_msg void OnGreenButton();
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
};
下面是這個類中與使用CMultiColorStatic相關的主要成員函數:
void CCallDllDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CCallDllDlg)
DDX_Control(pDX, IDC_COLOR_STATIC, m_colorstatic);
//使m_colorstatic與IDC_COLOR_STATIC控件關聯
//}}AFX_DATA_MAP
}
BOOL CCallDllDlg::OnInitDialog()
{
…
// TODO: Add extra initialization here
// 初始static控件的顯示
m_colorstatic.SetCaption("最開始為黑色");
m_colorstatic.SetTextColor(RGB(0,0,0));
return TRUE; // return TRUE unless you set the focus to a control
}
//設置static控件文本顏色為紅色
void CCallDllDlg::OnRedButton()
{
m_colorstatic.SetCaption( "改變為紅色" );
m_colorstatic.SetTextColor( RGB( 255, 0, 0 ) );
Invalidate( TRUE ); //導致發出WM_PAINT消息
}
//設置static控件文本顏色為藍色
void CCallDllDlg::OnBlueButton()
{
m_colorstatic.SetCaption( "改變為藍色" );
m_colorstatic.SetTextColor( RGB( 0, 0, 255 ) );
Invalidate( TRUE ); //導致發出WM_PAINT消息
}
//設置static控件文本顏色為綠色
void CCallDllDlg::OnGreenButton()
{
m_colorstatic.SetCaption( "改變為綠色" );
m_colorstatic.SetTextColor( RGB(0,255,0) );
Invalidate( TRUE ); //導致發出WM_PAINT消息
}
至此,我們已經講解完成了所有類型的動態鏈接庫,即非MFC DLL、MFC規則DLL和MFC擴展DLL。下一節將給出DLL的三個工程實例,與讀者朋友們共同體會DLL的應用范圍和使用方法。
新聞熱點
疑難解答