[Repost] SKIN Technology Implementation Framework (4)

xiaoxiao2021-03-06  22

Today is a bit empty, continue to write.

The last time we have already got a basic design, thereby determining that each window must have a class to correspond to it. The window species here is to distinguish between the Windows Class name of the window, the Class name is the same, the Class name is the same It is a window. This classification method and the type of window we have seen may have some differences. For example, a normal button, the class name, radio button, and check boxes are "Button". For this situation, we still use a class to correspond to these Window, and distinguish these different windows within the class.

In this way, we must write a class for each control window that needs to change the appearance. According to the object-oriented idea, we naturally think of extracting their public base classes, this is the public base class for CWIDGETHOOKBASE, all controls window processing classes, In fact, it is a C interface because it only contains a pure virtual function, below is its definition:

///

/// Abstract Base Class for Widget Hook

Class CWIDGETHOKBASE

{

PUBLIC:

Virtual Void Install (HWND HWIDGET) = 0; // Implement In CWIDGETHOOK

}

The only install function in this interface is used to enable the object to link the object to the window, which is SubclassWindow, which will be implemented in the inheritance class, then we say how to implement it. It is actually the control factories today, which is CWidgetFactory and its inheritance class. Here is a complete declaration and implementation of CWidgetFactory:

/

/// Abstract Factory Class for Widget Hooks. Create Hook Instances

Class CWIDGETFACTORY

{

protected:

Static CWidgetFactory * m_pinstance;

PUBLIC:

// Initialize the instance

CWidgetFactory ()

{

Atlassert (m_pinstance == null);

M_Pinstance = this;

}

// Get the Singleton Instance

Static CWidgetFactory * instance ()

{

Return M_Pinstance;

}

Virtual CWidgetHookBase * CreateWidget (LPCTSTR SZCLASS) = 0;

}

CWidgetFactory * CWidgetFactory :: m_pinstance = null;

CWidGetFactory uses two design patterns, Singleton mode, and Abstract Factory mode, which actually also includes Factory Method mode.

First look at the abstract factory mode, we hope that the control plant creates a different control window message processing class according to the name of the window Class. For the analog Mac system, these control window message processing classes include cmacbutton, cmaccombobox, cmactrackbar, etc .; for simulating KDE systems, CKDeButton, CKDECOMBOBOX, etc. In this way, we can define two CWIDGETFACTORY inheritance classes, called CMACFactory and CKDEFActory, generate these two series of objects, respectively. CWidgetFactory :: CREATEWIDGET is used to generate these objects, it is a pure virtual function, must be implemented in inheritance classes. CreateWidget accepts the name of the window Class as a parameter, returns the CWIDGETHOKBASE pointer, which is the base class of all control classes. In this way, each target factory is responsible for generating a series of objects, but for an application, there should be only one style, that is, there can be only one factory instance, single mode coming here, using Simplified Edition Singleton Mode, you need to declare an instance of inheritance class, and then get this unique instance through CWIDGETFACTORY static functions. There is no control here that cannot generate a second instance, but this is not a big problem.

Now look at the implementation of Factory, cmacfactory, complete code as follows:

Class CMACfactory: Public CWIDGETFACTORY

{

PUBLIC:

Virtual CWIDGETHOKBASE * CREATEWIDGET (LPCTSTR SZCLASS)

{

IF (LSTRCMPI (Szclass, "Button") == 0)

Return new cmacbutton;

Else IF (szcls, "# 32770") == 0) // Dialog

Return new cmacdialog;

ELSE IF (szcls, "listbox") == 0)

Return New CMACListBox;

Else IF (lstrcmpi (szclass, wc_tabcontrol) == 0)

Return new cmactabctrl;

Else IF (LSTRCMPI (Szclass, "# 32768") == 0) // Menu

Return new cmacmenu;

Else IF (LSTRCMPI (Szclass, "ComboBoX") == 0) // ComboBox

Return New CMACCOMBO;

Else IF (Lstrcmpi (Szclass, TrackBar_Class) == 0) // TrackBar

Return New cmactrackbar;

Return NULL;

}

}

Look at the code of the message hook, it is very simple.

Lresult Callback CMACSKIN :: HookProc (int Ncode, WParam WParam, LParam Lparam)

{

CWPSTRUCT CWPS;

IF (ncode == hc_action)

{

CopyMemory (& CWPS, (LPVOID) LPARAM, SIZEOF (CWPSTRUCT);

Switch (cwps.message)

{

Case WM_CREATE:

{

Char Szclass [MAX_PATH];

GetClassName (CWPS.HWND, SZCLASS, MAX_PATH);

CWIDGETHOKBASE * PWIDGET = NULL;

PWIDGET = CWIDGETFAACTORY :: Instance () -> CREATEWIDGET (SZCLASS);

IF (PWIDGET)

PWIDGET-> Install (cwps.hwnd);

}

Break;

}

}

Return Callnexthookex ((hHOOK) CMACSKIN :: M_HHHOOK, NCODE, WPARAM, LPARAM;

}

Regardless of CMACFactory or other factories, the implementation of the hook function is the same regardless of the different control class series. The implementation of the CWIDGETFActory inherited class is also very similar, just replacing some class names.

Today, the factory class and hooks are finished, may not be very clear, it can only be like this.

In fact, I see the code is the clearest.

. How to implement the control next time, including how to use the ATL / WTL infrastructure, it is my favorite part.

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

New Post(0)