万星星@豌豆荚 欢迎加入我们
一个吃软饭的男人!!!!!我只想写程序####
微博:http://weibo.com/wanlianwen
posts - 172,  comments - 1253,  trackbacks - 0

我对ole技术的了解源于com技术的学习,认识源于windows os上多年的编程,而深入理解却来之多年的痛苦摸索、反复的体会,水到渠成的感觉终于有了。
记得很久以前有个人加我qq,说想学mfc,问有什么办法。我告诉它,得花2、3年时间才能入门,他说算了还是不学。我不知道是不是害了他,或者过早断送了他学习C++的路。小的时候很盼望长大,可以赚钱自立;记得学习编程的时候很希望自己能够入门。这种希望都变成了现时,自己走过的路只有自己清楚。有人说java好,有人说linux下编程来钱,有人说钻研技术没钱途,这些道理我明白只是自己可能并没有那么大梦想,或许很小的梦想都能满足我。
对于我这个年龄的青年来说,ole技术真的很晦涩难懂,这并不是自夸。记得以前在公司的时候,有个boss对com很了解。我本身不太爱问别人技术细节问题,但是崇拜之情下我找了他:做控件的时候如何强制控制控件的尺寸。得到的答案是:具体你看看里面的代码。当时我没有弄明白,只是暂时放弃。第二次是在研一的时候,问一个高级工程师(30多岁),如何在控件里面获取当前是设计时还是运行时。答案是:我回去看看在告诉你。结果是杳无音讯。我曾一度放弃com知识的进一步学习有一年,只是因为身边少了一个导师(在后来遇到了),或许自己很笨。
不多说了,下面来看技术吧。
问题是这样的:开发环境里面一般都是支持activex控件插入的,比如vb编辑器、vc编辑器、office系列产品,在mfc里面有ole文档。
假设我们要做一个activex容器,支持activex的插入、设计时属性编程的话,恐怕就需要一个载体(窗口),首先使其成为容器,支持插入,然后要提供idispatch接口为控件获取环境属性提供支持。为什么呢?我们首先来看看ATL.CComControlBase.GetAmbientUserMode方法:

HRESULT GetAmbientUserMode(BOOL& bUserMode)
    
{
        CComVariant var;
        HRESULT hRes 
= GetAmbientProperty(DISPID_AMBIENT_USERMODE, var);
        ATLASSERT(var.vt 
== VT_BOOL || FAILED(hRes));
        bUserMode 
= var.boolVal;
        
return hRes;
    }


进一步:

HRESULT GetAmbientProperty(DISPID dispid, VARIANT& var)
    
{
        HRESULT hRes 
= E_FAIL;
        
if (m_spAmbientDispatch.p != NULL)
            hRes 
= m_spAmbientDispatch.GetProperty(dispid, &var);
        
return hRes;
    }


其中m_spAmbientDispatch的获取是在这里:

inline HRESULT CComControlBase::IOleObject_SetClientSite(IOleClientSite *pClientSite)
{
    ATLASSERT(pClientSite 
== NULL || m_spClientSite == NULL);
    m_spClientSite 
= pClientSite;
    m_spAmbientDispatch.Release();
    
if (m_spClientSite != NULL)
    
{
        m_spClientSite
->QueryInterface(IID_IDispatch,
            (
void**&m_spAmbientDispatch.p);
    }

    
return S_OK;
}


也就是activex控件在放到自己窝里面的时候设置的。这样我们的容器就需要实现IDispatch以便控件查询环境属性。

// this for activex control AMBIENT query
STDMETHODIMP CActiveXCtrl::Invoke(
                  DISPID dispidMember, REFIID iid, LCID lcid,
                  WORD wFlags, DISPPARAMS
* pdpParams, VARIANT* pvarResult,
                  EXCEPINFO
* pExceptionInfo, UINT* piArgError)
{
    
if(dispidMember == DISPID_AMBIENT_USERMODE)
    
{
        VariantClear(pvarResult);
        pvarResult
->vt = VT_BOOL;
        pvarResult
->boolVal = VARIANT_FALSE;
        
return S_OK;
    }

    
return E_NOTIMPL;
}


这里只是简单的返回activex控件的用户模式为设计时。我有一个测试,代码如下:

HRESULT OnDraw(ATL_DRAWINFO& di)
    
{
        RECT
& rc = *(RECT*)di.prcBounds;
        Rectangle(di.hdcDraw, rc.left, rc.top, rc.right, rc.bottom);

        SetTextAlign(di.hdcDraw, TA_CENTER
|TA_BASELINE);
        BOOL bUserMode 
= FALSE;
        HRESULT hr 
= GetAmbientUserMode(bUserMode);
        
if(bUserMode)
        
{
            LPCTSTR pszText 
= _T("ATL 3.0 : UserMode");

            TextOut(di.hdcDraw, 
                (rc.left 
+ rc.right) / 2
                (rc.top 
+ rc.bottom) / 2
                pszText, 
                lstrlen(pszText));
        }

        
else
        
{
            LPCTSTR pszText 
= _T("ATL 3.0 : DesignMode");
            TextOut(di.hdcDraw, 
                (rc.left 
+ rc.right) / 2
                (rc.top 
+ rc.bottom) / 2
                pszText, 
                lstrlen(pszText));
        }


        
return S_OK;
    }


运行效果如下:

微软有一个控件叫owc11.chartspace.11,在设计时支持数据选择,而运行时不支持,来看看运行效果:



posted on 2007-05-13 08:57 万连文 阅读(2564) 评论(2)  编辑 收藏 引用 所属分类: ATL

FeedBack:
# re: OLE容器之环境属性支持
2007-05-13 17:33 | doodle
WOW 很详细, 仔细学习。。。

www.doodle8.cn 涂鸦基地,跟踪最新的 web2.0 资源  回复  更多评论
  
# re: OLE容器之环境属性支持
2014-07-01 12:52 | xuthus
你好,有没有研究过C#下的OLE容器设计。
我正在做这方面的项目,不知道你有没有兴趣,有报酬。
邮箱:xuthus@sina.com,随时联系我。  回复  更多评论
  

只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理


简历下载
联系我

<2006年3月>
2627281234
567891011
12131415161718
19202122232425
2627282930311
2345678

常用链接

留言簿(66)

随笔分类

随笔档案

相册

搜索

  •  

最新评论

阅读排行榜

评论排行榜