Overview
From MFC to ATL, there is a lot of Map ing mechanisms, and it seems that the Map mechanism is not enough. Event ing exists in the WebBrower control, and custom function ing exists in IDispatch in COM.
In the past, as long as we talked about the ing mechanism, it always left me alone and left for self-protection. For the time being, remember it. Now I want to think about it, as long as it is a different hurdle, if you do not face it seriously and solve it, it will never be insurmountable, and it will always be a pain in my heart. In the end, we can only bind ourselves to our sole promise. Since God has given me another chance, I will seize this opportunity.
The vigorous opening remarks are over. Let's return to the topic: "ing mechanism"
Map format of Windows messages
The map code is as follows:
BEGIN_MSG_MAP(CTestDialog)MESSAGE_HANDLER(WM_INITDIALOG, OnInitDialog)MESSAGE_HANDLER(WM_CLOSE, OnClose)MESSAGE_HANDLER(WM_DESTROY, OnDestroy)END_MSG_MAP()
It is actually composed of three define statements, as shown below:
#define BEGIN_MSG_MAP(theClass) \public: \BOOL ProcessWindowMessage(_In_ HWND hWnd, _In_ UINT uMsg, _In_ WPARAM wParam,\_In_ LPARAM lParam, _Inout_ LRESULT& lResult, _In_ DWORD dwMsgMapID = 0) \{ \BOOL bHandled = TRUE; \(hWnd); \(uMsg); \(wParam); \(lParam); \(lResult); \(bHandled); \switch(dwMsgMapID) \{ \case 0:
#define MESSAGE_HANDLER(msg, func) \if(uMsg == msg) \{ \bHandled = TRUE; \lResult = func(uMsg, wParam, lParam, bHandled); \if(bHandled) \return TRUE; \}
#define END_MSG_MAP() \break; \default: \ATLASSERT(FALSE); \break; \} \return FALSE; \}
We can see that the map macro in the header file is indeed composed of three define statements. In essence, it defines a ProcessWindowMessage function. In
#define MESSAGE_HANDLER(msg, func) \
, Msg and func are selected by the user, so these two parameters are exposed. If three parameters are selected by the user, three parameters will be exposed.
In general, the last parameter is the function name or function address, and its previous parameters are generally its parameters. In this way, only one macro can be used to solve all input parameters of the same number and type, but different operations can be generalized function calls, that is, the ing mechanism in the program.
Usually, a ing word has an illumination meaning and is a verb. In mathematics, ing is a term that refers to the relationship between elements in two element sets and nouns. It also refers to the action of "forming a ing.
(From Baidu encyclopedia)
To put it bluntly, it is a corresponding relationship. It is so simple and there is nothing to say.
Template Class Map format
In the header file, we define the ing relationships in the following format:
BEGIN_XXX_MAP (CClassName)
XXX_ENTRY (String1, Identify1, OnFunctionName1)
XXX_ENTRY (String2, Identify2, OnFunctionName2)
......
XXX_ENTRY (StringN, IdentifyN, OnFunctionNameN)
END_XXX_MAP ()
Now we can understand that the OnFunctionName function requires the String and Identify variables. If there is such a XXX_ENTRY, there will be a corresponding function, and it will become a function container for the time being.
At this time, we will think of two cases to explain a function container:
One is: the "Windows message ing" mentioned above, which only maps messages and functions one by one, makes the program more expressive and hides unnecessary code. And the corresponding relationship is relatively simple, it is a proxy of class function pointers.
Another is: if a function is used as a function container, it is used to poll each function in the container in the corresponding template class to determine whether to use a function with a specific code. It no longer acts as a proxy role, but more often it acts as a member variable array role.
The advantage of doing so is that the template class can process the array more flexibly to achieve specific processing results. Data and functions are liberated and processed separately. We have distinct responsibilities.
Note:
(1) define the GetMap () function
It is generally modified by const staic, and its return value is a pointer to the template array. In this way, you only need to use T: GetMap to reference the GetMap in the function, because it is a static function! The following is a struct for saving and displaying the relationship between the three variables:
template
struct ST_XXX_ENTRY{typedef void(T::*Function_Name)();LPSTR string;UINT identify;Function_Name func;static void ProcessFunc1(){//...}static void ProcessFunc2(){// ...}};
Struct is important, but here it is more important to show the static functions between the three variables.
The map instantiation code is as follows:
# Define BEGIN_XXX_MAP (theClassName) \ static const ST_XXX_ENTRY
* GetMap () \ {\ static ST_XXX_ENTRY
TheMap [] ={# define XXX_ENTRY (string, identify, func) \ {string, identify, & theClassName: func }, /// the method for getting the class function pointer is applied here # define END_XXX_MAP () \ {NULL, 0, ST_XXX_ENTRY
: Function_Name (NULL )}\}\}
(2) Call the GetMap Function
The parent class template defines how to use the function ing relationships in GetMap. At this time, the call must directly use T: GetMap () to obtain the pointer of the static container, and then traverse and filter it, in order to obtain the processing result of the corresponding function or corresponding function.
So far, we have basically finished How to associate map, instantiate map, and define variables in struct. The more you write, the more you feel. The more you write, the more you understand the mysteries of the map mechanism.
Customer (Interface) Code
The Customer Code uses the map macro code, which inherits a template class, And the instance class required by the template class is the customer class. Why is it like this?
In fact, the reason is very simple, because the template class here is to extract the public functions and uniformly process the conversion relationships in the map macro, so as to streamline the customer code. The customer class can be defined according to the way the customer wants to define. If you want to name a class name, you are free to name the class name. The only thing you need to do is inherit the template class and add the corresponding relationship you like. You can use either the function name or the id you want to use, because map instantiation only references the function pointer, it has nothing to do with the name. It's cool. It's cool ".
In other words, not all template classes can accommodate various classes and unify the processing process. In practice, we once again felt the advantages of the template, or its mission:
(1) templates are more helpful for compiling. We only need to create a generic version of the class or function, rather than manually creating a dedicated version;
(2) templates are type-safe. Since the template operation type is known during compilation, the compiler can perform a type check before an error occurs;
(3) The template is easier to understand because information can be extracted directly through the template. (Of course, this is true. If you only view the template, it will be abstract. If you instantiate an object through the template, the extracted information will become visualized and easy to understand .)
I picked these three advantages from msdn, but it turned a little bit more clear, making the subject clearer (after all, translate e-text, and the benevolent sees benevolence ).
Now, I have finished the ing mechanism. All the Windows ing mechanisms in Windows are similar.
I did not think that I wrote so much. But I really feel that after writing this blog, I feel relieved about the ing mechanism, and I have never been more comfortable. I feel that writing a blog is a good deep learning experience. Only in the process of writing will you feel that kind of feeling.