现在的位置: 首页 > 综合 > 正文

理解AO中的接口

2013年10月09日 ⁄ 综合 ⁄ 共 12006字 ⁄ 字号 评论关闭

    本文将通过介绍自定义接口的实例,解释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 _Module
extern 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

/////////////////////////////////////////////////////////////////////////////
// CZoomIn
class 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()

// IZoomIn
private:
    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"

/////////////////////////////////////////////////////////////////////////////
// CZoomIn
STDMETHODIMP 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

处理前

处理后

抱歉!评论已关闭.