メモ Microsoft Visual C++ .NET (2002) は、Microsoft .NET Framework によって提供されるマネージ コード モデルとアンマネージ ネイティブ Windows コード モデルの両方をサポートします。 この資料の情報は、アンマネージ Visual C++ コードのみに適用されます。
#pragma once
#include "oaidl.h"
#include "CApplication.h"
#include "CDocument0.h"
#include "CDocuments.h"
#include "CSelection.h"
#include "CWindow0.h"
const IID IID_IApplicationEvents2 =
{0x000209fe,0x0000,0x0000,{0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46}};
// Parsed UUID for WordApplicationEvents2 dispinterface.
class CAppEventListener : public IDispatch
{
private:
int m_refCount;
public:
//Constructor.
CAppEventListener();
//Destructor
~CAppEventListener();
/***** IUnknown Methods *****/
STDMETHODIMP QueryInterface(REFIID riid, void ** ppvObj);
STDMETHODIMP_(ULONG) AddRef();
STDMETHODIMP_(ULONG) Release();
/***** IDispatch Methods *****/
STDMETHODIMP GetTypeInfoCount(UINT *iTInfo);
STDMETHODIMP GetTypeInfo(UINT iTInfo, LCID lcid,
ITypeInfo **ppTInfo);
STDMETHODIMP GetIDsOfNames(REFIID riid,
OLECHAR **rgszNames,
UINT cNames, LCID lcid,
DISPID *rgDispId);
STDMETHODIMP Invoke(DISPID dispIdMember, REFIID riid, LCID lcid,
WORD wFlags, DISPPARAMS* pDispParams,
VARIANT* pVarResult, EXCEPINFO* pExcepInfo,
UINT* puArgErr);
// The following three examples are patterns for the
// declaration, definition, and implementation of
// event handler methods.
STDMETHODIMP WindowSelectionChange(CSelection* Sel);
STDMETHODIMP WindowBeforeRightClick(CSelection* Sel,
VARIANT_BOOL* Cancel);
STDMETHODIMP WindowDeactivate(IUnknown* Doc,
CWindow0* Wn);
// End of examples.
};
注 : IID_IApplicationEvents2 変数の値は、Word オブジェクト ライブラリから派生します。 詳細については、参照、アプリケーション イベントの Word してください。
Appeventlistener.cpp のコードの全体を次のコードに置き換えます:
#include "stdafx.h"
#include "AppEventListener.h"
//Constructor.
CAppEventListener::CAppEventListener()
{
m_refCount = 0;
}
//Destructor.
CAppEventListener::~CAppEventListener()
{}
/******************************************************************************
* IUnknown Interfaces -- All COM objects must implement, either
* directly or indirectly, the IUnknown interface.
******************************************************************************/
/******************************************************************************
* QueryInterface -- Determines if this component supports the
* requested interface, places a pointer to that interface in ppvObj if it is
* available, and returns S_OK. If not, sets ppvObj to NULL and returns
* E_NOINTERFACE.
******************************************************************************/
STDMETHODIMP CAppEventListener::QueryInterface(REFIID riid, void ** ppvObj)
{
if (riid == IID_IUnknown){
*ppvObj = static_cast<IUnknown*>(this);
}
else if (riid == IID_IDispatch){
*ppvObj = static_cast<IDispatch*>(this);
}
else if (riid == IID_IApplicationEvents2){
*ppvObj = static_cast<IDispatch*>(this);
}
else{
*ppvObj = NULL;
return E_NOINTERFACE;
}
static_cast<IUnknown*>(*ppvObj)->AddRef();
return S_OK;
}
/******************************************************************************
* AddRef() -- In order to allow an object to delete itself when
* it is no longer needed, it is necessary to maintain a count of all
* references to this object. When a new reference is created, this function
* increments the count.
******************************************************************************/
STDMETHODIMP_(ULONG) CAppEventListener::AddRef()
{
return ++m_refCount;
}
/******************************************************************************
* Release() -- When a reference to this object is removed, this
* function decrements the reference count. If the reference count is 0,
* this function deletes this object and returns 0.
******************************************************************************/
STDMETHODIMP_(ULONG) CAppEventListener::Release()
{
m_refCount--;
if (m_refCount == 0)
{
delete this;
return 0;
}
return m_refCount;
}
/******************************************************************************
* IDispatch Interface -- This interface allows this class to be used as an
* Automation server, allowing its functions to be called by other COM
* objects.
******************************************************************************/
/******************************************************************************
* GetTypeInfoCount -- This function determines if the class supports type
* information interfaces or not. It places 1 in iTInfo if the class supports
* type information and 0 if it does not.
******************************************************************************/
STDMETHODIMP CAppEventListener::GetTypeInfoCount(UINT *iTInfo)
{
*iTInfo = 0;
return S_OK;
}
/******************************************************************************
* GetTypeInfo -- Returns the type information for the class. For classes
* that do not support type information, this function returns E_NOTIMPL;
******************************************************************************/
STDMETHODIMP CAppEventListener::GetTypeInfo(UINT iTInfo, LCID lcid,
ITypeInfo **ppTInfo)
{
return E_NOTIMPL;
}
/******************************************************************************
* GetIDsOfNames -- Takes an array of strings and returns an array of DISPIDs
* that correspond to the methods or properties indicated. If the name is not
* recognized, it returns DISP_E_UNKNOWNNAME.
******************************************************************************/
STDMETHODIMP CAppEventListener::GetIDsOfNames(REFIID riid,
OLECHAR **rgszNames,
UINT cNames, LCID lcid,
DISPID *rgDispId)
{
return E_NOTIMPL;
}
/******************************************************************************
* Invoke -- Takes a dispid and uses it to call another of the methods of this
* class. Returns S_OK if the call was successful.
******************************************************************************/
STDMETHODIMP CAppEventListener::Invoke(DISPID dispIdMember, REFIID riid, LCID lcid,
WORD wFlags, DISPPARAMS* pDispParams,
VARIANT* pVarResult,
EXCEPINFO* pExcepInfo,
UINT* puArgErr)
{
//Validate arguments.
if ((riid != IID_NULL))
return E_INVALIDARG;
HRESULT hr = S_OK; // Initialize.
switch(dispIdMember){
case 0x00000001: //Startup(); Word is started before this is fired.
OutputDebugString("Startup\n");
break;
case 0x00000002: //Quit();
OutputDebugString( "Quit\n");
break;
case 0x00000003: //DocumentChange();
OutputDebugString( "DocumentChange\n");
break;
case 0x00000004: //DocumentOpen([in] Document* Doc);
OutputDebugString( "DocumentOpen\n");
break;
case 0x00000005: // No dispID
OutputDebugString( "No dispID yields 00005. This is wierd!\n");
break;
case 0x00000006: // DocumentBeforeClose([in] Document* Doc, [in] VARIANT_BOOL* Cancel);
OutputDebugString( "DocumentBeforeClose\n");
break;
case 0x00000007: // DocumentBeforePrint([in] Document* Doc, [in] VARIANT_BOOL* Cancel);
OutputDebugString( "DocumentBeforePrint\n");
break;
case 0x00000008: // DocumentBeforeSave([in] Document* Doc, [in] VARIANT_BOOL* SaveAsUI, [in] VARIANT_BOOL* Cancel);
OutputDebugString( "DocumentBeforeSave\n");
break;
case 0x00000009: // NewDocument([in] Document* Doc);
OutputDebugString( "New Document\n");
break;
case 0x0000000a: // WindowActivate([in] Document* Doc, [in] Window* Wn);
OutputDebugString( "WindowActivate\n");
break;
// Next 3 illustrate passing parameters to real event handler functions.
case 0x0000000b: // WindowDeactivate([in] Document* Doc, [in] Window* Wn);
// The client(in this case, Word) sends arguments to INVOKE
// in a parameter array, stacked in reverse order, but you
// need to send them to the called function in not-reverse order.
if(pDispParams->cArgs!=2)
return E_INVALIDARG;
else
{
if(pDispParams->rgvarg[0].vt & VT_BYREF)
{
if(pDispParams->rgvarg[0].vt & VT_BYREF)
{
WindowDeactivate(*(pDispParams->rgvarg[1].ppunkVal),
((CWindow0*)*(pDispParams->rgvarg[0].ppunkVal)));
}
else
{
WindowDeactivate(*(pDispParams->rgvarg[1].ppunkVal),
((CWindow0*)(pDispParams->rgvarg[0].punkVal)));
}
}
else
{
if(pDispParams->rgvarg[0].vt & VT_BYREF)
{
WindowDeactivate((pDispParams->rgvarg[1].punkVal),
((CWindow0*)*(pDispParams->rgvarg[0].ppunkVal)));
}
else
{
WindowDeactivate((pDispParams->rgvarg[1].punkVal),
((CWindow0*)(pDispParams->rgvarg[0].punkVal)));
}
}
}
break;
case 0x0000000c: // WindowSelectionChange([in] Selection* Sel);
if (pDispParams->cArgs != 1)
return E_INVALIDARG;
else{
if (pDispParams->rgvarg[0].vt & VT_BYREF)
WindowSelectionChange( ((CSelection*)*(pDispParams->rgvarg[0].ppunkVal)) );
else
WindowSelectionChange((CSelection*) pDispParams->rgvarg[0].punkVal );
}
break;
case 0x0000000d: // WindowBeforeRightClick([in] Selection* Sel, [in] VARIANT_BOOL* Cancel);
if(pDispParams->cArgs !=2)
return E_INVALIDARG;
else
{
if(pDispParams->rgvarg[1].vt & VT_BYREF) // The pointer to bool is always by reference.
{
WindowBeforeRightClick( // call the function
((CSelection*)*(pDispParams->rgvarg[1].ppunkVal)),
pDispParams->rgvarg[0].pboolVal);
}
else
{
WindowBeforeRightClick( // Call the function.
((CSelection*)(pDispParams->rgvarg[1].punkVal)),
pDispParams->rgvarg[0].pboolVal);
}
}
break;
case 0x0000000e: // WindowBeforeDoubleClick([in] Selection* Sel, [in] VARIANT_BOOL* Cancel);
OutputDebugString( "WindowBeforeDoubleClick\n");
break;
default:
OutputDebugString( "An event with a dispID above 000e\n");
break;
}
return hr;
}
/************************************************************************************
* Sample event handler functions, called from the above switch.
* Fill each with the code needed to handle the event according to
* the needs and design of your application.
************************************************************************************/
STDMETHODIMP CAppEventListener::WindowSelectionChange(CSelection* Sel)
{
OutputDebugString("WindowSelectionChange\n");
return S_OK;
}
STDMETHODIMP CAppEventListener::WindowBeforeRightClick(CSelection* Sel, VARIANT_BOOL* Cancel)
{
OutputDebugString("WindowBeforeRightClick\n");
return S_OK;
}
STDMETHODIMP CAppEventListener::WindowDeactivate(IUnknown* Doc, CWindow0* Wn)
{
OutputDebugString("WindowDeactivate\n");
return S_OK;
}
void CWordEvents1Dlg::OnBnClickedStartsink()
{
// Common OLE-variants. These are easy variants to use for calling arguments.
COleVariant
covTrue((short)TRUE),
covFalse((short)FALSE),
covOptional((long)DISP_E_PARAMNOTFOUND, VT_ERROR);
COleException e;
CDocuments oDocs; // oDocs is the Documents Collection.
CDocument0 oDoc; // oDoc is the Document object.
CString str;
HRESULT hr = S_OK;
try
{
// Start Word and get an Application object.
if(!m_wordApplication.CreateDispatch("Word.Application", &e))
{
str.Format("Problem instantiating Word. Error is %ld <0x%08lx>", e.m_sc, e.m_sc);
AfxMessageBox(str,MB_SETFOREGROUND);
return;
}
else // Success.
{
//Make the application visible.
m_wordApplication.put_Visible(TRUE);
}
oDocs = m_wordApplication.get_Documents();
oDoc = oDocs.Add(covOptional,covOptional,covOptional,covTrue);
//Do not try to hook up more than once.
if (m_pAppEventListener != NULL)
return;
// Get IConnectionPointContainer interface for the server.
IConnectionPointContainer *pConnPtContainer= NULL;
hr = m_wordApplication.m_lpDispatch->QueryInterface(
IID_IConnectionPointContainer,
(void **)&pConnPtContainer );
if (SUCCEEDED(hr)){
// Find the connection point for events that you are interested in.
hr = pConnPtContainer->FindConnectionPoint(
IID_IApplicationEvents2,
&m_pConnectionPoint
);
if (SUCCEEDED(hr)){
//Create a new CAppEventListener.
m_pAppEventListener = new CAppEventListener();
m_pAppEventListener->AddRef();
// Set up advisory connection.
hr = m_pConnectionPoint->Advise(m_pAppEventListener,
&m_dwConnectionCookie);
// Release the IConnectionPointContainer interface.
pConnPtContainer->Release();
}
}
}
catch(COleException* e)
{
str.Format("Error in Try..Catch was 0x%08lx", e->m_sc);
AfxMessageBox(str, MB_SETFOREGROUND);
return;
}
}
Microsoft Knowledge Base の免責: Microsoft Knowledge Baseに含まれている情報は、いかなる保証もない現状ベースで提供されるものです。Microsoft Corporation及びその関連会社は、市場性および特定の目的への適合性を含めて、明示的にも黙示的にも、一切の保証をいたしません。さらに、Microsoft Corporation及びその関連会社は、本文書に含まれている情報の使用及び使用結果につき、正確性、真実性等、いかなる表明・保証も行ないません。Microsoft Corporation、その関連会社及びこれらの権限ある代理人による口頭または書面による一切の情報提供またはアドバイスは、保証を意味するものではなく、かつ上記免責条項の範囲を狭めるものではありません。Microsoft Corporation、その関連会社 及びこれらの者の供給者は、直接的、間接的、偶発的、結果的損害、逸失利益、懲罰的損害、または特別損害を含む全ての損害に対して、状況のいかんを問わず一切責任を負いません。(Microsoft Corporation、その関連会社 またはこれらの者の供給者がかかる損害の発生可能性を了知している場合を含みます。) 結果的損害または偶発的損害に対する責任の免除または制限を認めていない地域においては、上記制限が適用されない場合があります。なお、本文書においては、文書の体裁上の都合により製品名の表記において商標登録表示、その他の商標表示を省略している場合がありますので、予めご了解ください。