activex控件编程:Win32编程点滴 - 简单ActiveXControl控件的使用



  虽然这里.net气氛到处充斥着像MVC、WPF、WorkFlow、LINQ等各种niubility术语但我们使用Windows还是由COM技术主宰着;我们在选择日常使用软件Software时也会避免使用.net开发软件Software即便是.net桌面也会经常使用ActiveXControl控件这篇文章就让我们用最原始方式来使用ActiveX不使用任何MFC,ATL等框架也不使用编译器提供#import的类指令也不使用任何ide提供向导

  像OLE、ActiveX等COM术语即便是微软也说不清它们关系所以下面说我也这样模棱两可下去只要明白意思即可

  首先要了解是ActiveX技术是为了做“嵌入”这样功能而诞生比如:在Word中插入张Bitmap图片双击此图片Word会画笔功能来编辑图片整个Word菜单栏也会变成画笔菜单栏所以ActiveXControl控件相当复杂有着几十个相关接口简单说来ActiveXControl控件父窗口被称为“容器”所以作为ActiveXControl控件使用者来说要实现接口基本上都是IOleXXXXContainer或IOleXXXXSite的类;而ActiveX则实现了IOleXXXXObject等接口在这些接口中大多有“InPlace”这个术语是“InPlace edit”也就是Word通过双击图片画笔编辑图片就称为“InPlace edit”(仅仅了解和这篇文章说使用AcitveXControl控件无关)

  在这样篇文章中我并不想讲很多COM或者AcitveX知识只是讲使用ActiveX所必须涉及接口然后你就可以去查MSDN中其他些可选接口来步步对这个ActiveX加强控制

  作为个最简单我们需要实现接口有:IOleClientSite和IOleInPlaceSite使用到AcitveX提供接口有:IOleObject和IOleInPlaceObject创建ActiveXControl控件步骤:

  创建个类实现IOleClientSite和IOleInPlaceSite

  使用CoCreateInstance创建相应ActiveXControl控件例子并获取它IOleObject接口指针

  IOleObject::SetClientSite传入第步中指针

  IOleObject::DoVerb完成ActiveXControl控件创建

  的后可以ActiveXControl控件IOleInPlaceObject::SetObjectRects调整Control控件大小和位置

  根据以上步骤创建如下:

HRESULT CreateAxControl(HWND hWnd,const wchar_t * ProgId,IUnknown ** ppControlUnknown,IUnknown ** ppContainerUnknown);

  第个参数hWnd是父窗口句柄ProgId是ActiveXControl控件ProgId我们不使用编译器#import般不知道所要创建Control控件CLSIDppControlUnknown是用来返回ActiveXControl控件IUnknown指针ppContainerUnknown是用来返回用来代表父窗口IUnknown指针

  代码如下(这里代码去除了出错处理):

