理解AO中的接口

    技术2022-05-11  17

        本文将通过介绍自定义接口的实例,解释AO中接口的一般使用方法。这个实例是在VC 6.0下用ATL创建的一个COM。    COM的创建的主要步骤是:    1.实现esriSystemUI ICommand接口,使用户可以把这个组建模型加入ArcScene或其他工具栏上,在点击这个按钮的时候实现相关操作。    2.创建一个连接点实现ISceneGraphEvents接口事件,并改写fire事件的相关函数。我在Fire_BeforeDraw和Fire_AfterDraw中加了一些OpenGL的函数以实现雾化的效果。    3.回过头,我们具体实现ICommand接口。在ICommand的OnCreate函数中用ISceneHookHelper钩住IScene。在OnClick中我们通过ISceneHookHelper进一步获得ISceneViewer用来刷新场景。在刷新场景的前后分别调用Fire_BeforeDraw和Fire_AfterDraw来绘制雾化效果。这样ArcScene中的sink们就可以响应fire事件函数了。    主要流程是这样的:用户-->ArcScene-->ICommand接口-->自定义接口-->连接点-->fire事件-->OpenGL-->ArcScene。    工程名:Walkthrough1Cpp;自定义接口类:CZoomIn;代理接口事件类CProxyISceneGraphEvents    注意:在用ATL创建接口的时候,要在属性面板Interface中选择Custom而不是Dual,前者继承IUnkown,后者继承IDispatch。还要选择支持连接点。

    // stdafx.h : include file for standard system include files,//      or project specific include files that are used frequently,//      but are changed infrequently

    #if !defined(AFX_STDAFX_H__FF23B542_C904_4F39_8A97_C4DE3C45A0E6__INCLUDED_)#define AFX_STDAFX_H__FF23B542_C904_4F39_8A97_C4DE3C45A0E6__INCLUDED_

    #if _MSC_VER > 1000#pragma once#endif // _MSC_VER > 1000

    #define STRICT#ifndef _WIN32_WINNT#define _WIN32_WINNT 0x0400#endif#define _ATL_APARTMENT_THREADED

    #include <atlbase.h>//You may derive a class from CComModule and use it if you want to override//something, but do not change the name of _Moduleextern CComModule _Module;#include <atlcom.h>

    #pragma warning(push)#pragma warning(disable : 4146)#pragma warning(disable : 4192)#import "e:/Program Files/ArcGIS/com/esriSystem.olb" raw_interfaces_only raw_native_types no_namespace

    named_guids exclude("OLE_COLOR", "OLE_HANDLE", "VARTYPE")#import "e:/Program Files/ArcGIS/com/esriSystemUI.olb" raw_interfaces_only raw_native_types no_namespace

    named_guids#import "e:/Program Files/ArcGIS/com/esriGeometry.olb" raw_interfaces_only raw_native_types no_namespace

    named_guids#import "e:/Program Files/ArcGIS/com/esriDisplay.olb" raw_interfaces_only raw_native_types no_namespace

    named_guids#import "e:/Program Files/ArcGIS/com/esriGeoDatabase.olb" raw_interfaces_only raw_native_types

    no_namespace named_guids#import "e:/Program Files/ArcGIS/com/esriCarto.olb" raw_interfaces_only raw_native_types no_namespace

    named_guids#import "e:/Program Files/ArcGIS/com/esriControlCommands.olb" raw_interfaces_only raw_native_types

    no_namespace named_guids#import "e:/Program Files/ArcGIS/com/esriFramework.olb" raw_interfaces_only raw_native_types no_namespace

    named_guids#import "e:/Program Files/ArcGIS/com/esri3DAnalyst.olb" raw_interfaces_only raw_native_types no_namespace

    named_guids

    #pragma warning(pop) 

    #include "gl/gl.h"#include "gl/glu.h"#include "gl/glaux.h"#include <GL/glut.h>//{{AFX_INSERT_LOCATION}}// Microsoft Visual C++ will insert additional declarations immediately before the previous line.

    #endif // !defined(AFX_STDAFX_H__FF23B542_C904_4F39_8A97_C4DE3C45A0E6__INCLUDED)

     

     

    // ZoomIn.h : Declaration of the CZoomIn

    #ifndef __ZOOMIN_H_#define __ZOOMIN_H_

    #include "resource.h"       // main symbols#include "esri3DAnalystCP.h"//#import "D:/Program Files/ArcGIS/com/esriSystemUI.olb" raw_interfaces_only, raw_native_types,

    no_namespace, named_guids

    /// CZoomInclass ATL_NO_VTABLE CZoomIn :  public CComObjectRootEx<CComSingleThreadModel>, public CComCoClass<CZoomIn, &CLSID_ZoomIn>, public IZoomIn, public ICommand, public CProxyISceneGraphEvents< CZoomIn >, public IConnectionPointContainerImpl<CZoomIn>{public:  CZoomIn()  {    m_hBitmap = ::LoadBitmap(_Module.GetResourceInstance(), MAKEINTRESOURCE(IDB_ZOOMIN));  }

      ~CZoomIn()  {    DeleteObject(m_hBitmap);  }  IHookHelperPtr    m_ipHookHelper;  ISceneHookHelperPtr  m_ipSceneHookHelper;DECLARE_REGISTRY_RESOURCEID(IDR_ZOOMIN)

    DECLARE_PROTECT_FINAL_CONSTRUCT()

    BEGIN_COM_MAP(CZoomIn) COM_INTERFACE_ENTRY(IZoomIn) COM_INTERFACE_ENTRY(ICommand) COM_INTERFACE_ENTRY_IMPL(IConnectionPointContainer)END_COM_MAP()

    // IZoomInprivate:    HBITMAP    m_hBitmap;public:// ICommand STDMETHOD(get_Enabled)(VARIANT_BOOL * Enabled); STDMETHOD(get_Checked)(VARIANT_BOOL * Checked); STDMETHOD(get_Name)(BSTR * Name); STDMETHOD(get_Caption)(BSTR * Caption); STDMETHOD(get_Tooltip)(BSTR * Tooltip); STDMETHOD(get_Message)(BSTR * Message); STDMETHOD(get_HelpFile)(BSTR * HelpFile); STDMETHOD(get_HelpContextID)(LONG * helpID); STDMETHOD(get_Bitmap)(OLE_HANDLE * Bitmap); STDMETHOD(get_Category)(BSTR * categoryName); STDMETHOD(OnCreate)(IDispatch * hook); STDMETHOD(OnClick)();public :

    BEGIN_CONNECTION_POINT_MAP(CZoomIn) CONNECTION_POINT_ENTRY(IID_ISceneGraphEvents)END_CONNECTION_POINT_MAP()

    };

    #endif //__ZOOMIN_H_

     

     

    // ZoomIn.cpp : Implementation of CZoomIn#include "stdafx.h"#include "Walkthrough1Cpp.h"#include "ZoomIn.h"

    /// CZoomInSTDMETHODIMP CZoomIn::get_Enabled(VARIANT_BOOL * Enabled){ if (Enabled == NULL)      return E_POINTER;          *Enabled = VARIANT_TRUE;   // Enable the tool always

        return S_OK;

    }

    STDMETHODIMP CZoomIn::get_Checked(VARIANT_BOOL * Checked){ if (Checked == NULL)  return E_POINTER;   return E_NOTIMPL;}

    STDMETHODIMP CZoomIn::get_Name(BSTR * Name){if (Name == NULL)      return E_POINTER;

        *Name = ::SysAllocString(L"ZoomIn x 0.5 Cpp");    return S_OK;

    }

    STDMETHODIMP CZoomIn::get_Caption(BSTR * Caption){ if (Caption == NULL)      return E_POINTER;

        *Caption = ::SysAllocString(L"ZoomIn x 0.5 Cpp");    return S_OK;

    }

    STDMETHODIMP CZoomIn::get_Tooltip(BSTR * Tooltip){ if (Tooltip == NULL)  return E_POINTER;   return E_NOTIMPL;}

    STDMETHODIMP CZoomIn::get_Message(BSTR * Message){ if (Message == NULL)  return E_POINTER;   return E_NOTIMPL;}

    STDMETHODIMP CZoomIn::get_HelpFile(BSTR * HelpFile){ if (HelpFile == NULL)  return E_POINTER;   return E_NOTIMPL;}

    STDMETHODIMP CZoomIn::get_HelpContextID(LONG * helpID){ if (helpID == NULL)  return E_POINTER;   return E_NOTIMPL;}

    STDMETHODIMP CZoomIn::get_Bitmap(OLE_HANDLE * Bitmap){   if (Bitmap == NULL)      return E_POINTER;

        *Bitmap = (OLE_HANDLE) m_hBitmap;

        return S_OK;}

    STDMETHODIMP CZoomIn::get_Category(BSTR * categoryName){  if (categoryName == NULL)      return E_POINTER;

        *categoryName = ::SysAllocString(L"Developer Samples");    return S_OK;

    }

    STDMETHODIMP CZoomIn::OnCreate(IDispatch * hook){ m_ipSceneHookHelper.CreateInstance(CLSID_SceneHookHelper); HRESULT hr = m_ipSceneHookHelper->putref_Hook(hook);    return hr;

    }

    STDMETHODIMP CZoomIn::OnClick(){  // HRESULT checking omitted for clarity IScenePtr ipScene; m_ipSceneHookHelper->get_Scene(&ipScene); ISceneGraphPtr ipSceneGraph; ipScene->get_SceneGraph(&ipSceneGraph);

     

     ISceneViewer * pViewer; ipSceneGraph->get_ActiveViewer(&pViewer); Fire_BeforeDraw(pViewer, NULL); ipSceneGraph->RefreshViewers(); Fire_AfterDraw(pViewer);

            return S_OK;

    }

     

    // Walkthrough1Cpp.idl : IDL source for Walkthrough1Cpp.dll//

    // This file will be processed by the MIDL tool to// produce the type library (Walkthrough1Cpp.tlb) and marshalling code.

    import "oaidl.idl";import "ocidl.idl"; [  object,  uuid(5CA669DE-0DFE-4C49-8546-B8AE24A629D5),   helpstring("IZoomIn Interface"),  pointer_default(unique) ] interface IZoomIn : IUnknown { };

    [ uuid(5C0841D7-80E7-4CDB-AFCD-5D77B23B879E), version(1.0), helpstring("Walkthrough1Cpp 1.0 Type Library")]library WALKTHROUGH1CPPLib{ importlib("stdole32.tlb"); importlib("stdole2.tlb"); importlib("e:/Program Files/ArcGIS/com/esriSystemUI.olb"); [  uuid(C9265E95-7317-4CB2-9ACC-E3EA5C9CA550),  helpstring("ZoomIn Class") ] coclass ZoomIn {  [default] interface IUnknown;  interface IZoomIn;  interface ICommand;

    //  [default] interface IZoomIn; };};

     

     

    //esri3DAnalystCP.h#ifndef _ESRI3DANALYSTCP_H_#define _ESRI3DANALYSTCP_H_

    #import "E:/Program Files/ArcGIS/com/esri3DAnalyst.olb" raw_interfaces_only, raw_native_types,

    no_namespace, named_guids //"Import typelib"template <class T>class CProxyISceneGraphEvents : public IConnectionPointImpl<T, &IID_ISceneGraphEvents,

    CComDynamicUnkArray>{ //Warning this class may be recreated by the wizard.public: HRESULT Fire_ActiveViewerChanged(ISceneViewer * pViewer) {  HRESULT ret;  T* pT = static_cast<T*>(this);  int nConnectionIndex;  int nConnections = m_vec.GetSize();    for (nConnectionIndex = 0; nConnectionIndex < nConnections; nConnectionIndex++)  {   pT->Lock();   CComPtr<IUnknown> sp = m_vec.GetAt(nConnectionIndex);   pT->Unlock();   ISceneGraphEvents* pISceneGraphEvents = reinterpret_cast<ISceneGraphEvents*>

    (sp.p);   if (pISceneGraphEvents != NULL)    ret = pISceneGraphEvents->ActiveViewerChanged(pViewer);  } return ret;  } HRESULT Fire_ViewerAdded(ISceneViewer * pViewer) {  HRESULT ret;  T* pT = static_cast<T*>(this);  int nConnectionIndex;  int nConnections = m_vec.GetSize();    for (nConnectionIndex = 0; nConnectionIndex < nConnections; nConnectionIndex++)  {   pT->Lock();   CComPtr<IUnknown> sp = m_vec.GetAt(nConnectionIndex);   pT->Unlock();   ISceneGraphEvents* pISceneGraphEvents = reinterpret_cast<ISceneGraphEvents*>

    (sp.p);   if (pISceneGraphEvents != NULL)    ret = pISceneGraphEvents->ViewerAdded(pViewer);  } return ret;  } HRESULT Fire_ViewerRemoved(ISceneViewer * pViewer) {  HRESULT ret;  T* pT = static_cast<T*>(this);  int nConnectionIndex;  int nConnections = m_vec.GetSize();    for (nConnectionIndex = 0; nConnectionIndex < nConnections; nConnectionIndex++)  {   pT->Lock();   CComPtr<IUnknown> sp = m_vec.GetAt(nConnectionIndex);   pT->Unlock();   ISceneGraphEvents* pISceneGraphEvents = reinterpret_cast<ISceneGraphEvents*>

    (sp.p);   if (pISceneGraphEvents != NULL)    ret = pISceneGraphEvents->ViewerRemoved(pViewer);  } return ret;  } HRESULT Fire_InteractionStopped() {  HRESULT ret;  T* pT = static_cast<T*>(this);  int nConnectionIndex;  int nConnections = m_vec.GetSize();    for (nConnectionIndex = 0; nConnectionIndex < nConnections; nConnectionIndex++)  {   pT->Lock();   CComPtr<IUnknown> sp = m_vec.GetAt(nConnectionIndex);   pT->Unlock();   ISceneGraphEvents* pISceneGraphEvents = reinterpret_cast<ISceneGraphEvents*>

    (sp.p);   if (pISceneGraphEvents != NULL)    ret = pISceneGraphEvents->InteractionStopped();  } return ret;  } HRESULT Fire_RecordingStarted(BSTR Name) {  HRESULT ret;  T* pT = static_cast<T*>(this);  int nConnectionIndex;  int nConnections = m_vec.GetSize();    for (nConnectionIndex = 0; nConnectionIndex < nConnections; nConnectionIndex++)  {   pT->Lock();   CComPtr<IUnknown> sp = m_vec.GetAt(nConnectionIndex);   pT->Unlock();   ISceneGraphEvents* pISceneGraphEvents = reinterpret_cast<ISceneGraphEvents*>

    (sp.p);   if (pISceneGraphEvents != NULL)    ret = pISceneGraphEvents->RecordingStarted(Name);  } return ret;  } HRESULT Fire_RecordingStopped() {  HRESULT ret;  T* pT = static_cast<T*>(this);  int nConnectionIndex;  int nConnections = m_vec.GetSize();    for (nConnectionIndex = 0; nConnectionIndex < nConnections; nConnectionIndex++)  {   pT->Lock();   CComPtr<IUnknown> sp = m_vec.GetAt(nConnectionIndex);   pT->Unlock();   ISceneGraphEvents* pISceneGraphEvents = reinterpret_cast<ISceneGraphEvents*>

    (sp.p);   if (pISceneGraphEvents != NULL)    ret = pISceneGraphEvents->RecordingStopped();  } return ret;  } HRESULT Fire_BeforeDraw(ISceneViewer * pViewer, VARIANT_BOOL * pbHandled) {  ISceneGraphPtr ipSceneGraph;  pViewer->get_SceneGraph(&ipSceneGraph);

      IEnvelopePtr pExtent;  ipSceneGraph->get_Extent(&pExtent);       ICameraPtr pCamera;  pViewer->get_Camera(&pCamera);

      double Near;  double Far;  double Angle;  double m_aspect;

      pCamera->QueryViewingPlatformMBB(pExtent, &Near, &Far, &Angle, &m_aspect);

      glEnable(GL_FOG);  glFogf(GL_FOG_MODE, GL_LINEAR);  glFogf(GL_FOG_START, Near);  glFogf(GL_FOG_END, Far);

      float red = 0.8;  float green = 0.4;  float blue = 0.4;    GLfloat FogColor[4] = {red, green, blue, 1};  glFogfv(GL_FOG_COLOR, FogColor);

     

      HRESULT ret;  T* pT = static_cast<T*>(this);  int nConnectionIndex;  int nConnections = m_vec.GetSize();    for (nConnectionIndex = 0; nConnectionIndex < nConnections; nConnectionIndex++)  {   pT->Lock();   CComPtr<IUnknown> sp = m_vec.GetAt(nConnectionIndex);   pT->Unlock();   ISceneGraphEvents* pISceneGraphEvents = reinterpret_cast<ISceneGraphEvents*>

    (sp.p);   if (pISceneGraphEvents != NULL)    ret = pISceneGraphEvents->BeforeDraw(pViewer, pbHandled);  } return ret;  } HRESULT Fire_AfterDraw(ISceneViewer * pViewer) {    glDisable(GL_FOG);

      HRESULT ret;  T* pT = static_cast<T*>(this);  int nConnectionIndex;  int nConnections = m_vec.GetSize();    for (nConnectionIndex = 0; nConnectionIndex < nConnections; nConnectionIndex++)  {   pT->Lock();   CComPtr<IUnknown> sp = m_vec.GetAt(nConnectionIndex);   pT->Unlock();   ISceneGraphEvents* pISceneGraphEvents = reinterpret_cast<ISceneGraphEvents*>

    (sp.p);   if (pISceneGraphEvents != NULL)    ret = pISceneGraphEvents->AfterDraw(pViewer);  } return ret;  }};#endif

    处理前

    处理后


    最新回复(0)