How to create an object through a string under VC6

xiaoxiao2021-03-06  70

In the programming process, it is possible to encounter the corresponding object to create a corresponding object according to the incoming string, which can be implemented under VC7, and the MFC is not implemented in VC6.

Everyone must first understand that the key to realize dynamic creation in the MFC is that the CruntimeClass class can refer to "in-depth light-out MFC", nonsense, first look at the CruntimeClass class.

The following functions have been added in the CRUNTIMECLASS class in the VC7:

Struct cruntimeclass

{

...

// Dynamic Name Lookup and Creation

Static Cruntimeclass * Pascal fromName (LPCSTR LPSZCLASSNAME);

Static CruntimeClass * Pascal fromName (lpcwstr lpszclassname);

Static COBJECT * PASCAL CREATEOBJECT (LPCSTR LPSZCLASSNAME);

Static COBJECT * PASCAL CREATEOBJECT (LPCWSTR LPSZCLASSNAME);

...

}

Function definition:

// Runtime Class Serialization Code

COBJECT * PASCAL CRUNTIMECLASS :: CreateObject (lpcstr lpszclassname)

{

// Attempt to Find Matching Runtime Class Structure

CruntimeClass * PCLASS = fromname (lpszclassname);

IF (PCLASS == NULL)

{

// NOT Found, Trace A Warning for Diagnostic Purposes

TRACE (TraceAppmsg, 0, "Warning: Cannot Find% HS CRUNTIMECLASS. CLASS Not Defeed./N",

Lpszclassname);

Return NULL;

}

// attempt to create the Object with the found cruntimeclass

COBJECT * POBJECT = PCLASS-> CREATEOBJECT ();

Return POBJECT;

}

COBJECT * PASCAL CRUNTIMECLASS :: CreateObject (lpcwstr lpszclassname)

{

Uses_Conversion;

Return Cruntimeclass :: CreateObject (W

2A

(lpszclassname);

}

Cruntimeclass * Pascal Cruntimeclass :: fromName (LPCSTR LPSZCLASSNAME)

{

CruntimeClass * PCLASS;

// Search App Specific Classes

AFX_MODULE_STATE * PModuleState = AFXGETMODULESTATE ();

AfxlockGlobals (crit_runtimeclasslist);

For (pclass = pmodules-> m_classlist; pclass! = null;

PCLASS = PCLASS-> M_PNEXTCLASS)

{

IF (lstrcmpa (lpszclassname, pclass-> m_lpszclassname) == 0)

{

AFXUNLOCKGLOBALS (crit_runtimeclasslist);

Return PCLASS;

}

}

AFXUNLOCKGLOBALS (crit_runtimeclasslist); # ifdef _afxdll

// Search Classes in Shared DLLS

AfxlockGlobals (crit_dynlinklist);

For (cdynlinklibrary * pdll = pmodulestate-> m_libraryList; pdll! = null;

PDLL = PDLL-> M_PNEXTDLL)

{

PCLASS = PDLL-> M_ClassList; PCLASS! = NULL;

PCLASS = PCLASS-> M_PNEXTCLASS)

{

IF (lstrcmpa (lpszclassname, pclass-> m_lpszclassname) == 0)

{

AfXunlockGlobals (crit_dynlinklist);

Return PCLASS;

}

}

}

AfXunlockGlobals (crit_dynlinklist);

#ENDIF

Return null; // NOT FOUND

}

Cruntimeclass * Pascal Cruntimeclass :: fromName (lpcwstr lpszclassname)

{

Uses_Conversion_ex;

LPCSTR PSZCLASSNAME = W

2A

_Ex (lpszclassname, _ATL_SAFE_ALLOCA_DEF_THRESHOLD);

IF (pszclassname == NULL)

Return NULL;

Return Cruntimeclass :: fromName (pszclassname);

}

In fact, in the Load function of the Cruntimeclass class in the VC6, you can find the figure of the fromName function, Microsoft is just extracting some of the code as a separate fromname function, see the load function below.

// Runtime Class Serialization Code

Cruntimeclass * Pascal Cruntimeclass :: Load (carchive & ar, uint * pwschemanum)

// loads a Runtime Class Description

