I. Entrance function mechanism (program initiation mechanism)
Language Summary:
3.1 Constructing Theapp Object Cwinapp::cwinapp ()
1) Save the &theapp to the current program module status information
2) Save the &theapp to the current program thread state information
3) Afxgetapp/afxgetthread-back to &theapp
3.2 Program Flow (WinMain)
1) Get &theapp with Afxgetapp/afxgetthread
2) Invoking application class member virtual functions with &theapp
InitApplication (Initialize)
3) Invoking application class member virtual functions with &theapp
InitInstance (Create, display window)
4) Invoking application class member virtual functions with &theapp
Run (message loop)
4.1 Calling application class member virtual functions with &theapp
OnIdle (Idle processing)
4.2 Calling application class member virtual functions with &theapp
ExitInstance (Aftercare)
Pseudo code:
Afx_module_state aaa;//Current Program module status information
Afx_module_thread_state bbb;//Current Program thread state information
Constructing Theapp objects
Cwinapp::cwinapp (...)
{
afx_module_state* Pmodulestate=afxgetmodulestate ()
Get global variable &aaa
afx_module_thread_state* pthreadstate = pmodulestate->m_thread;
2
Get global variable &BBB
Pthreadstate->m_pcurrentwinthread = this;
Save &theapp to a member of the global variable BBB
Afxgetthread ()
{
afx_module_thread_state* pState = Afxgetmodulethreadstate ();
Get global variable &BBB
cwinthread* PThread = pstate->m_pcurrentwinthread;
Get &theapp
return pThread;
}
Pmodulestate->m_pcurrentwinapp = this;
Save &theapp to a member of the global variable AAA
AfxGetApp ()
{
Return Afxgetmodulestate ()->m_pcurrentwinapp;
}
}
****************************************
Experience is not the Theapp object guidance process.
WinMain (...)
{
Afxwinmain (...)
{
cwinthread* pThread = Afxgetthread ();
cwinapp* papp = AfxGetApp ();//The above two sentences get &theapp
Papp->initapplication ();
Call CWinApp class member virtual function (initialize) with Theapp object
Pthread->initinstance ();
Invoking a member virtual function of an application class with a Theapp object
Pthread->run ()
Invoking a member virtual function (message loop) of an application class with a Theapp object
{
Cwinthread::run ()//function internal this is &theapp
{
while (no message)
{
This->onidle (...); /Application class member virtual function (idle processing)
}
Do
{
If (GetMessage caught Wm_quit)
return ExitInstance ();
Application class member virtual function (aftercare)
3
}while (...)
}
}
}
}
Second, the window creation mechanism
Language Summary:
1 Loading Menus
2 Call CreateEx Register window class, create window
2.1 Calling PreCreateWindow to design and register the window class
Wndclass wndcls;
....
Wndcls.lpfnwndproc = DefWindowProc;
Finally call the Win32 API function registerclass Register a window class
2.2 Calling the Afxhookwindowcreate function
1) Save Pframe (your own New Frame class object address) to the current program
The thread information.
2) Use:: SetWindowsHookEx function to bury a hook in the program,
The type is WH_CBT.
2.3 Using the Win32 API function:: CreateWindowEx Create window, this function
Once the trigger hook handler function is executed
3 Hook handler function
3.1 Create your own new Frame class object address and window handle one-to-one
The binding relationship.
M_hwnd = hWnd-the window handle can be obtained by pframe
M_permanentmap[hwnd] = pframe
Pframe can be obtained by window handle
3.2 Using the Win32 API function:: SetWindowLong The window handler function more
Change to AfxWndProc (real window processing function)
Pseudo code:
_afxwndframeorview=== "AFXFRAMEORVIEW42SD"
Cmyframewnd *pframe = new Cmyframewnd;
Pframe->create (NULL, "mfccreate")//function internal this is pframe
{
Load Menu
CreateEx (..., NULL:) Inside the function this is pframe
{
4
CREATESTRUCT cs;
Cs.lpszclass = null;//below will change
......
Cs.hinstance = AfxGetInstanceHandle ();
PreCreateWindow (CS)
{
Afxdeferregisterclass (...)
{
Wndclass wndcls;
....
Wndcls.lpfnwndproc = defwindowproc;//Bottom Change
_afxregisterwithicon (&wndcls, "AFXFRAMEORVIEW42SD")
{
&wndcls->lpszclassname = "AFXFRAMEORVIEW42SD";
AfxRegisterClass (&WNDCLS)
{
:: RegisterClass (&WNDCLS);
}
}
}
Cs.lpszclass = "AFXFRAMEORVIEW42SD";
}
Afxhookwindowcreate (pframe)//parameter for self new Frame class object address
{
_afx_thread_state* pthreadstate = _afxthreadstate.getdata ();
Get global variable &CCC (current program thread information)
:: SetWindowsHookEx (WH_CBT ...);
Bury a hook of type WH_CBT in the program
Pthreadstate->m_pwndinit = pframe;
Save your new Frame class object address pframe to a member of the CCC
}
:: CreateWindowEx (...); /This function once executed wm_create message appears
The hook is immediately hooked to the hook handler function.
}
}
*********************************************************
Hook handler function
_afxcbtfilterhook (... wParam.)
{
_afx_thread_state* pthreadstate = _afxthreadstate.getdata ();
Get global variable &CCC
cwnd* Pwndinit = pthreadstate->m_pwndinit;
Get Pframe===pwndinit from the CCC
HWND hwnd = (HWND) wparam;//get window Handle
5
Pwndinit->attach (HWND)//function internal this is Pframe===pwndinit
{
chandlemap* PMap = Afxmaphwnd (TRUE)
{
afx_module_thread_state* pState = Afxgetmodulethreadstate ();
Get global variable &BBB
Pstate->m_pmaphwnd = new Chandlemap (...);
Save the new map class object address in a member of BBB
Return pstate->m_pmaphwnd;
}
Pmap->setpermanent (m_hwnd = hWnd, pframe)
Inside the function this is PMAP (Map class object address)
{
M_permanentmap[hwnd] = pframe;
}
}
WNDPROC AfxWndProc = Afxgetafxwndproc ();
Get the address of the AFXWNDPROC function
:: SetWindowLong (HWnd, GWL_WNDPROC, (DWORD) afxwndproc);
Change the window handler function to AfxWndProc (real window processing function)
}
***************************************************
Take wm_create message as an example
AfxWndProc (...)
{
cwnd* pWnd = cwnd::fromhandlepermanent (hWnd)
{
chandlemap* PMap = Afxmaphwnd ()
{
afx_module_thread_state* pState = Afxgetmodulethreadstate ();
Get &BBB
Return pstate->m_pmaphwnd;
Returns the address of the mapped class object saved above
}
PWnd = (cwnd*) pmap->lookuppermanent (hWnd)
Inside the function this is PMAP (Map class object address)
{
return m_permanentmap[hwnd];//Get Pframe
}
}
Afxcallwndproc (PWnd ...) Pwnd===pframe of parameters
{
Pwnd->windowproc (...)
{
6
Go back to your code
}
}
}
Third, message mapping mechanism
Language Summary:
1 use of the message mapping mechanism
1) class must derive from the CCmdTarget class
2) The Declaration macro must be added within the class Declare_message_map ()
3) Implement macros must be added outside the class
Begin_message_map (Theclass, BaseClass)
End_message_map ()
Implementation of 2 message mapping mechanism
2.1 Data Structures
struct Afx_msgmap_entry (static array per element type)
{
UINT nmessage; Message ID
UINT NCode; Notification code
UINT NID; Command ID/control ID.
UINT Nlastid; Last control ID
UINT NSig; Types of Message handler functions
Afx_pmsg PFN; Address of the message handler function (pointer)
};
struct Afx_msgmap (static variable type)
{
Const afx_msgmap* pbasemap;//
Const afx_msgmap_entry* lpentries;//
};
2.2 Macro Expansion
See Code
2.3 Macro Expand the role of each part
_messageentries[]-static array
Each element holds a pointer to the message-handler function corresponding to the message ID
Messagemap-Static variables
Responsible for getting the parent class static variable address (link list)
The first address of the static array that is responsible for obtaining the corresponding class
Getmessagemap ()-Virtual function
Get the static variable address of this class (Get the link header node)
2.4 Execution of the message-mapping mechanism
7
1) Call Getmessagemap using the Framework class object (Pframe) to get the linked list
Head node (this class static variable address) Pmessagemap
2) Use the second member of Pmessagemap to get the static number of the corresponding class
Group header address, finding the message ID in the array corresponding to the handler function pointer
If 4 is found, if no execution 3 is found
3) Use the first member of Pmessagemap to get the parent class static variable address
If NULL, the end lookup, if not NULL, is performed 2
4) Use the sixth member of this array element found
(Message handler address) completes the processing of the message.
Classification of two MFC messages
1 Windows Standard Example: keyboard/mouse/timer ....
On_wm_xxx
2 Custom Messages
#define Wm_mymessage Wm_user+n
On_message
3 command Message (WM_COMMAND)
On_command
On_command_range (start ID, termination ID, processing function)
Pseudo code:
Take the WM_CREATE message as an example (think about the point Wm_command/wm_paint)
AfxWndProc (...)
{
cwnd* pWnd = cwnd::fromhandlepermanent (hWnd);
Gets the Frame class object address (Pframe===pwnd) bound together with HWND
Afxcallwndproc (pWnd.) Parameter Pwnd===pframe
{
Pwnd->windowproc (...) Inside the function this is Pframe===pwnd
{
Onwndmsg (...) Inside the function this is Pframe===pwnd
{
Const afx_msgmap* PMESSAGEMAP = Getmessagemap ();
Get the Link header node (this class static variable address)
afx_msgmap_entry* Lpentry;
for (; Pmessagemap! = null;//Traversal list find something
Pmessagemap = Pmessagemap->pbasemap)
{
Lpentry = Afxfindmessageentry
(Pmessagemap->lpentries,message ...);
if (lpentry! = NULL)
{
Goto Ldispatch;
}
}
Ldispatch:
8
Union Messagemapfunctions MMF;
MMF.PFN = lpentry->pfn;//Get &oncreate
int nSig = LPENTRY->NSIG;//AFXSIG_LWL
Switch (NSIG)
{
Case AFXSIG_LWL:
LResult = (THIS->*MMF.PFN_LWL) (WParam, LParam);
Break
.....
}
}
}
}
}
Iv. Runtime class information (CRuntimeClass)
1 run-time class information mechanism function
The program can get information about the object related classes during the execution.
(whether the object belongs to this class)
2 run-time class information mechanism usage
Class 2.1 must derive from CObject
Declare macros must be added within class 2.2 declare_dynamic
Implementation macro must be added outside of class 2.3 implement_dynamic
CObject::IsKindOf-You can tell if an object belongs to a class
3 implementation of runtime class information mechanism
3.1 Data structures
struct CRuntimeClass (static variable type)
{
LPCSTR m_lpszclassname;//class Name
int m_nobjectsize; Class size sizeof
UINT M_wschema; Version 0XFFFF of the class
cobject* (pascal* m_pfnCreateObject) ();
The dynamic creation mechanism is used, and the runtime class information mechanism is NULL
Cruntimeclass* M_pbaseclass;
Parent static variable address (for connecting linked list)
Cruntimeclass* m_pnextclass;//is null
};
3.2 Macro-Expanded Code
See Code
3.3 Macro Expand the role of each part
9
Classcdog-Static variables
To save information about a class such as: Class size/name/version.
Getruntimeclass ()-Virtual function
Gets the address of the static variable of this class (the linked list head node)
3.4 The execution process of IsKindOf function
Use this class of objects Yellowdog call virtual functions Getruntimeclass get
Static variable address of this class (linked table head node)
Use this type of static variable address to match the target if the equivalence proof object
belongs to the class, if not equal to the loop comparison
As long as there is an equal proof object belonging to the class during the cycle comparison, the loop
The end is not equal. proves that the object does not belong to this class
**************
Runtime_class (Theclass)-The static variable address of the class inside the parentheses
(&theclass::classtheclass)
Pseudo code:
No
V. Dynamic creation (essentially the new object)
Usually programmatically, programmers use system classes to create objects, calling member functions to complete
Related functions. With dynamic creation, the system's code can create a programmer-defined class of
object, in other words, the underlying code can create objects of the upper class.
Language Summary:
2 use
Creates a class object without knowing the name of the class.
2 use
Class 2.1 must derive from the CObject class
Declare macros must be added within class 2.2 declare_dyncreate
Implementation macro must be added outside of class 2.3 implement_dyncreate
Cruntimeclass::createobject-Dynamically creating class objects
3 implementation
3.1 Difference (and runtime class information mechanism comparison)
Classcdog-Static variables
The fourth member is no longer null and the address of a static function is saved
The difference between functions
One more static function CreateObject
3.2 Effects
CreateObject ()-Static function
New an object of the Cdog class and returns the object address
Classcdog-Static variables
Save the address of the newly added static function CreateObject in the fourth
10
Members of
Getruntimeclass ()-Virtual function
Gets the static variable address of this class (Cdog) (The Chain header node)
3.3 Cruntimeclass::createobject Execution Process
1) Use the fourth member of this class of static variables (Classcdog)
2) Save new Add static function in call member (Cdog::createobject)
Completes the creation of the object (this function internally new a Cdog class of
Object and returns the object address)
Pseudo code:
Dynamic creation mechanism
cobject* Pobject=runtime_class (Cdog)->createobject () {
Inside the function The this pointer is &classcdog---the node of the linked header
cobject* pobject = NULL;
Pobject = (*m_pfncreateobject) ()//call a static variable fourth member
--->cdog::createobject
{
return new Cdog;
}
}
VI. serialization of objects
Serialization of two
The benefits of introducing the CArchive class: 1 You can set the buffer size for file read and write
2 Read and write various basic data types, no type conversions are required.
1 Concepts
Writes data to a file as a binary stream or read from a file.
2 use
2.1 Open or create a new file
CFile::Open
2.2 File read/write
2.2.1 Defining CArchive objects
2.2.2 Specific data read and write
Carchive::operator >> "read"
Carchive::operator << "Write"
2.2.3 Closing CArchive objects
Carchive::close
2.3 Closing files
CFile::Close
Serialization of three objects (sixth mechanism of MFC)
1 Concepts
11
Serialized object-The class information for the object and the object's member variable as a binary stream
The process of writing to a file in sequential mode.
(Runtime class information is required for serialization)
Deserialize object-Reads the class information from the file, creates the object, and then reads the file
Initializes the process of the newly created object by a member variable in the
(Dynamic creation is a sine qua non for serialization)
2 use
2.1 Defining classes that support serialization
2.1.1 Derived from the CObject class
2.1.2 Adding a serialized declaration macro and Implementation macro
2.1.3 overrides the virtual function serilize (), in the function that completes the data member of the class.
Serialization of
2.2 Read and Write objects
The arguments passed in to read and write objects are the addresses of objects, steps and read-write basic types
The same data.
3 principle-Pseudo-code
3.1 Expanding the structure of a macro
struct AFX_CLASSINIT
{
constructor function
Afx_classinit (cruntimeclass* pnewclass)
{
Afxclassinit (Pnewclass);
{
afx_module_state* pModuleState = Afxgetmodulestate ();
Afxlockglobals (crit_runtimeclasslist);
Saves the current run-time class information to the application's m_classlist linked list
Pmodulestate->m_classlist.addhead (Pnewclass);
Afxunlockglobals (crit_runtimeclasslist);
}
}
};
_init_cstudent is a global structure variable, and the type is a struct-body
Afx_classinit. Before entering the _tmain () function, the current class's
Run-time class information is saved to the M_classlist linked list of module state information
3.2 The process of writing to an object
Ar. WriteObject (POB);
{
Get run-time class information for the current class
cruntimeclass* pclassref = Pob->getruntimeclass ();
Writes information about the class of an object to a file
WriteClass (PCLASSREF);
{
12
Pclassref->store (*this);
{
Class name length
Word Nlen = (word) Lstrlena (m_lpszclassname);
Write version, class name length to file
Ar << (WORD) M_wschema << Nlen;
Write a class name to a file
Ar. Write (m_lpszClassName, nlen*sizeof (char));
}
}
Because of the virtual function mechanism, call the Cstudent::serialize () function,
Writes member variables of a class to a file sequentially
((cobject*) pOb)->serialize (*this);
{
CObject::Serialize (AR);
if (AR. IsStoring ())
{
ar<<m_strname<<m_nage;
}
...
}
}
3.3 The process of reading an object
Ar. ReadObject (Runtime_class (cstudent));
{
Get run-time class information for the current class
ReadClass (pclassrefrequested, &nschema, &obtag);
{
Cruntimeclass::load (*this, &nschema);
{
Ar >> wtemp;
Ar >> nlen;
Ar. Read (Szclassname, nlen*sizeof (char));
Szclassname[nlen] = ' + ';
Looping through the name of a class in a linked list to get runtime class information
for (PClass = pmodulestate->m_classlist; PClass! = NULL;
PClass = Pclass->m_pnextclass)
{
if (Lstrcmpa (szclassname, pclass->m_lpszclassname) = = 0)
{
Afxunlockglobals (crit_runtimeclasslist);
return pClass;
}
}
13
}
}
Creating objects Dynamically
POb = Pclassref->createobject ();
Initializes a new object using a member of a class read from a file
Pob->serialize (*this);
{
CObject::Serialize (AR);
{
...
Else
{
ar>>m_strname>>m_nage;
}
}
}
}
This article from the "Do not know the day" blog, declined to reprint!
Six major mechanisms of MFC