一、關于DECLARE_MESSAGE_MAP宏定義
使用MFC向導,在ApplicationType頁面選擇DialogBased,生成一個對話框項目,Dialog類命名為CCapturePacketDlg,在CCapturePacketDlg.cpp中自動產生下列代碼:
1
BEGIN_MESSAGE_MAP(CCapturePacketDlg,?CDialog)
2
????ON_WM_PAINT()
3
END_MESSAGE_MAP()
- 先來分析ON_WM_PAINT(),在頭文件“afxmsg.h”有它的宏定義,如下:
1
#define
?ON_WM_PAINT()?\
2
????
{?WM_PAINT,?
0
,?
0
,?
0
,?AfxSig_vv,?\
3
????????(AFX_PMSG)(AFX_PMSGW)?\
4
????????(static_cast
<
?
void
?(AFX_MSG_CALL?CWnd::
*
)(
void
)?
>
?(?
&
ThisClass?::?OnPaint))?}
,
說明:層次序號x.y.z表示x為根節點也就是上面代碼中的行號,y、z為上一級的定義展開。
2.1 #define WM_PAINT??????????????????????? 0x000F
2.2 AfxSig_vv = AfxSig_v_v_v
2.2.1 enum AfxSig::AfxSig_v_v_v = 19
3.1 AFX_PMSG:typedef void (AFX_MSG_CALL CCmdTarget::*AFX_PMSG)(void); //為一個函數指針
3.2 AFX_PMSGW:typedef void (AFX_MSG_CALL CWnd::*AFX_PMSGW)(void);?? //為一個函數指針
將ON_WM_PAINT()完全展開:
1