HRESULT CreateAxControl(HWND hWnd,const wchar_t * ProgId,IUnknown ** ppControlUnknown,IUnknown ** ppContainerUnknown)
{
  HRESULT hr;
  CLSID cls;
  IOleObject * pObject = NULL;
  CControlContainer * pContainer = NULL;
  //通过ProgId得到CLSID 
  CLSIDFromProgID(ProgId,&cls); 
   
  //创建ActiveXControl控件对象顺便得到IOleObject指针 
  CoCreateInstance(cls,NULL,CLSCTX_INPROC_SERVER|CLSCTX_INPROC_HANDLER|CLSCTX_LOCAL_SERVER, 
    IID_IOleObject,(void**)&pObject); 
   
  //CControlContainer是实现了IOleClientSite和IOleInPlaceSite接口类 
  pContainer =  CControlContainer(hWnd); 
   
  //IOleObject::SetClientSite传入容器指针 
  pObject->SetClientSite(pContainer); 
   
  //IOleObject::DoVerb显示Control控件 
  pObject->DoVerb(OLEIVERB_SHOW,0,pContainer,0,hWnd,0); 
   
  //些返回参数 
  pObject->QueryInterface(IID_IUnknown,(void**)ppControlUnknown); 
  pContainer->QueryInterface(IID_IUnknown,(void**)ppContainerUnknown); 
 
   (pObject) pObject->Release; 
   (pContainer) pContainer->Release; 
   S_OK; 
} 


  CControlContainer类实现非常简单基本上IOleClientSite和IOleInPlaceSite接口大部分思路方法都只要简单返回S_OK或E_NOTIMPLE即可需要实现是IUnknown思路方法还有IOleWindow接口(IOleInPlaceSite继承于IOleWindow)GetWindow(返回父窗口句柄)代码如下:

 CControlContainer:public IOleClientSite,public IOleInPlaceSite
{
  HWND m_hWnd;
  ULONG m_refCnt;
public:
  CControlContainer(HWND hWnd)
  {
    m_hWnd = hWnd;
    m_refCnt = 1;
  }
  ~CControlContainer
  {
  }
  .... IUnknown实现
  //IOleControlSite 
  STDMETHOD(SaveObject) 
  { 
     E_NOTIMPL; 
  } 
  STDMETHOD(GetMoniker(DWORD,DWORD,IMoniker**)) 
  { 
     E_NOTIMPL; 
  } 
  STDMETHOD(GetContainer(IOleContainer **ppContainer)) 
  { 
     E_NOINTERFACE; 
  } 
  STDMETHOD(ShowObject) 
  { 
     S_OK; 
  } 
  STDMETHOD(OnShowWindow(BOOL bShow)) 
  { 
     S_OK; 
  } 
  STDMETHOD(RequestNewObjectLayout) 
  { 
     E_NOTIMPL; 
  } 
  //IOleWindow 
  STDMETHOD(GetWindow(HWND * pHwnd)) 
  { 
    *pHwnd = m_hWnd; 
     S_OK; 
  } 
  STDMETHOD(ContextSensitiveHelp(BOOL bEnterMode)) 
  { 
     S_OK; 
  } 
  //IOleInPlaceSite 
  STDMETHOD(CanInPlaceActivate) 
  { 
     S_OK; 
  } 
  STDMETHOD(OnInPlaceActivate) 
  { 
     S_OK; 
  } 
  STDMETHOD(OnUIActivate) 
  { 
     S_OK; 
  } 
  STDMETHOD(GetWindowContext(/* [out] */ IOleInPlaceFrame **ppFrame,
    /* [out] */ IOleInPlaceUIWindow **ppDoc,
    /* [out] */ LPRECT lprcPosRect,
    /* [out] */ LPRECT lprcClipRect,
    /* [out][in] */ LPOLEINPLACEFRAMEINFO lpFrameInfo))
  {
     E_NOTIMPL;
  }
  STDMETHOD(Scroll(SIZE scrollSize))
  {
     S_OK;
  }
  STDMETHOD(OnUIDeactivate(BOOL bUndoable))
  {
     S_OK;
  }
  STDMETHOD(OnInPlaceDeactivate)
  {
     S_OK;
  }
  STDMETHOD(DiscardUndoState)
  {
     S_OK;
  }
  STDMETHOD(DeactivateAndUndo)
  {
     S_OK;
  }
  STDMETHOD(OnPosRectChange(LPCRECT lprcPosRect))
  {
     S_OK;
  }
};


  接下来在父窗口窗口过程中上面实现创建个FlashControl控件:

IUnknown * g_pControl = NULL;//Control控件指针
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
  ....
  switch(message)
  {
   WM_CREATE:
    //FlashControl控件
    hr = CreateAxControl(hWnd,L"ShockwaveFlash.ShockwaveFlash",&pControl,&pContainer);
     (SUCCESSED(hr))
    {
      VARIANT src;
      src.vt = VT_BSTR;
      src.bstrVal = SysAllocString(L"http://www.google.com/l/en_ALL/images/logo.g");
      DispSetProperty(pControl,L"movie",&src);//这个实现请下载源代码
    }
    ;
   WM_SIZE:
    {  
      //调整Control控件大小      
      RECT rcClient;
      GetClientRect(hWnd,&rcClient);
      IOleInPlaceObject * pInPlaceObject;
       (g_pControl && 
        SUCCEEDED(g_pControl->QueryInterface(IID_IOleInPlaceObject,(void**)&pInPlaceObject)))
      {
        pInPlaceObject->SetObjectRects(&rcClient,&rcClient);
        pInPlaceObject->Release;
      }
    }
    ;
  }
  ....
}


  本文举例源代码或素材下载

Tags:  activex控件和插件 安装activex控件 activex控件 activex控件编程

延伸阅读

最新评论

发表评论