{

...

// Search App Specific Classes

AFX_MODULE_STATE * PModuleState = AFXGETMODULESTATE ();

AfxlockGlobals (crit_runtimeclasslist);

For (pclass = pmodules-> m_classlist; pclass! = null;

PCLASS = PCLASS-> M_PNEXTCLASS)

{

IF (lstrcmpa (szclassname, pclass-> m_lpszclassname) == 0)

{

AFXUNLOCKGLOBALS (crit_runtimeclasslist);

Return PCLASS;

}

}

AFXUNLOCKGLOBALS (crit_runtimeclasslist);

#ifdef _AFXDLL

// Search Classes in Shared DLLS

AfxlockGlobals (crit_dynlinklist);

For (cdynlinklibrary * pdll = pmodulestate-> m_libraryList; pdll! = null;

PDLL = PDLL-> M_PNEXTDLL)

{

For (pclass = pdll-> m_classlist; pclass! = null; pclass = pclass-> m_pnextclass)

{

IF (lstrcmpa (szclassname, pclass-> m_lpszclassname) == 0)

{

AfXunlockGlobals (crit_dynlinklist);

Return PCLASS;

}

}

}

AfXunlockGlobals (crit_dynlinklist);

#ENDIF

TRACE1 ("Warning: Cannot Load% HS from archive. Class Not Defined./N",

szclassname;

Return null; // NOT FOUND

}

Let's take a look at the dynamic creation macro and serialization of the MFC:

I. Macro group creation in MFC:

#define declare_dyncreate (class_name)

#define import_dyncreate (class_name, base_class_name)

1.Declare_dyncreate expand:

protected:

Static cruntimeclass * pascal _getbaseclass ();

PUBLIC:

Static const AFX_DATA CRUNTIMECLASS CLASSCMYCLASS;

Virtual cruntimeclass * getruntimeclass () const;

Static COBJECT * PASCAL CREATEOBJECT ();

2. IMPLEMENT_DYNCREATE Expand:

COBJECT * PASCAL CMYCLASS :: CreateObject ()

{Return New CMYCLASS;

Cruntimeclass * Pascal CMYCLASS :: _ getBaseClass ()

{RETURN Runtime_class (CBaseClass);

AFX_COMDAT Const AFX_DATADEF CRUNTIMECLASS CMYCLASS :: ClassCMYCLASS =

{"CMYCLASS", SIZEOF (Class CMYCLASS), 0xFFFF, NULL, & CMYCLASS :: _ getBaseClass, null}

Cruntimeclass * CMYCLASS :: getruntimeclass () const

{RETURN Runtime_class (cmyclass);

Die. MFC Sequence Macro group:

#define declare_serial (class_name)

#define import_serial (class_name, base_class_name, wschema)

1.Declare_serial expand:

protected:

Static cruntimeclass * pascal _getbaseclass ();

PUBLIC:

Static AFX_DATA CRUNTIMECLASS CLASSCMYCLASS;

Virtual cruntimeclass * getruntimeclass () const;

Static COBJECT * PASCAL CREATEOBJECT ();

AFX_API Friend Carchive & Afxapi Operator >> (CARCHIVE & AR, CMYCLASS * & PO);

2. IMPLEMENT_SERIAL Expand:

COBJECT * PASCAL CMYCLASS :: CreateObject () {Return New CMYClass;

Cruntimeclass * Pascal CMYCLASS :: _ getBaseClass ()

{RETURN Runtime_class (CBaseClass);

AFX_COMDAT AFX_DATADEF CRUNTIMECLASS CMYCLASS :: ClassCMYClass =

{"CMYCLASS", SIZEOF (CLASS CMYCLASS), 1, CMYCLASS :: CreateObject, & CMYCLASS :: _ getBaseClass, null};

Cruntimeclass * CMYCLASS :: getruntimeclass () const

{RETURN Runtime_class (cmyclass);

AFX_CLASSINIT _INIT_CMYCLASS (Runtime_Class (CMYCLASS));

CARCHIVE & AFXAPI Operator >> (CARCHIVE & Ar, CMYCLASS * & PO)

{POB = (CMYCLASS *) ar.readObject (runtime_class (cmyclass)); Return Ar;}

These two key places affect dynamic creation in the two groups of macros are:

1. DeClare_DyncReate defines the CRUNTIMECLASSCMYCLASS as static const type; and defined in Declare_Serial is defined as static type, Declare_DyncReate does not need to modify M_PNextClass members in CRUntimeClass.

2. AFX_CLASSINIT_INIT_CLASS (Runtime_Class (CMYCLAS)) is defined in Implement_Serial; this is extremely critical to building a class information chain list. If there is no such thing, the m_pnextclass in CruntimeClass is useless.

in conclusion:

Use declare_dyncReate to determine the inheritance relationship of the class of the runtime, but there is no class information list.

With Implement_Serial, you can establish a runtime information chain list. With a class information list, you can query the corresponding class information according to the string, then create an object.

Routine download address:

http://cmmy.vicp.net/bbs/viewfile.asp?boardid=2&id=2035

转载请注明原文地址:https://www.9cbs.com/read-92077.html

New Post(0)