{
2
????????0x000F,?
3
????????0,
4
????????0,
5
????????0,
6
????????19,
7
????????//Converts?OnPaint?to?the?type?of?CCmdTarget?finally.?Derive?Class?'s?pointer?->?Base?Class's?pointer
8
????????(AFX_MSG_CALL?CCmdTarget::*)((AFX_MSG_CALL?CWnd::*)(static_cast<?void?(AFX_MSG_CALL?CWnd::*)(void)?>(&ThisClass?::?OnPaint))
9
????} ???2.???再來分析BEGIN_MESSAGE_MAP(CCapturePacketDlg, CDialog),在“afxwin.h”中有定義:
?1
#define?BEGIN_MESSAGE_MAP(theClass,?baseClass)?\
?2
????PTM_WARNING_DISABLE?\
?3
????const?AFX_MSGMAP*?theClass::GetMessageMap()?const?\
?4
????????
{?return?GetThisMessageMap();?}?\
?5
????const?AFX_MSGMAP*?PASCAL?theClass::GetThisMessageMap()?\
?6
????
{?\
?7
????????typedef?theClass?ThisClass;???????????????????????????\
?8
????????typedef?baseClass?TheBaseClass;???????????????????????\
?9
????????static?const?AFX_MSGMAP_ENTRY?_messageEntries[]?=??\
10
????????
{ 2.1 PTM_WARNING_DISABLE:
#define PTM_WARNING_DISABLE \
?__pragma(warning( push ))??\?//#pragma warning( push [ ,n ] ),Where n represents a warning level (1 through 4).
????????????????????????????????????????????? //The pragma warning( push ) stores the current warning state for all warnings.
?__pragma(warning( disable : 4867 ))//Do not issue the specified warning message(s).
//http://msdn2.microsoft.com/en-us/2c8f766e.aspx
//?Allows selective modification of the behavior of compiler warning messages.
3.1 struct AFX_MSGMAP
?{
??3.1.1 const AFX_MSGMAP* (PASCAL* pfnGetBaseMap)();
??3.1.2 const AFX_MSGMAP_ENTRY* lpEntries;
?};
3.1.2 struct AFX_MSGMAP_ENTRY
?{
??UINT nMessage;?? // windows message
??UINT nCode;????? // control code or WM_NOTIFY code
??UINT nID;??????? // control ID (or 0 for windows messages)
??UINT nLastID;??? // used for entries specifying a range of control id's
??UINT_PTR nSig;?????? // signature type (action) or pointer to message #
??3.1.2.1 AFX_PMSG pfn;??? // routine to call (or special value)
?};
?3.1.2.1 typedef void (AFX_MSG_CALL CCmdTarget::*AFX_PMSG)(void);
5.1 #define PASCAL????? __stdcall
將BEGIN_MESSAGE_MAP(CCapturePacketDlg, CDialog)完全展開:
?1
__pragma(warning(?push?))?__pragma(warning(?disable?:?4867?))
?2
????const?struct?AFX_MSGMAP*?CCapturePacketDlg::GetMessageMap()?const
?3
????
{?
?4
????????return?GetThisMessageMap();?
?5
????}
?6
????const?struct?AFX_MSGMAP*?__stdcall?CCapturePacketDlg::GetThisMessageMap()
?7
????
{
?8
????????typedef?CCapturePacketDlg?ThisClass;???????????????????????????
?9
????????typedef?CDialog?TheBaseClass;????????
10
????????static?const?struct?AFX_MSGMAP_ENTRY?_messageEntries[]?=?
11
????????
{ ?? 3??? 最后分析END_MESSAGE_MAP(),在“afxwin.h”中有定義:
1
#define?END_MESSAGE_MAP()?\
2
????????
{0,?0,?0,?0,?AfxSig_end,?(AFX_PMSG)0?}?\
3
????};?\
4
????????static?const?AFX_MSGMAP?messageMap?=?\
5
????????
{?&TheBaseClass::GetThisMessageMap,?&_messageEntries[0]?};?\
6
????????return?&messageMap;?\
7
????}??????????????????????????????????\
8
????PTM_WARNING_RESTORE 2.1 AfxSig_end:enum AfxSig.AfxSig_end = 0
2.2 AFX_PMSG:typedef void (AFX_MSG_CALL CCmdTarget::*AFX_PMSG)(void);//函數指針
4.1 struct AFX_MSGMAP
?{
??const AFX_MSGMAP* (PASCAL* pfnGetBaseMap)();
??const AFX_MSGMAP_ENTRY* lpEntries;
?};
8.1 #define PTM_WARNING_RESTORE \
?__pragma(warning( pop ))
//pop restores the state of all warnings (including 4705, 4706, and 4707) to what it was at the beginning of the code.
·最后將
1
BEGIN_MESSAGE_MAP(CCapturePacketDlg,?CDialog)
2
????ON_WM_PAINT()
3
END_MESSAGE_MAP() 完全展開為:
?1
__pragma(warning(?push?))?__pragma(warning(?disable?:?4867?))
?2
????const?struct?AFX_MSGMAP*?CCapturePacketDlg::GetMessageMap()?const
?3
????
{?
?4
????????return?GetThisMessageMap();?
?5
????}
?6
????const?struct?AFX_MSGMAP*?__stdcall?CCapturePacketDlg::GetThisMessageMap()
?7
????
{
?8
????????typedef?CCapturePacketDlg?ThisClass;???????????????????????????
?9
????????typedef?CDialog?TheBaseClass;????????
10
????????static?const?struct?AFX_MSGMAP_ENTRY?_messageEntries[]?=?
11
????????
{
12
????????????
{
13
????????????????0x000F,?
14
????????????????0,
15
????????????????0,
16
????????????????0,
17
????????????????19,
18
????????????????//Converts?OnPaint?to?the?type?of?CCmdTarget?finally.?Derive?Class?'s?pointer?->?Base?Class's?pointer
19
????????????????(AFX_MSG_CALL?CCmdTarget::*)((AFX_MSG_CALL?CWnd::*)(static_cast<?void?(AFX_MSG_CALL?CWnd::*)(void)?>(&ThisClass?::?OnPaint))
20
????????????},
21
????????????//add?others
22
????????????
{
23
????????????????0,
24
????????????????0,
25
????????????????0,
26
????????????????0,
27
????????????????0,
28
????????????????(AFX_PMSG)0
29
????????????}
30
????????}
31
????????static?const?struct?AFX_MSGMAP?messageMap?=?
32
????????
{
33
????????????&TheBaseClass::GetThisMessageMap,
34
????????????&_messageEntries[0]
35
????????};
36
????????return?&messageMap;
37
????}
38
__pragma(warning(?pop?))
39
其中GetMessageMap()是在哪里聲明的呢?在CCapturePacketDlg的定義中有一個這樣的宏:DECLARE_MESSAGE_MAP()
老辦法查看它的定義:
1
#define?DECLARE_MESSAGE_MAP()?\
2
protected:?\
3
????static?const?AFX_MSGMAP*?PASCAL?GetThisMessageMap();?\
4
????virtual?const?AFX_MSGMAP*?GetMessageMap()?const;?\ 注意函數為static,即它們是類的函數。函數中的static變量實際也在類對象未生成之前已經存在。(這種說法不知道是否正確?)
小結:
每次用MFC類向導生成一個類時,系統會在類的聲明部分添加兩個方法的聲明:GetThisMessageMap(),GetMessageMap()。在類的實現部分.cpp文件中加上這兩個方法的定義。
當然這所有的代碼都是由系統生成的,如果我們要定義自己的消息處理函數呢,例如,我們要添加一個按鈕(ID為:IDC_BUTTON1)的單擊處理函數我們可以添加宏ON_NOTIFY(NM_CLICK, IDC_BUTTON1, OnMyClick),OnMyClick為自定義函數,但是他必須與ON_NOTIFY中的函數原型一致。
二、關于DECLARE_DYNCREATE宏
使用MFC向導,在ApplicationType頁面選擇SingleDocument,生成一個單文檔項目,Document類命名為CDynamicDoc,在CDynamicDoc.h中自動產生DECLARE_DYNCREATE(CDynamicDoc),CDynamicDoc.cpp中產生IMPLEMENT_DYNCREATE(CDynamicDoc, CDocument)。
1、展開CDynamicDoc.h中的DECLARE_DYNCREATE(CDynamicDoc):
1
//?not?serializable,?but?dynamically?constructable
2
????#define?DECLARE_DYNCREATE(class_name)?\
3
????????DECLARE_DYNAMIC(class_name)?\
4
????????static?CObject*?PASCAL?CreateObject(); 3.1如下定義:
1
#ifdef?_AFXDLL
2
????#define?DECLARE_DYNAMIC(class_name)?\
3
????protected:?\
4
????????static?CRuntimeClass*?PASCAL?_GetBaseClass();?\
5
????public:?\
6
????????static?const?CRuntimeClass?class##class_name;?\
7
????????static?CRuntimeClass*?PASCAL?GetThisClass();?\
8
????????virtual?CRuntimeClass*?GetRuntimeClass()?const;?\ so the result(DECLARE_DYNCREATE(CDynamicDoc)) of combining the above two is following:
1
protected:?
2
????????static?CRuntimeClass*?PASCAL?_GetBaseClass();?
3
????public:?
4
????????static?const?CRuntimeClass?classCDynamicDoc;?
5
????????static?CRuntimeClass*?PASCAL?GetThisClass();?
6
????????virtual?CRuntimeClass*?GetRuntimeClass()?const;?
7
????????static?CObject*?PASCAL?CreateObject(); 2、展開CDynamicDoc.cpp中的IMPLEMENT_DYNCREATE(CDynamicDoc, CDocument):
1
#define?IMPLEMENT_DYNCREATE(class_name,?base_class_name)?\
2
????CObject*?PASCAL?class_name::CreateObject()?\
3
????????
{?return?new?class_name;?}?\
4
????IMPLEMENT_RUNTIMECLASS(class_name,?base_class_name,?0xFFFF,?\
5
????????class_name::CreateObject,?NULL) 4.1如下定義:
?1
#define?IMPLEMENT_RUNTIMECLASS(class_name,?base_class_name,?wSchema,?pfnNew,?class_init)?\
?2
????CRuntimeClass*?PASCAL?class_name::_GetBaseClass()?\
?3
????????
{?return?RUNTIME_CLASS(base_class_name);?}?\
?4
????AFX_COMDAT?const?CRuntimeClass?class_name::class##class_name?=?
{?\
?5
????????#class_name,?sizeof(class?class_name),?wSchema,?pfnNew,?\
?6
????????????&class_name::_GetBaseClass,?NULL,?class_init?};?\
?7
????CRuntimeClass*?PASCAL?class_name::GetThisClass()?\
?8
????????
{?return?_RUNTIME_CLASS(class_name);?}?\
?9
????CRuntimeClass*?class_name::GetRuntimeClass()?const?\
10
????????
{?return?_RUNTIME_CLASS(class_name);?}?\ 4.1.2 CRuntimeClass如下定義:
?1
struct?CRuntimeClass
?2
????
{
?3
????//?Attributes
?4
????????LPCSTR?m_lpszClassName;
?5
????????int?m_nObjectSize;
?6
????????UINT?m_wSchema;?//?schema?number?of?the?loaded?class
?7
????????CObject*?(PASCAL*?m_pfnCreateObject)();?//?NULL?=>?abstract?class
?8
????#ifdef?_AFXDLL
?9
????????CRuntimeClass*?(PASCAL*?m_pfnGetBaseClass)();
10
????#else
11
????????CRuntimeClass*?m_pBaseClass;
12
????#endif
13
14
????//?Operations
15
????????CObject*?CreateObject();
16
????????BOOL?IsDerivedFrom(const?CRuntimeClass*?pBaseClass)?const;
17
18
????????//?dynamic?name?lookup?and?creation
19
????????static?CRuntimeClass*?PASCAL?FromName(LPCSTR?lpszClassName);
20
????????static?CRuntimeClass*?PASCAL?FromName(LPCWSTR?lpszClassName);
21
????????static?CObject*?PASCAL?CreateObject(LPCSTR?lpszClassName);
22
????????static?CObject*?PASCAL?CreateObject(LPCWSTR?lpszClassName);
23
24
????//?Implementation
25
????????void?Store(CArchive&?ar)?const;
26
????????static?CRuntimeClass*?PASCAL?Load(CArchive&?ar,?UINT*?pwSchemaNum);
27
28
????????//?CRuntimeClass?objects?linked?together?in?simple?list
29
????????CRuntimeClass*?m_pNextClass;???????//?linked?list?of?registered?classes
30
????????const?AFX_CLASSINIT*?m_pClassInit;
31
????}; 4.1.2.30 AFX_CLASSINIT如下定義:(這個變量非常重要,它完成了將新的類加在List頭部的功能,List中的節點類型就是CRuntimeClass)
?1
/**//////////////////////////////////////////////////////////////////////////////?2
????//?Basic?object?model
?3
?4
????//?generate?static?object?constructor?for?class?registration
?5
????void?AFXAPI?AfxClassInit(CRuntimeClass*?pNewClass);
?6
????struct?AFX_CLASSINIT
?7
????????
{?AFX_CLASSINIT(CRuntimeClass*?pNewClass)?
{?AfxClassInit(pNewClass);?}?};
?8
????//C:\Program?Files\Microsoft?Visual?Studio?8\VC\atlmfc\src\mfc\objcore.cpp?Line157
?9
????void?AFXAPI?AfxClassInit(CRuntimeClass*?pNewClass)
10
????
{
11
????????AFX_MODULE_STATE*?pModuleState?=?AfxGetModuleState();
12
????????AfxLockGlobals(CRIT_RUNTIMECLASSLIST);
13
????????pModuleState->m_classList.AddHead(pNewClass);
14
????????AfxUnlockGlobals(CRIT_RUNTIMECLASSLIST);
15
????}
16
????//可以將AfxClassInit()函數的功能簡單的如下表示:
17
????AFX_CLASSINIT::AFX_CLASSINIT(CRuntimeClass*?pNewClass)
18
????
{
19
????????pNewClass->m_pNextClass?=?CRuntimeClass::pFirstClass;
20
????????CRuntimeClass::pFirstClass?=?pNewClass;
21
????} 4.1.3 RUNTIME_CLASS如下定義:
1
#define?RUNTIME_CLASS(class_name)?(class_name::GetThisClass()) 4.1.4 AFX_COMDAT如下定義:
1
#define?AFX_COMDAT?__declspec(selectany) 說明:“#”——operator (#) converts macro parameters to string literals without expanding the parameter definition.
“##”——operator (
##), which is sometimes called the "merging" operator, is used in both object-like and function-like macros.
4.1.8 _RUNTIME_CLASS如下定義:
1
#define?_RUNTIME_CLASS(class_name)?((CRuntimeClass*)(&class_name::class##class_name)) so the result(IMPLEMENT_DYNCREATE(CDynamicDoc, CDocument)) of combining the aboves is following:
?1//CDynamicDoc,?CDocument->class_name,?base_class_name
?2??static??CObject*?PASCAL?CDynamicDoc::CreateObject()

?3????
{?
?4????????return?new?CDynamicDoc;?
?5????}
?6
?7????static?CRuntimeClass*?PASCAL?CDynamicDoc::_GetBaseClass()

?8????
{?
?9????????return?CDocument::GetThisClass()
10????}
11
12????__declspec(selectany)?static?const?CRuntimeClass?CDynamicDoc::classCDynamicDoc?=?

13????
{
14????????"CDynamicDoc"
15????????,?sizeof(class?CDynamicDoc)
16????????,?0xFFFF
17????????,?CDynamicDoc::CreateObject
18????????,?&CDynamicDoc::_GetBaseClass
19????????,?NULL
20????????,?NULL
21????};
22
23????static?CRuntimeClass*?PASCAL?CDynamicDoc::GetThisClass()

24????
{
25????????return?((CRuntimeClass*)(&CDynamicDoc::classCDynamicDoc));
26????}
27
28????CRuntimeClass*?CDynamicDoc::GetRuntimeClass()?const

29????
{
30????????return?((CRuntimeClass*)(&CDynamicDoc::classCDynamicDoc));
31????}小結:注意了,上面的成員變量、很多函數都是static
如果你想看這些宏的簡化版,可以參考侯老的《深入淺出MFC》,如下:
三、宏DECLARE_SERIAL(CStroke)、IMPLEMENT_SERIAL(CStroke, CObject, 1),給出它們的宏定義及結果:
?1
//declaration?file
?2
#define?DECLARE_SERIAL(class_name)?\
?3
????_DECLARE_DYNCREATE(class_name)?\
?4
????AFX_API?friend?CArchive&?AFXAPI?operator>>(CArchive&?ar,?class_name*?&pOb);
?5
?6
????#define?_DECLARE_DYNCREATE(class_name)?\
?7
????_DECLARE_DYNAMIC(class_name)?\
?8
????static?CObject*?PASCAL?CreateObject();
?9
10
????#define?_DECLARE_DYNAMIC(class_name)?\
11
????protected:?\
12
????????static?CRuntimeClass*?PASCAL?_GetBaseClass();?\
13
????public:?\
14
????????static?CRuntimeClass?class##class_name;?\
15
????????static?CRuntimeClass*?PASCAL?GetThisClass();?\
16
????????virtual?CRuntimeClass*?GetRuntimeClass()?const;?\
17
//implement?file
18
#define?IMPLEMENT_SERIAL(class_name,?base_class_name,?wSchema)?\
19
????CObject*?PASCAL?class_name::CreateObject()?\
20
????????
{?return?new?class_name;?}?\
21
????extern?AFX_CLASSINIT?_init_##class_name;?\
22
????_IMPLEMENT_RUNTIMECLASS(class_name,?base_class_name,?wSchema,?\
23
????????class_name::CreateObject,?&_init_##class_name)?\
24
????AFX_CLASSINIT?_init_##class_name(RUNTIME_CLASS(class_name));?\
25
????CArchive&?AFXAPI?operator>>(CArchive&?ar,?class_name*?&pOb)?\
26
????????
{?pOb?=?(class_name*)?ar.ReadObject(RUNTIME_CLASS(class_name));?\
27
????????????return?ar;?}?\
28
????
29
????//?generate?static?object?constructor?for?class?registration
30
????void?AFXAPI?AfxClassInit(CRuntimeClass*?pNewClass);
31
????struct?AFX_CLASSINIT
32
????????
{?AFX_CLASSINIT(CRuntimeClass*?pNewClass)?
{?AfxClassInit(pNewClass);?}?};
33
34
????void?AFXAPI?AfxClassInit(CRuntimeClass*?pNewClass)
35
????
{
36
????????AFX_MODULE_STATE*?pModuleState?=?AfxGetModuleState();
37
????????AfxLockGlobals(CRIT_RUNTIMECLASSLIST);
38
????????pModuleState->m_classList.AddHead(pNewClass);
39
????????AfxUnlockGlobals(CRIT_RUNTIMECLASSLIST);
40
????}
41
42
????
43
????#define?_IMPLEMENT_RUNTIMECLASS(class_name,?base_class_name,?wSchema,?pfnNew,?class_init)?\
44
????CRuntimeClass*?PASCAL?class_name::_GetBaseClass()?\
45
????????
{?return?RUNTIME_CLASS(base_class_name);?}?\
46
????AFX_COMDAT?CRuntimeClass?class_name::class##class_name?=?
{?\
47
????????#class_name,?sizeof(class?class_name),?wSchema,?pfnNew,?\
48
????????????&class_name::_GetBaseClass,?NULL,?class_init?};?\
49
????CRuntimeClass*?PASCAL?class_name::GetThisClass()?\
50
????????
{?return?_RUNTIME_CLASS(class_name);?}?\
51
????CRuntimeClass*?class_name::GetRuntimeClass()?const?\
52
????????
{?return?_RUNTIME_CLASS(class_name);?}?\
53
????
54
????#define?_RUNTIME_CLASS(class_name)?((CRuntimeClass*)(&class_name::class##class_name))
55
56
????#define?RUNTIME_CLASS(class_name)?(class_name::GetThisClass()) ?1
//header?file
?2
????protected:?
?3
????????static?CRuntimeClass*?PASCAL?_GetBaseClass();?
?4
????public:?
?5
????????static?CRuntimeClass?classCStroke;?
?6
????????static?CRuntimeClass*?PASCAL?GetThisClass();?
?7
????????virtual?CRuntimeClass*?GetRuntimeClass()?const;?
?8
????????static?CObject*?PASCAL?CreateObject();
?9
????????AFX_API?friend?CArchive&?AFXAPI?operator>>(CArchive&?ar,?CStroke*?&pOb);
10
//implement?file
11
????//static
12
????static?CObject*?PASCAL?CStroke::CreateObject()
13
????
{
14
????????return?new?CStroke;
15
????}
16
????//static
17
????static?CRuntimeClass*?PASCAL?CStroke::GetThisClass();
18
????
{?
19
????????return?((CRuntimeClass*)(&CStroke::classCStroke))
20
????}
21
????//static
22
????static?CRuntimeClass*?PASCAL?CStroke::_GetBaseClass()?
23
????
{?
24
????????return?(CObject::GetThisClass());
25
????}
26
????//static
27
????static?AFX_COMDAT?CRuntimeClass?CStroke::classCStroke?=?
28
????
{
29
????????"CStroke"
30
????????,?sizeof(class?CStroke)
31
????????,?1
32
????????,?CStroke::CreateObject
33
????????,?&class_name::_GetBaseClass
34
????????,?NULL
35
????????,?&_init_CStroke?
36
????};?
37
????CRuntimeClass*?CStroke::GetRuntimeClass()?const
38
????
{?
39
????????return?((CRuntimeClass*)(&CStroke::classCStroke));?
40
????}
41
????extern?struct?AFX_CLASSINIT?_init_CStroke;
42
????struct?AFX_CLASSINIT?_init_CStroke
43
????
{
44
????????void?AFXAPI?AfxClassInit(CRuntimeClass*?CStroke)
45
????????
{
46
????????????AFX_MODULE_STATE*?pModuleState?=?AfxGetModuleState();
47
????????????AfxLockGlobals(CRIT_RUNTIMECLASSLIST);
48
????????????pModuleState->m_classList.AddHead(CStroke);
49
????????????AfxUnlockGlobals(CRIT_RUNTIMECLASSLIST);
50
????????}
51
????};
52
????CArchive&?AFXAPI?operator>>(CArchive&?ar,?class_name*?&pOb)?
53
????
{?
54
????????pOb?=?(CStroke*)?ar.ReadObject(RUNTIME_CLASS(CStroke));
55
????????return?ar;?
56
????} 總結,一旦RUNTIME_CLASS(CStroke)由#define RUNTIME_CLASS(class_name) (class_name::GetThisClass())也就是CStroke::GetThisClass() 即
CStroke::classCStroke =
?{
??"CStroke"
??, sizeof(class CStroke)
??, 1
??, CStroke::CreateObject
??, &class_name::_GetBaseClass
??, NULL
??, &_init_CStroke
?}
其中,由extern AFX_CLASSINIT _initCStroke可知_init_CStroke是一個結構體AFX_CLASSINIT的對象,此結構體有構造函數:
?1
void?AFXAPI?AfxClassInit(CRuntimeClass*?pNewClass);
?2
????struct?AFX_CLASSINIT
?3
????????
{?AFX_CLASSINIT(CRuntimeClass*?pNewClass)?
{?AfxClassInit(pNewClass);?}?};
?4
?5
????void?AFXAPI?AfxClassInit(CRuntimeClass*?pNewClass)
?6
????
{
?7
????????AFX_MODULE_STATE*?pModuleState?=?AfxGetModuleState();
?8
????????AfxLockGlobals(CRIT_RUNTIMECLASSLIST);
?9
????????pModuleState->m_classList.AddHead(pNewClass);
10
????????AfxUnlockGlobals(CRIT_RUNTIMECLASSLIST);
11
????} 所以一旦返回classCStroke,也就調用了_init_CStroke的構造函數即將類CStroke添加到了全局變量m_classList類的List中了,同時在變量classCStroke中,也可以得到類CStroke的名稱、大小、一個CStroke的對象、類CStroke的基類以及AFX_CLASSINIT結構的一個對象。