AO中接口的一般使用方法(转)
AO中接口的一般使用方法(转)
我们通过实例来学习在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\") [Page]
#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> [Page]
{
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) [Page]
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); [Page]
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); [Page]
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++) [Page]
{
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); [Page]
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*> [Page]
(sp.p);
if (pISceneGraphEvents != NULL)
ret = pISceneGraphEvents->AfterDraw(pViewer);
} return ret;
}
};
#endif
posted on 2009-08-14 23:54 kisstome88 阅读(807) 评论(0) 编辑 收藏 举报