Overview of superclass
In MFC, the form instance provides the following two capabilities after a form handle is superclass:
1. When we call the member function for the form instance, the corresponding form of the corresponding form handle will be changed directly.
2. messages sent by the system to the corresponding form handle will first pass through the message ing of the form instance
Here is an example:
For example, I wrote a class named csuperedit (the parent class is cedit). In this class, I declared void onchar (uint nchar, uint nrepcnt, uint nflags ); the on_wm_char row is added to the message loop.
Now, I just need to declare csuperedit m_edit in the dialog box cprog1dlg; then add the following code in the cprog1dlg: oninitdialog to complete the "superclass ":
Hwnd hwndcontrol =: getdlgitem (pparent-> m_hwnd, idc_edit1 );
M_edit.subclasswindow (hwndcontrol );
After the supercategory processing:
When we call m_edit.setwindowtext ("<enter a, B, c> ");, the corresponding text on the idc_edit1 form is changed to "<enter A, B, and C>"
When you press the keyboard in the idc_edit1 form, the system will call the csuperedit: onchar function (instead of the original cedit: onchar function) That I wrote myself)
Implementation of superclass
All the secrets are in cwnd: subclasswindow. Let's check what it actually does. The following is the function body (in the wincore. cpp file ):
Bool cwnd: subclasswindow (hwnd)
{
If (! Attach (hwnd ))
Return false;
// Allow any other subclassing to occur
Presubclasswindow ();
// Now hook into the afx wndproc
Wndproc * lplpfn = getsuperwndprocaddr ();
Wndproc oldwndproc = (wndproc): setwindowlong (hwnd, gwl_wndproc, (DWORD) afxgetafxwndproc ());
Assert (oldwndproc! = (Wndproc) afxgetafxwndproc ());
Return true;
}
Presubclasswindow is a non-functional function, so we only need to study two functions to understand the approximate functions of cwnd: subclasswindow cwnd: attach and: afxgetafxwndproc.
In the two, cwnd: attach corresponds to function 1, that is, "When we call a member function on the form instance, the corresponding form of the corresponding form handle will be directly changed"
: The afxgetafxwndproc function corresponds to function 2, that is, "messages sent to the corresponding form handle first pass through the message ing of the form instance"
Function 1 Implementation
The function body of cwnd: attach is as follows (in the wincore. cpp file ):
Bool cwnd: attach (hwnd hwndnew)
{
If (hwndnew = NULL)
Return false;
Chandlemap * pmap = afxmaphwnd (true); // create map if not exist
Assert (pmap! = NULL );
Pmap-> setpermanent (m_hwnd = hwndnew, this );
Return true;
}
The most important thing is m_hwnd = hwndnew (anyone who has been familiar with Windows APIs knows that all form operation functions in Windows use the form handle as a call parameter ), obviously, as long as I save the form handle, I can specify a form in the system and perform operations on the form.
Yes, the idea is that simple. Now we can see that cwnd (don't forget that csuperedit is inherited from cwnd, and cwnd here is actually csuperedit) saves the idc_edit1 handle in the member variable m_hwnd in the attach function, then function 1 is implemented.
As for the chandlemap: setpermanent function, it is used to extend the use period of the handle, and it has nothing to do with "superclass". We will not discuss it here. For details about its implementation, refer to the winhand_.h file.
Function 2 Implementation
Gwl_wndproc attribute of the form handle
In the previous discussion, I mentioned that function 2 is related to: afxgetafxwndproc. The implementation of this function is like this (also in the wincore. cpp file ):
Wndproc afxapi afxgetafxwndproc ()
{
# Ifdef _ afxdll
Return afxgetmodulestate ()-> m_pfnafxwndproc;
# Else
Return & afxwndproc;
# Endif
}
This refers to the afxgetmodulestate ()-> m_pfnafxwndproc if it is called in the DLL; otherwise, the address of the afxwndproc function is returned. Therefore, in a general executable file, what cwnd: subclasswindow does for function 2 can be simplified to one line: setwindowlong (hwnd, gwl_wndproc, (DWORD) & afxwndproc );
This function is used to set the gwl_wndproc attribute of the form handle hwnd to the address of afxwndproc. The problem that needs to be solved now is: what is the gwl_wndproc attribute of the form handle? In fact, I don't need to say that everyone can guess (because we are discussing the form message, and I have been saying afxwndproc is a function ), it specifies the form message processing function.
This attribute is more accurately described as follows: For all messages sent to the form, the Windows operating system uses this message as the parameter to call the function specified by the gwl_wndproc attribute of the form handle.
Passed to the MFC Environment
(In this section, refer to "25,000 li changzheng" in the chapter "message ing and Command Transmission" in "deep dive into MFC ")
Function 2 can be expressed as: How does the afxwndproc function find the message ing I wrote for The csuperedit class? Or starting from the function body
Lresult callback afxwndproc (hwnd, uint nmsg, wparam, lparam)
{
// Special message which identifies the window as using afxwndproc
If (nmsg = wm_queryafxwndproc)
Return 1;
// All other messages route through message map
Cwnd * pwnd = cwnd: fromhandlepermanent (hwnd );
Return afxcallwndproc (pwnd, hwnd, nmsg, wparam, lparam );
}
As listed above: afxwndproc has only four rows. Obviously, it only wraps the: afxcallwndproc function. It just wraps the hwnd parameter into pwnd, and then converts it to: afxcallwndproc.
: Afxcallwndproc this function is actually doing something, but one of them has a direct relationship with message passing:
Lresult afxapi afxcallwndproc (cwnd * pwnd, hwnd, uint nmsg,
Wparam = 0, lparam = 0)
{
...
// Delegate to object ''' windowproc
Lresult = pwnd-> windowproc (nmsg, wparam, lparam );
...
Return lresult;
}
Now we can see that through the following two functions: afxwndproc/: afxcallwndproc, messages in the operating system are transmitted to the MFC environment.
Further discussions can focus on lresult cwnd: windowproc (uint message, wparam, lparam );
4.3: Conclusion
We can see the transfer: In order to implement different function calls, oop itself provides many methods such as inheritance and virtual functions. MFC is a language for objects.
Now csuperedit is inherited from cedit, and cedit is inherited from cwnd. It is no technical difficulty to have the program call csuperedit: onchar. For example, you can write a virtual function virtual void cwnd: onchar (uint nchar, uint nrepcnt, uint nflags) that responds to keyboard messages in cwnd :: calling onchar in windowproc
So as long as I reload the csuperedit: onchar function, the program will naturally call the function I wrote.
Microsoft has made some optimizations to reduce the volume of program files. It does not use virtual modifiers to modify all functions, instead, the "Response Message and corresponding response function" is registered in a message_map (called message ing.