zoukankan      html  css  js  c++  java
  • ATL固有属性(CStockPropImpl)

    继承该类,派生类就可以支持一些固有属性

    一实现方法

    1.继承CStockPropImpl

    class ATL_NO_VTABLE CBullsEye :
        public CStockPropImpl<CBullsEye, IBullsEye, &IID_IBullsEye,
                          &LIBID_ATLINTERNALSLib>,
        ...
    

    2.虽然已经实现,如想对外开发访问属性,必须显示声明

    interface IBullsEye : IDispatch {
        const int DISPID_ALTERNATECOLOR = 1;
        const int DISPID_BEEP = 2;
        const int DISPID_CENTERCOLOR = 3;
        const int DISPID_RINGCOUNT = 4;
        const int DISPID_RINGVALUE = 5;
        const int DISPID_APPLICATION = 6;
        const int DISPID_PARENT = 7;
    
        [propput, bindable, requestedit, id(DISPID_BACKCOLOR)]
        HRESULT BackColor([in]OLE_COLOR clr);
        [propget, bindable, requestedit, id(DISPID_BACKCOLOR)]
        HRESULT BackColor([out,retval]OLE_COLOR* pclr);
        [propput, bindable, requestedit, id(DISPID_BACKSTYLE)]
        HRESULT BackStyle([in]long style);
        [propget, bindable, requestedit, id(DISPID_BACKSTYLE)]
        HRESULT BackStyle([out,retval]long* pstyle);
        [propput, bindable, requestedit, id(DISPID_FORECOLOR)]
        HRESULT ForeColor([in]OLE_COLOR clr);
        [propget, bindable, requestedit, id(DISPID_FORECOLOR)]
        HRESULT ForeColor([out,retval]OLE_COLOR* pclr);
        [propput, bindable, requestedit, id(DISPID_ENABLED)]
        HRESULT Enabled([in]VARIANT_BOOL vbool);
        [propget, bindable, requestedit, id(DISPID_ENABLED)]
        HRESULT Enabled([out,retval]VARIANT_BOOL* pbool);
    };

    3.当属性发生变更时,可以有一个通知方法

    void CBullsEye::OnForeColorChanged( )
    {
    …
    } void CBullsEye::OnBackColorChanged( ) { …
    } void CBullsEye::OnBackStyleChanged( ) { …
    }

    4.必须为支持的固有属性提供成员变量

    public:
        OLE_COLOR                   m_clrBackColor;     // BackColor stock property
        OLE_COLOR                   m_clrForeColor;     // ForeColor stock property
        long                        m_nBorderStyle;     // BorderStyle stock property
        long                        m_nBorderWidth;     // BorderWidth stock property
        long                        m_nBackStyle;       // BackStyle stock property
        BOOL                        m_bEnabled;         // Enabled stock property

    变量名可以参考深入解析ATL

    二.内部实现

    HRESULT STDMETHODCALLTYPE get_Picture(IPictureDisp** ppPicture)
    {
        __if_exists(T::m_pPicture) 
        { 
            ATLTRACE(atlTraceControls,2,_T("CStockPropImpl::get_Picture\n"));
            ATLASSERT(ppPicture != NULL);
            if (ppPicture == NULL)
                return E_POINTER;
    
            T* pT = (T*) this;
            *ppPicture = pT->m_pPicture;
            if (*ppPicture != NULL)
                (*ppPicture)->AddRef();
        }
        return S_OK;
    }

    CStockPropImpl使用__if_exists来判断子类是否存在这个字段,缺点就是即使变量写错了,编译器也无法判断错误

    附__if_exists && __if_not_exists用法

    The __if_exists statement tests whether the specified identifier exists. If the identifier exists, the specified statement block is executed.

    跟if语句不同,if必须是字段存在的且为1的情况下,__if_exists只是判断字段是否存在而已,并不在意是否为true或者false

    // the__if_exists_statement.cpp
    // compile with: /EHsc
    #include <iostream>
    
    template<typename T>
    class X : public T {
    public:
       void Dump() {
          std::cout << "In X<T>::Dump()" << std::endl;
    
          __if_exists(T::Dump) {
             T::Dump();
          }
    
          __if_not_exists(T::Dump) {
             std::cout << "T::Dump does not exist" << std::endl;
          }
       }   
    };
    
    class A {
    public:
       void Dump() {
          std::cout << "In A::Dump()" << std::endl;
       }
    };
    
    class B {};
    
    bool g_bFlag = true;
    
    class C {
    public:
       void f(int);
       void f(double);
    };
    
    int main() { 
       X<A> x1;
       X<B> x2;
    
       x1.Dump();
       x2.Dump();
    
       __if_exists(::g_bFlag) {
          std::cout << "g_bFlag = " << g_bFlag << std::endl;
       }
       
    
       __if_exists(C::f) {
          std::cout << "C::f exists" << std::endl;
       }
    
       return 0;
    }
    

    使用宏定义

    IMPLEMENT_STOCKPROP(LONG, BackStyle, nBackStyle, DISPID_BACKSTYLE)
    IMPLEMENT_STOCKPROP(LONG, BorderStyle, nBorderStyle, DISPID_BORDERSTYLE)
    IMPLEMENT_STOCKPROP(LONG, BorderWidth, nBorderWidth, DISPID_BORDERWIDTH)
    

    我们可以看下IMPLEMENT_STOCKPROP宏的实现

    #define IMPLEMENT_STOCKPROP(type, fname, pname, dispid) \
        HRESULT STDMETHODCALLTYPE put_##fname(type pname) \
        { \
            __if_exists(T::m_##pname) \
            { \
                ATLTRACE(ATL::atlTraceControls,2,_T("CStockPropImpl::put_%s\n"), #fname); \
                T* pT = (T*) this; \
                if (pT->m_nFreezeEvents == 0 && pT->FireOnRequestEdit(dispid) == S_FALSE) \
                    return S_FALSE; \
                pT->m_##pname = pname; \
                pT->m_bRequiresSave = TRUE; \
                if (pT->m_nFreezeEvents == 0) \
                    pT->FireOnChanged(dispid); \
                __if_exists(T::On##fname##Changed) \
                { \
                    pT->On##fname##Changed(); \
                } \
                pT->FireViewChange(); \
                pT->SendOnDataChange(NULL); \
            } \
            return S_OK; \
        } \
        HRESULT STDMETHODCALLTYPE get_##fname(type* p##pname) \
        { \
            __if_exists(T::m_##pname) \
            { \
                ATLTRACE(ATL::atlTraceControls,2,_T("CStockPropImpl::get_%s\n"), #fname); \
                ATLASSERT(p##pname != NULL); \
                if (p##pname == NULL) \
                    return E_POINTER; \
                T* pT = (T*) this; \
                *p##pname = pT->m_##pname; \
            } \
            return S_OK; \
        }

    其中还会判断是否定义了属性变更事件

    三.自定义属性

    1.先声明IDL文件

    interface IBullsEye : IDispatch {
        const int DISPID_ALTERNATECOLOR = 1;
        const int DISPID_BEEP = 2;
        const int DISPID_CENTERCOLOR = 3;
        const int DISPID_RINGCOUNT = 4;
        const int DISPID_RINGVALUE = 5;
        const int DISPID_APPLICATION = 6;
        const int DISPID_PARENT = 7;
    
           [propget, bindable, requestedit, id(DISPID_CENTERCOLOR), helpstring("property CenterColor")]
        HRESULT CenterColor([out, retval] OLE_COLOR* pVal);
        [propput, bindable, requestedit, id(DISPID_CENTERCOLOR), helpstring("property CenterColor")]
        HRESULT CenterColor([in] OLE_COLOR newVal);
    
        };

    2.手动实现get,put方法

    STDMETHODIMP CBullsEye::get_CenterColor(OLE_COLOR *pVal)
    {
        if( pVal == 0 ) return E_POINTER;
    
        *pVal = m_clrCenterColor;
        return S_OK;
    }
    
    STDMETHODIMP CBullsEye::put_CenterColor(OLE_COLOR newVal)
    {
        if( m_clrCenterColor == newVal ) return S_OK;
    
        if(!m_nFreezeEvents)
        {
            if( FireOnRequestEdit(DISPID_CENTERCOLOR) == S_FALSE )
            {
                return S_FALSE;
            }
        }
    
        m_clrCenterColor = newVal;             // Save new color
        ::DeleteObject(m_centerBrush);         // Clear old brush color
        m_centerBrush = 0;
    
        m_bRequiresSave = TRUE;                // Set dirty flag
        if( !m_nFreezeEvents )
        {
            FireOnChanged(DISPID_CENTERCOLOR); // Notify container of change
        }
        FireViewChange( );                     // Request redraw
        SendOnDataChange(0);                   // Notify advise sinks of change
        return S_OK;
    }

    get,put实现几乎与固有属性实现一致,所以也可以直接用宏IMPLEMENT_STOCKPROP在头文件中实现

    3.属性与控件呈现

    有些属性改变需要重绘UI,那么就需要调用FireViewChange方法

    4.关于FireOnChanged、FireOnRequestEdit、FireViewChange等方法的实现

    CComControlBase和CComControl提供了这些辅助方法来实现,所以子类还需要继承CComControl

  • 相关阅读:
    一个比喻理解进程和线程的区别
    python蛋疼的编码decode、encode、unicode、str、byte的问题都在这了
    python类中__unicode__和__str__方法的妙用
    python re 正则提取中文
    一个python爬虫协程的写法(gevent模块)
    python 中range和xrange的区别
    python 监控oracle 数据库
    Spring security 知识笔记【自定义登录页面】
    Spring security 知识笔记【内存角色授权】
    Spring security 知识笔记【入门】
  • 原文地址:https://www.cnblogs.com/Clingingboy/p/2112211.html
Copyright © 2011-2022 走看看