代码改变世界

金山卫士UI原理解析(1)

2011-08-15 19:46  Clingingboy  阅读(1568)  评论(1编辑  收藏  举报

 

Skin结构图

image

一.CBkObject

有点跟CObject,可以根据类名结合宏来动态创建Skin

#define BKOBJ_DECLARE_CLASS_NAME(theclass, classname)   \
public:                                                 \
    static theclass* CheckAndNew(LPCSTR lpszName)       \
    {                                                   \
        if (strcmp(GetClassName(), lpszName)  == 0)     \
            return new theclass;                        \
        else                                            \
            return NULL;                                \
    }                                                   \
                                                        \
    static LPCSTR GetClassName()                        \
    {                                                   \
        return classname;                               \
    }                                                   \
                                                        \
    virtual LPCSTR GetObjectClass()                     \
    {                                                   \
        return classname;                               \
    }                                                   \
                                                        \
    virtual BOOL IsClass(LPCSTR lpszName)               \
    {                                                   \
        return strcmp(GetClassName(), lpszName)  == 0;  \
    }          

CheckAndNew方法用来动态创建Skin

二.CBkSkinBase

定义了控件的Skin基类,定义了一个Draw方法,这个好比css样式一般,Draw方法来定义各个控件的呈现样式

三.根据xml载入skin样式

这里以button为例子,xml示例

<skins>
       <button name="normalbtn" border="7D9EBC" bg="FBFCFD" bgup="FEFEFE" bgdown="C6E2FD" 
          bguphover="FEFEFE" bgdownhover="DBEDFE" bguppush="C6E2FD" bgdownpush="FEFEFE"/>
</skins>

四.给载入的xml属性赋值

这次再次使用宏

#define BKWIN_DECLARE_ATTRIBUTES_BEGIN()                            \
public:                                                             \
    virtual HRESULT SetAttribute(                                   \
        CStringA strAttribName,                                     \
        CStringA strValue,                                          \
        BOOL     bLoading)                                          \
    {                                                               \
        HRESULT hRet = __super::SetAttribute(                       \
            strAttribName,                                          \
            strValue,                                               \
            bLoading                                                \
            );                                                      \
        if (SUCCEEDED(hRet))                                        \
            return hRet;                                            \

#define BKWIN_DECLARE_ATTRIBUTES_END()                              \
            return E_FAIL;                                          \
                                                                    \
        return hRet;                                                \
    }     

然后根据不同数据类型,定义多个赋值的宏

// DWORD = %u StringA
#define BKWIN_DWORD_ATTRIBUTE(attribname, varname, allredraw)       \
        if (attribname == strAttribName)                            \
        {                                                           \
            varname = (DWORD)::StrToIntA(strValue);                 \
            hRet = allredraw ? S_OK : S_FALSE;                      \
        }                                                           \
        else                                                        \

// StringA = StringA
#define BKWIN_STRING_ATTRIBUTE(attribname, varname, allredraw)      \
        if (attribname == strAttribName)                            \
        {                                                           \
            varname = strValue;                                     \
            hRet = allredraw ? S_OK : S_FALSE;                      \
        }                                                           \
        else  

Button控件示例

class CBkSkinButton : public CBkSkinBase
{
    BKOBJ_DECLARE_CLASS_NAME(CBkSkinButton, "button")
public:
    CBkSkinButton()
        : m_crBorder(RGB(0x70, 0x70, 0x70))
        , m_crBg(RGB(0xEE, 0xEE, 0xEE))
        , m_crBgUpNormal(RGB(0xEE, 0xEE, 0xEE))
        , m_crBgUpHover(RGB(0xEE, 0xEE, 0xEE))
        , m_crBgUpPush(RGB(0xCE, 0xCE, 0xCE))
        , m_crBgDownNormal(RGB(0xD6, 0xD6, 0xD6))
        , m_crBgDownHover(RGB(0xE0, 0xE0, 0xE0))
        , m_crBgDownPush(RGB(0xC0, 0xC0, 0xC0))
    {

    }

    virtual void Draw(CDCHandle dc, CRect rcDraw, DWORD dwState)
    {
     …     
} protected: COLORREF m_crBg; COLORREF m_crBorder; COLORREF m_crBgUpNormal; COLORREF m_crBgUpHover; COLORREF m_crBgUpPush; COLORREF m_crBgDownNormal; COLORREF m_crBgDownHover; COLORREF m_crBgDownPush; public: BKWIN_DECLARE_ATTRIBUTES_BEGIN() BKWIN_COLOR_ATTRIBUTE("bg", m_crBg, TRUE) BKWIN_COLOR_ATTRIBUTE("border", m_crBorder, TRUE) BKWIN_COLOR_ATTRIBUTE("bgup", m_crBgUpNormal, TRUE) BKWIN_COLOR_ATTRIBUTE("bguphover", m_crBgUpHover, TRUE) BKWIN_COLOR_ATTRIBUTE("bguppush", m_crBgUpPush, TRUE) BKWIN_COLOR_ATTRIBUTE("bgdown", m_crBgDownNormal, TRUE) BKWIN_COLOR_ATTRIBUTE("bgdownhover", m_crBgDownHover, TRUE) BKWIN_COLOR_ATTRIBUTE("bgdownpush", m_crBgDownPush, TRUE) BKWIN_DECLARE_ATTRIBUTES_END() };

五.重写Draw方法

这里不列代码了,这样一个控件的整个skin流程就完成了,当然其相关方法还需要其他地方来调