[Repost] SKIN Technology Implementation Framework (5)

xiaoxiao2021-03-06  24

Connecting the above, the interface of the control class has: CWIDGETHOKBASE, the factory that generates the control object is also available, and the control class is implemented. When the upper section defines the base class class, we only define an abstract function install, without any other code, then all implementation code is handed over to each control class to implement? No, many public code can be implemented in the base class, however, we choose to join these code in CWIDGETHOKBASE, but add another middle class: CWIDGETHOK. Why don't you synthesize these two base classes? In fact, the original design is only one base class, which is CWIDGETHOOK, and we hope to use the WTL's packaging class for Windows controls in inheritance classes, which, according to the ATL / WTL architecture, CWIDGETHOOK must be a template class, and The template class cannot be used as a base category pointer because the template is uncertain, and our abstract factory model requires a base class pointer, so we have extracted a purexious interface class such as CWIDGETHOKBASE. The result is the structure shown below: The following is a statement of the CWIDGETHOOK template class:

///

/// base class for all Widget Hook

/// Parameters:

/// t

/// Derived Class

/// TBASE

/// Widget Window Wrapper, Use WTL Wrappers for Convenient

Template

Class CWIDGETHOK: PUBLIC CWIDGETHOKBASE, PUBLIC CWINDOWIMPL

It uses multiple inheritances here, which is common in ATL. The first parent class is the CWIDGETHOKBASE interface we defined earlier. We need this interface to implement abstract factory design model. The second parent class is CWINDOWIMP, which is defined by the ATL, which is the high-level parent class of all window classes (although not top). CWindowIMP receives two template parameters and is also a template parameter of CWIDGETHOOK. The first template parameter is inherited, which is also a technique that is often used in the ATL. This technique allows us to know the type of inheritance class in the parent class, so that the THIS pointer is enforced into the type of inheritance, you can call the inherit class. Method, this way achieves polymorphism similar to virtual functions, but does not need to pay the performance cost of virtual functions. This is also used to use the C template and come. It seems that there is such a usage in the ATL. There are many other weird skills that seem to be approximative. These are also the charm of C . Later language, such as Java, C # Although there are new progress in all aspects, it is really hard to find more than C , the truly exciting place is really hard to find. It's far away, continue to say our second template parameters. Tracking the ATL code, you can see that the TBASE parameter is ultimately as a base class, by changing the base class through template parameters, which is also a different place in OO. TBASE has a default CWindow, you can incorporate other classes here, but you must be a CWindow inheritance class, the most valuable parameters, of course, WTL window packaging classes, which, WTL can be used when implementing the control message processing class. The function provided by the packaging class does not need to rely on the Windows API, it is indeed a lot of help. I have finished the statement of CWIDGETHOOK, I'm really enough. Let's see the definition and implementation of CWIDGETHOK, first look at several functions declaration: void initialize () {}; // instance initialize

Void finalize () {}; // instance finalize

Static void initialization () {}; // Class Initialize

Static void finalizeclass () {}; // Class Finalize

The above four functions contain an empty implementation, which can be overloaded in the inheritance class. Heavy 12 non-virtual functions, use the template skills told above to achieve a similar virtual function, this is the new concept that template gives us. Initialize is called when each instance is generated, Finalize is called before the instance is destroyed; the static function initializeclass is called when generated in the first instance of the class, and FinalizeClass is called at the last instance of the class. Why have two static functions, because a class represents the same window, these windows use the same resources, such as Checkbox, need a few different status pictures, and these images are the same for each Checkbox, If you save such a resource for each instance, you have a waste of memory. For a SKIN plug-in, efficiency is still important, so we choose to keep these pictures with static variables, and load these resources when the first Checkbox is generated, and other CHECKBOXs that are subsequently generated can reuse these resources, and then in the last When a checkbox disappears, this resource is released, so that the amount of memory is optimized to the smallest. These two static functions are called in the constructor and the destructor, and there is another instance count value M_LREF, and there is not much to say. There is no onfinalMessage and install functions left below. OnfinalMessage is relatively simple, call Fianlize and delete yourself, because the cwindowimp inherited class, the onfinalMessage function is automatically called when the window is destroyed, so that the instance will be released by the instance, which will not cause memory leakage. It is also worth mentioning that when four functions mentioned above call Finalize, the THIS pointer is first converted to the pointer PT of the inheritance class T, and then calls on the PT pointer. This can achieve a polymorphic similar to virtual functions. This means is said to be more efficient than the use of virtual functions, but I should not be because I want to deliberate efficiency, but the That's the ATL WAY finally looks at the install function, this is The pure virtual function defined in CWIDGETHOKBASE, in the CWIDGETHOK template class, this function is implemented. The main function of the Install function is to call subclasswindow to obtain control of the window message. In addition, the operation of the control message reflection and the initialization example is also implemented. Here is its code: Virtual Void Install (HWND HWIDGET)

{

Atlassert (:: iswindow (hwidget));

SubclassWindow (HWIDGET);

// if it is a child window, install a reflector for ITS PARENT

// SO That The Parent Will Reflect Messages Back to Me

IF ((:: getwindowlong (hwidget, gwl_style) & ws_child) == ws_child)

{

HWND HWNDPARENT = :: getParent (hwidget);

Atlassert (:: iswindow (hwndparent));

// the wm_getreflector get the installed reflector, IF exists

CREFLECTHOOK * preflector =

(CREFLECTHOOK *) :: SendMessage (HWndParent, WM_GetReflector, 0, 0);

IF (! preflector)

NEW CREFLECTHOK (HWNDPARENT);

T * pt = static_cast (this);

Pt-> Initialize ();

}

A large piece of code in the middle is about the news reflection. It is said to be next time, today is long enough, and finally tell the initialize. In fact, you can see a design pattern: template method. The Install function is a template method, and the initialize method it calls to overload in the inheritance class. Then, the initialize method is an initialization function of the instance, why not placed in the constructor? Since the initialization of each instance may not be quite, to be determined according to the status of the hooked window, so after SubclassWindow is called, then the initialize method is called, in the initialize implementation of the inherited class, you can directly obtain the window handle through M_HWND Call the API or WTL package method to check the window status, and perform the necessary instance initialization code. Ok, today is almost the same, the remaining tail is next

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

New Post(0)