?? beeper.cpp
字號(hào):
/*
* BEEPER.CPP
* Beeper Automation Object #4 Chapter 14
*
* Implementation of the CBeeper class demonstrating the use of
* dual interface.
*
* Copyright (c)1993-1995 Microsoft Corporation, All Rights Reserved
*
* Kraig Brockschmidt, Microsoft
* Internet : kraigb@microsoft.com
* Compuserve: >INTERNET:kraigb@microsoft.com
*/
#include "beeper.h"
extern HINSTANCE g_hInst;
#ifdef WIN32
extern DWORD g_dwTLS;
#endif
/*
* CBeeper::CBeeper
* CBeeper::~CBeeper
*
* Parameters (Constructor):
* pUnkOuter LPUNKNOWN of a controlling unknown.
* pfnDestroy PFNDESTROYED to call when an object
* is destroyed.
*/
CBeeper::CBeeper(LPUNKNOWN pUnkOuter, PFNDESTROYED pfnDestroy)
{
m_cRef=0;
m_pUnkOuter=pUnkOuter;
m_pfnDestroy=pfnDestroy;
m_lSound=0;
//These are created as needed in GetTypeInfo
m_pITINeutral=NULL;
m_pITIGerman=NULL;
return;
}
CBeeper::~CBeeper(void)
{
ReleaseInterface(m_pITIGerman);
ReleaseInterface(m_pITINeutral);
return;
}
/*
* CBeeper::Init
*
* Purpose:
* Performs any intiailization of a CBeeper that's prone to failure
* that we also use internally before exposing the object outside.
*
* Parameters:
* None
*
* Return Value:
* BOOL TRUE if the function is successful,
* FALSE otherwise.
*/
BOOL CBeeper::Init(void)
{
LPUNKNOWN pIUnknown=this;
if (NULL!=m_pUnkOuter)
pIUnknown=m_pUnkOuter;
return TRUE;
}
/*
* CBeeper::QueryInterface
* CBeeper::AddRef
* CBeeper::Release
*/
STDMETHODIMP CBeeper::QueryInterface(REFIID riid, PPVOID ppv)
{
*ppv=NULL;
/*
* IUnknown, IBeeper, and IDispatch are all
* part of CBeeper now.
*/
if (IID_IUnknown==riid || IID_IBeeper==riid
|| IID_IDispatch==riid)
*ppv=this;
//Indicate that we support error information
if (IID_ISupportErrorInfo==riid)
*ppv=m_pImpISuppErr;
//AddRef any interface we'll return.
if (NULL!=*ppv)
{
((LPUNKNOWN)*ppv)->AddRef();
return NOERROR;
}
return ResultFromScode(E_NOINTERFACE);
}
STDMETHODIMP_(ULONG) CBeeper::AddRef(void)
{
return ++m_cRef;
}
STDMETHODIMP_(ULONG) CBeeper::Release(void)
{
if (0L!=--m_cRef)
return m_cRef;
if (NULL!=m_pfnDestroy)
(*m_pfnDestroy)();
delete this;
return 0L;
}
//IDispatch functions, now part of CBeeper
/*
* CBeeper::GetTypeInfoCount
*
* Purpose:
* Returns the number of type information (ITypeInfo) interfaces
* that the object provides (0 or 1).
*
* Parameters:
* pctInfo UINT * to the location to receive
* the count of interfaces.
*
* Return Value:
* HRESULT NOERROR or a general error code.
*/
STDMETHODIMP CBeeper::GetTypeInfoCount(UINT *pctInfo)
{
//We implement GetTypeInfo so return 1
*pctInfo=1;
return NOERROR;
}
/*
* CBeeper::GetTypeInfo
*
* Purpose:
* Retrieves type information for the automation interface. This
* is used anywhere that the right ITypeInfo interface is needed
* for whatever LCID is applicable. Specifically, this is used
* from within GetIDsOfNames and Invoke.
*
* Parameters:
* itInfo UINT reserved. Must be zero.
* lcid LCID providing the locale for the type
* information. If the object does not support
* localization, this is ignored.
* ppITypeInfo ITypeInfo ** in which to store the ITypeInfo
* interface for the object.
*
* Return Value:
* HRESULT NOERROR or a general error code.
*/
STDMETHODIMP CBeeper::GetTypeInfo(UINT itInfo, LCID lcid
, ITypeInfo **ppITypeInfo)
{
HRESULT hr;
ITypeLib *pITypeLib;
ITypeInfo **ppITI=NULL;
if (0!=itInfo)
return ResultFromScode(TYPE_E_ELEMENTNOTFOUND);
if (NULL==ppITypeInfo)
return ResultFromScode(E_POINTER);
*ppITypeInfo=NULL;
/*
* Since we returned one from GetTypeInfoCount, this function
* can be called for a specific locale. We support English,
* German, and neutral (defaults to English) locales. Anything
* else is an error.
*
* After this switch statement, ppITI will either be NULL or
* a valid pointer in it after. If NULL, we know we need to
* load type information, retrieve the ITypeInfo we want, and
* then store it in *ppITI.
*/
switch (PRIMARYLANGID(lcid))
{
case LANG_NEUTRAL:
case LANG_ENGLISH:
ppITI=&m_pITINeutral;
break;
case LANG_GERMAN:
ppITI=&m_pITIGerman;
break;
default:
return ResultFromScode(DISP_E_UNKNOWNLCID);
}
//Load a type lib if we don't have the information already.
if (NULL==*ppITI)
{
/*
* The type libraries are registered under 0 (neutral),
* 7 (German), and 9 (English) with no specific sub-
* language, which would make them 407 or 409 and such.
* If you are sensitive to sub-languages, then use the
* full LCID instead of just the LANGID as done here.
*/
hr=LoadRegTypeLib(LIBID_BeeperTypeLibrary, 1, 0
, PRIMARYLANGID(lcid), &pITypeLib);
/*
* If LoadRegTypeLib fails, try loading directly with
* LoadTypeLib, which will register the library for us.
* Note that there's no default case here because the
* prior switch will have filtered lcid already.
*
* NOTE: You should prepend your DIR registry key to the
* .TLB name so you don't depend on it being it the PATH.
* This sample will be updated later to reflect this.
*/
if (FAILED(hr))
{
switch (PRIMARYLANGID(lcid))
{
case LANG_NEUTRAL:
case LANG_ENGLISH:
hr=LoadTypeLib(OLETEXT("BEEP0000.TLB"), &pITypeLib);
break;
case LANG_GERMAN:
hr=LoadTypeLib(OLETEXT("BEEP0007.TLB"), &pITypeLib);
break;
}
}
if (FAILED(hr))
return hr;
//Got the type lib, get type info for the interface we want
hr=pITypeLib->GetTypeInfoOfGuid(IID_IBeeper, ppITI);
pITypeLib->Release();
if (FAILED(hr))
return hr;
}
/*
* Note: the type library is still loaded since we have
* an ITypeInfo from it.
*/
(*ppITI)->AddRef();
*ppITypeInfo=*ppITI;
return NOERROR;
}
/*
* CBeeper::GetIDsOfNames
*
* Purpose:
* Converts text names into DISPIDs to pass to Invoke
*
* Parameters:
* riid REFIID reserved. Must be IID_NULL.
* rgszNames OLECHAR ** pointing to the array of names to be
* mapped.
* cNames UINT number of names to be mapped.
* lcid LCID of the locale.
* rgDispID DISPID * caller allocated array containing IDs
* corresponging to those names in rgszNames.
*
* Return Value:
* HRESULT NOERROR or a general error code.
*/
STDMETHODIMP CBeeper::GetIDsOfNames(REFIID riid
, OLECHAR **rgszNames, UINT cNames, LCID lcid, DISPID *rgDispID)
{
HRESULT hr;
ITypeInfo *pTI;
if (IID_NULL!=riid)
return ResultFromScode(DISP_E_UNKNOWNINTERFACE);
//Get the right ITypeInfo for lcid.
hr=GetTypeInfo(0, lcid, &pTI);
if (SUCCEEDED(hr))
{
hr=DispGetIDsOfNames(pTI, rgszNames, cNames, rgDispID);
pTI->Release();
}
return hr;
}
/*
* CBeeper::Invoke
*
* Purpose:
* Calls a method in the dispatch interface or manipulates a
* property.
*
* Parameters:
* dispID DISPID of the method or property of interest.
* riid REFIID reserved, must be IID_NULL.
* lcid LCID of the locale.
* wFlags USHORT describing the context of the invocation.
* pDispParams DISPPARAMS * to the array of arguments.
* pVarResult VARIANT * in which to store the result. Is
* NULL if the caller is not interested.
?? 快捷鍵說(shuō)明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -