void
CEx24cView::OnTestSpaceship()
{
CLSID clsid;
LPCLASSFACTORY pClf;
LPUNKNOWN pUnk;
IMotion * pMot;
IVisual * pVis;
HRESULT hr;
if ((hr = ::CLSIDFromProgID(L " Spaceship " , & clsid)) != NOERROR)
{
TRACE( " unable to find Program ID -- error = %x\n " , hr);
return ;
}
if ((hr = ::CoGetClassObject(clsid, CLSCTX_INPROC_SERVER,
NULL, IID_IClassFactory, ( void ** ) & pClf)) != NOERROR) {;
TRACE( " unable to find CLSID -- error = %x\n " , hr);
return ;
}
pClf -> CreateInstance(NULL, IID_IUnknown, ( void ** ) & pUnk);
pUnk -> QueryInterface(IID_IMotion, ( void ** ) & pMot); // All three
pMot -> QueryInterface(IID_IVisual, ( void ** ) & pVis); // pointers
// should work
TRACE( " main: pUnk = %p, pMot = %p, pDis = %p\n " , pUnk, pMot, pVis);
// Test all the interface virtual functions
pMot -> Fly();
int nPos = pMot -> GetPosition();
TRACE( " nPos = %d\n " , nPos);
pVis -> Display();
pClf -> Release();
pUnk -> Release();
pMot -> Release();
pVis -> Release();
AfxMessageBox( " Test succeeded. See Debug window for output. " );
}
{
CLSID clsid;
LPCLASSFACTORY pClf;
LPUNKNOWN pUnk;
IMotion * pMot;
IVisual * pVis;
HRESULT hr;
if ((hr = ::CLSIDFromProgID(L " Spaceship " , & clsid)) != NOERROR)
{
TRACE( " unable to find Program ID -- error = %x\n " , hr);
return ;
}
if ((hr = ::CoGetClassObject(clsid, CLSCTX_INPROC_SERVER,
NULL, IID_IClassFactory, ( void ** ) & pClf)) != NOERROR) {;
TRACE( " unable to find CLSID -- error = %x\n " , hr);
return ;
}
pClf -> CreateInstance(NULL, IID_IUnknown, ( void ** ) & pUnk);
pUnk -> QueryInterface(IID_IMotion, ( void ** ) & pMot); // All three
pMot -> QueryInterface(IID_IVisual, ( void ** ) & pVis); // pointers
// should work
TRACE( " main: pUnk = %p, pMot = %p, pDis = %p\n " , pUnk, pMot, pVis);
// Test all the interface virtual functions
pMot -> Fly();
int nPos = pMot -> GetPosition();
TRACE( " nPos = %d\n " , nPos);
pVis -> Display();
pClf -> Release();
pUnk -> Release();
pMot -> Release();
pVis -> Release();
AfxMessageBox( " Test succeeded. See Debug window for output. " );
}
// interface.h
struct
IMotion :
public
IUnknown
{
STDMETHOD_( void , Fly) () = 0 ;
STDMETHOD_( int & , GetPosition) () = 0 ;
};
struct IVisual : public IUnknown
{
STDMETHOD_( void , Display) () = 0 ;
};
{
STDMETHOD_( void , Fly) () = 0 ;
STDMETHOD_( int & , GetPosition) () = 0 ;
};
struct IVisual : public IUnknown
{
STDMETHOD_( void , Display) () = 0 ;
};
// Spaceship.h : header file
![ContractedBlock.gif](/Images/OutliningIndicators/ContractedBlock.gif)
![ExpandedBlockStart.gif](/Images/OutliningIndicators/ExpandedBlockStart.gif)
void ITrace(REFIID iid, const char* str);
/////
// CSpaceship command target
class CSpaceship : public CCmdTarget
{
DECLARE_DYNCREATE(CSpaceship)
private:
int m_nPosition; // We can access this from all the interfaces
int m_nAcceleration;
int m_nColor;
protected:
CSpaceship(); // protected constructor used by dynamic creation
// Attributes
public:
// Operations
public:
// Overrides
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CSpaceship)
public:
virtual void OnFinalRelease();
//}}AFX_VIRTUAL
// Implementation
protected:
virtual ~CSpaceship();
// Generated message map functions
//{{AFX_MSG(CSpaceship)
// NOTE - the ClassWizard will add and remove member functions here.
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
DECLARE_OLECREATE(CSpaceship)
BEGIN_INTERFACE_PART(Motion, IMotion)
STDMETHOD_(void, Fly) ();
STDMETHOD_(int&, GetPosition) ();
END_INTERFACE_PART(Motion)
BEGIN_INTERFACE_PART(Visual, IVisual)
STDMETHOD_(void, Display) ();
END_INTERFACE_PART(Visual)
DECLARE_INTERFACE_MAP()
};
// Spaceship.cpp : implementation file
![ContractedBlock.gif](/Images/OutliningIndicators/ContractedBlock.gif)
![ExpandedBlockStart.gif](/Images/OutliningIndicators/ExpandedBlockStart.gif)
//
// CSpaceship
// {692D03A4-C689-11CE-B337-88EA36DE9E4E}
static const IID IID_IMotion =
{ 0x692d03a4, 0xc689, 0x11ce,
{ 0xb3, 0x37, 0x88, 0xea, 0x36, 0xde, 0x9e, 0x4e } };
// {692D03A5-C689-11CE-B337-88EA36DE9E4E}
static const IID IID_IVisual =
{ 0x692d03a5, 0xc689, 0x11ce,
{ 0xb3, 0x37, 0x88, 0xea, 0x36, 0xde, 0x9e, 0x4e } };
IMPLEMENT_DYNCREATE(CSpaceship, CCmdTarget)
CSpaceship::CSpaceship()
{
TRACE("CSpaceship ctor\n");
m_nPosition = 100;
m_nAcceleration = 101;
m_nColor = 102;
// To keep the application running as long as an OLE automation
// object is active, the constructor calls AfxOleLockApp.
AfxOleLockApp();
}
CSpaceship::~CSpaceship()
{
TRACE("CSpaceship dtor\n");
// To terminate the application when all objects created with
// OLE automation, the destructor calls AfxOleUnlockApp.
AfxOleUnlockApp();
}
void CSpaceship::OnFinalRelease()
{
// When the last reference for an automation object is released
// OnFinalRelease is called. This implementation deletes the
// object. Add additional cleanup required for your object before
// deleting it from memory.
delete this;
}
BEGIN_MESSAGE_MAP(CSpaceship, CCmdTarget)
//{{AFX_MSG_MAP(CSpaceship)
// NOTE - the ClassWizard will add and remove mapping macros here.
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
BEGIN_INTERFACE_MAP(CSpaceship, CCmdTarget)
INTERFACE_PART(CSpaceship, IID_IMotion, Motion)
INTERFACE_PART(CSpaceship, IID_IVisual, Visual)
END_INTERFACE_MAP()
// {692D03A3-C689-11CE-B337-88EA36DE9E4E}
IMPLEMENT_OLECREATE(CSpaceship, "Spaceship", 0x692d03a3, 0xc689,
0x11ce, 0xb3, 0x37, 0x88, 0xea, 0x36, 0xde,
0x9e, 0x4e)
STDMETHODIMP_(ULONG) CSpaceship::XMotion::AddRef()
{
TRACE("CSpaceship::XMotion::AddRef\n");
METHOD_PROLOGUE(CSpaceship, Motion)
return pThis->ExternalAddRef();
}
STDMETHODIMP_(ULONG) CSpaceship::XMotion::Release()
{
TRACE("CSpaceship::XMotion::Release\n");
METHOD_PROLOGUE(CSpaceship, Motion)
return pThis->ExternalRelease();
}
STDMETHODIMP CSpaceship::XMotion::QueryInterface(
REFIID iid, LPVOID* ppvObj)
{
ITrace(iid, "CSpaceship::XMotion::QueryInterface");
METHOD_PROLOGUE(CSpaceship, Motion)
return pThis->ExternalQueryInterface(&iid, ppvObj);
}
STDMETHODIMP_(void) CSpaceship::XMotion::Fly()
{
TRACE("CSpaceship::XMotion::Fly\n");
METHOD_PROLOGUE(CSpaceship, Motion)
TRACE("m_nPosition = %d\n", pThis->m_nPosition);
TRACE("m_nAcceleration = %d\n", pThis->m_nAcceleration);
return;
}
STDMETHODIMP_(int&) CSpaceship::XMotion::GetPosition()
{
TRACE("CSpaceship::XMotion::GetPosition\n");
METHOD_PROLOGUE(CSpaceship, Motion)
TRACE("m_nPosition = %d\n", pThis->m_nPosition);
TRACE("m_nAcceleration = %d\n", pThis->m_nAcceleration);
return pThis->m_nPosition;
}
//
STDMETHODIMP_(ULONG) CSpaceship::XVisual::AddRef()
{
TRACE("CSpaceship::XVisual::AddRef\n");
METHOD_PROLOGUE(CSpaceship, Visual)
return pThis->ExternalAddRef();
}
STDMETHODIMP_(ULONG) CSpaceship::XVisual::Release()
{
TRACE("CSpaceship::XVisual::Release\n");
METHOD_PROLOGUE(CSpaceship, Visual)
return pThis->ExternalRelease();
}
STDMETHODIMP CSpaceship::XVisual::QueryInterface(
REFIID iid, LPVOID* ppvObj)
{
ITrace(iid, "CSpaceship::XVisual::QueryInterface");
METHOD_PROLOGUE(CSpaceship, Visual)
return pThis->ExternalQueryInterface(&iid, ppvObj);
}
STDMETHODIMP_(void) CSpaceship::XVisual::Display()
{
TRACE("CSpaceship::XVisual::Display\n");
METHOD_PROLOGUE(CSpaceship, Visual)
TRACE("m_nPosition = %d\n", pThis->m_nPosition);
TRACE("m_nColor = %d\n", pThis->m_nColor);
}
//
void ITrace(REFIID iid, const char* str)
{
OLECHAR* lpszIID;
::StringFromIID(iid, &lpszIID);
CString strTemp = (LPCWSTR) lpszIID;
TRACE("%s - %s\n", (const char*) strTemp, (const char*) str);
AfxFreeTaskMem(lpszIID);
}
正规DLL部分代码
/// //
// CEx24bApp initialization
BOOL CEx24bApp::InitInstance()
{
// Register all OLE server (factories) as running. This enables the
// OLE libraries to create objects from other applications.
COleObjectFactory::RegisterAll();
return TRUE;
}
/// //
// Special entry points required for inproc servers
STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID * ppv)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
return AfxDllGetClassObject(rclsid, riid, ppv);
}
STDAPI DllCanUnloadNow( void )
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
return AfxDllCanUnloadNow();
}
// by exporting DllRegisterServer, you can use regsvr.exe
STDAPI DllRegisterServer( void )
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
COleObjectFactory::UpdateRegistryAll();
return S_OK;
}
要想运行客户端和组件程序,必须先注册组件来更新注册表,可以使用如下的代码:
BOOL CRegCompApp::InitInstance()
{
SetRegistryKey(_T( " Local AppWizard-Generated Applications " ));
// make sure to set Explorer options to allow DLLs to be visible
CSpecialFileDialog dlgFile(TRUE, NULL, NULL, OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT,
" OCX files (*.ocx)|*.ocx|DLL files (*.dll)|*.dll|| " );
dlgFile.m_ofn.lpstrTitle = " 注册OCX/DLL File " ;
if (dlgFile.DoModal() != IDOK) return FALSE;
CString strDllPath = dlgFile.GetPathName(); // 获取文件名
// this wouldn't work for a dynamically linked Regular DLL
HINSTANCE h = ::LoadLibrary(strDllPath); // 加载dll
if (h == NULL)
{
CString msg;
msg.Format( " Failed to find server %s " , strDllPath);
AfxMessageBox(msg);
return FALSE;
}
FARPROC pFunc = ::GetProcAddress((HMODULE) h, " DllRegisterServer " );
if (pFunc == NULL) {
AfxMessageBox( " Failed to find DllRegisterServer function " );
return FALSE;
}
( * pFunc)(); // call the function to register the server 注册
AfxMessageBox( " Server registered OK " );
return FALSE;
}
{
SetRegistryKey(_T( " Local AppWizard-Generated Applications " ));
// make sure to set Explorer options to allow DLLs to be visible
CSpecialFileDialog dlgFile(TRUE, NULL, NULL, OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT,
" OCX files (*.ocx)|*.ocx|DLL files (*.dll)|*.dll|| " );
dlgFile.m_ofn.lpstrTitle = " 注册OCX/DLL File " ;
if (dlgFile.DoModal() != IDOK) return FALSE;
CString strDllPath = dlgFile.GetPathName(); // 获取文件名
// this wouldn't work for a dynamically linked Regular DLL
HINSTANCE h = ::LoadLibrary(strDllPath); // 加载dll
if (h == NULL)
{
CString msg;
msg.Format( " Failed to find server %s " , strDllPath);
AfxMessageBox(msg);
return FALSE;
}
FARPROC pFunc = ::GetProcAddress((HMODULE) h, " DllRegisterServer " );
if (pFunc == NULL) {
AfxMessageBox( " Failed to find DllRegisterServer function " );
return FALSE;
}
( * pFunc)(); // call the function to register the server 注册
AfxMessageBox( " Server registered OK " );
return FALSE;
}