ActiveX控件的MFC设计之旅-第12步 .

本文介绍如何通过重载MFC控件的方法实现属性的自定义展示,包括使用下拉列表显示枚举类型属性及通过对话框设置复杂属性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 在VB和类似的包容器在属性视图中显示控件的属性,特别是枚举类型的属性时,会有一个下拉按钮,当点击该按钮时,会弹出一个列表框,显示一些友好的文字,供用户选择。而对于某些特殊的属性,如字体等,还会弹出一个对话框来供用户设置属性。

要添加这种功能,你必须实现IPerPropertyBrowsing接口,
 typedef struct tagCALPOLESTR {
ULONG cElems;
OLECHAR ** pElems;
} CALPOLESTR;

typedef struct tagCADWORD {
ULONG cElems;
DWORD * pElems;
} CADWORD;

interface IPerPropertyBrowsing : IUnknown
{
HRESULT GetDisplayString(DISPID dispid, BSTR * lpbstr);
HRESULT MapPropertyToPage(DISPID dispid, CLSID *lpclsid);
HRESULT GetPredefinedStrings(DISPID dispid, CALPOLESTR *lpcasz, 
CADWORD *lpcadw);
HRESULT GetPredefinedValue(DISPID dispid, DWORD dwCookie,
VARIANT *lpvarOut);
}

幸运的是,在用MFC设计ActiveX控件时,COleControl已经帮我们实现了这个接口,我们只需要重载COleControl的一些函数就可以实现我们所需要的功能了。这些函数是
    virtual BOOL OnGetDisplayString(DISPID dispid, CString& strValue);
    virtual BOOL OnGetPredefinedStrings(DISPID dispid, CStringArray* pStringArray, CDWordArray* pCookieArray);
    virtual BOOL OnGetPredefinedValue(DISPID dispid, DWORD dwCookie, VARIANT* lpvarOut);
    virtual BOOL OnMapPropertyToPage(DISPID dispid, LPCLSID lpclsid, BOOL* pbPageOptional);

分别和IPerPropertyBrowsing的四个接口方法一一对应。其中,前三个就是用来显示友好文字的列表框式的属性设置的,最后一个则是用来显示属性页对话框式的属性设置的。

注:VB首先查询控件的IPerPropertyBrowsing接口,以获得一个属性的显示字符串。当查询失败时,如果可能的话,VB会装载类型库并找到在IDL文件中为这个属性指定的枚举值。如果再次失败,VB会显示实际属性值。

1.建立控件Tppb,添加属性long Week
2.添加连续的7个字符串资源
IDS_WEEK_MONDAY,IDS_WEEK_TUESDAY,......IDS_WEEK_SUNDAY;
相应的字符串分别是
星期一,星期二,......星期日。
3.重载OnGetDisplayString,OnGetPredefinedStrings和OnGetPredefinedValue。

BOOL CTppbCtrl::OnGetDisplayString(DISPID dispid, CString& strValue)
{
    // TODO: Add your specialized code here and/or call the base class
    if(dispid == dispidWeek){
        strValue.LoadString(IDS_WEEK_MONDAY+m_week);
        return TRUE;
    }
    return COleControl::OnGetDisplayString(dispid, strValue);
}

BOOL CTppbCtrl::OnGetPredefinedStrings(DISPID dispid, CStringArray* pStringArray, CDWordArray* pCookieArray)
{
    // TODO: Add your specialized code here and/or call the base class
    if(dispid == dispidWeek){
        for(int i=0; i<7; i++){
            CString str;
            str.LoadString(IDS_WEEK_MONDAY+i);
            pStringArray->Add(str);
            pCookieArray->Add(i);
        }
        return TRUE;
    }
    return COleControl::OnGetPredefinedStrings(dispid, pStringArray, pCookieArray);
}

BOOL CTppbCtrl::OnGetPredefinedValue(DISPID dispid, DWORD dwCookie, VARIANT* lpvarOut)
{
    // TODO: Add your specialized code here and/or call the base class
    if(dispid == dispidWeek){
        VariantInit(lpvarOut);
        lpvarOut->vt = VT_I4;
        //和dwCookie一一对应,0号位值就是0,......,6号位的值就是6
        lpvarOut->lVal = dwCookie;
        return TRUE;
    }
    return COleControl::OnGetPredefinedValue(dispid, dwCookie, lpvarOut);
}

4.在VB中测试就可以看到Week属性会列出从星期一到星期日共七个选项的列表选择框。

5.添加属性long Param和固有属性Caption

6.新建一属性页(资源为IDD_PROPPAGE_TEST,类为CTestPropPage),属性页中只有一个编辑框IDC_EDIT_CAPTION,和固有属性Caption关联。(新建属性页的步骤不详述,请参考本系列其它文章)


7.重载OnMapPropertyToPage以在设置Param属性时显示对话框

BOOL CTppbCtrl::OnMapPropertyToPage(DISPID dispid, LPCLSID lpclsid, BOOL* pbPageOptional)
{
    // TODO: Add your specialized code here and/or call the base class
    if(dispid == dispidParam){
        *lpclsid = CTestPropPage::guid;
        *pbPageOptional = TRUE;
        return TRUE;
    }
    return COleControl::OnMapPropertyToPage(dispid, lpclsid, pbPageOptional);
}
注:为什么不在属性页中设置Param属性,而是Caption属性呢,主要是想解释一下,从哪个属性设置中弹出属性页和在该属性页中设置哪个属性并无关联,你也可以在弹出的属性页对话框中设置多个属性。

8.简单修饰一下控件,为控件添加一些初始值

void CTppbCtrl::OnResetState()
{
    COleControl::OnResetState();  // Resets defaults found in DoPropExchange

    // TODO: Reset any other control state here.
    m_week = 0;
    m_param = 0;
}

9.可以在VB下测试了



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值