Calling SetFilterSRC in an MFC C++ Application?

S

Scott Metzger

Hi,

I am trying to call SetFilterSRC(Visio 2003) in an MFC Application. I
have imported the typelib via ClassWizard. According to this KB article
I need to write the SAFEARRAY functions by hand:
http://support.microsoft.com/default.aspx?scid=kb;en-us;158451

When my m_lpDispath->Invoke is called in my handwritten function I get a
result back saying "Invalid number of parameters". Any ideas?

Here is the ClassWizard imported function from the typelib I am trying
to fix:
void SetFilterSRC(SAFEARRAY * * SRCStream)
{
static BYTE parms[] = VTS_UNKNOWN ;
InvokeHelper(0x60020019, DISPATCH_METHOD, VT_EMPTY, NULL, parms,
SRCStream);
}

I have added another function to the ClassWizard generated class(Should
I do that?) that follows the KB article:
void SCMSetFilterSRC(VARIANT *pVar, int cElems)
{
HRESULT hr;

VARIANT returnval;
EXCEPINFO Excepinfo;
unsigned int uArgErr;
DISPPARAMS dp;

VariantInit(&returnval);

dp.rgvarg = new VARIANTARG[cElems];

memcpy(dp.rgvarg, pVar, sizeof(VARIANT)*cElems);

dp.cArgs = cElems;
dp.cNamedArgs = 0;

hr = m_lpDispatch->Invoke( 0x60020019, IID_NULL, LOCALE_SYSTEM_DEFAULT,
DISPATCH_METHOD, &dp, &returnval, &Excepinfo, &uArgErr);
delete[] dp.rgvarg;
}

Here is how I call my function:
VARIANT* filter = new VARIANT[7];
filter[0].vt = VT_I2;
filter[0].iVal = visSectionProp;

filter[1].vt = VT_I2;
filter[1].iVal = visRowProp;

filter[2].vt = VT_I2;
filter[2].iVal = visCustPropsValue;

filter[3].vt = VT_I2;
filter[3].iVal = visSectionProp;

filter[4].vt = VT_I2;
filter[4].iVal = visRowProp;

filter[5].vt = VT_I2;
filter[5].iVal = visCustPropsValue;

filter[6].vt = VT_I2;
filter[6].iVal = 1; //true

CellChangedEvent.SCMSetFilterSRC(filter, 7);


Thanks,
Scott Metzger
 
S

Scott Metzger

Ok, so I finally got events working with Visio 2003 and C++. So, I
thought I would post the solution here for any poor soul who is also
doing C++ development with Visio.

First off I have used the class wizard to import the Visio type libraries.

I have attached VisioDispatch.h this file contains a CMyDispatch which
is used to 'catch' a mapped event. The event will come into the Invoke
function.

Here I am actually mapping an event...
//MyVisio the DrawingControl.
CVDocument myDocument(MyVisio.get_Document());
CVApplication myApplication(myDocument.get_Application());
IUnknown FAR* pSink = NULL;
char buf[1024];
CVEventList myEventList(myApplication.get_EventList());
MyCellChangedEventProc = new CVisEventProc;

m_pDisp = new CMyDispatch();
m_pDisp->AddRef();

VARIANT m_v;
VariantInit(&m_v);
m_v.vt = VT_DISPATCH;


m_v.pdispVal = m_pDisp;

MyCellChangedEvent= myEventList.AddAdvise( (visEvtCell | visEvtMod),
m_v, "", "Cell Changed");

// below is how to use a filter.
//The filter used filters all cells out except the 1st User-defined cell
SAFEARRAY* filter;
SAFEARRAYBOUND bound[1];
bound[0].lLbound = 0;
bound[0].cElements = 7;
filter = SafeArrayCreate(VT_I2, 1, bound);
long index = 0;
short data = visSectionProp;
SafeArrayPutElement(filter, &index, (void*)&data);
index = 1;
data = visRowProp;
SafeArrayPutElement(filter, &index, (void*)&data);
index = 2;
data = visCustPropsValue;
SafeArrayPutElement(filter, &index, (void*)&data);
index = 3;
data = visSectionProp;
SafeArrayPutElement(filter, &index, (void*)&data);
index = 4;
data = visRowProp;
SafeArrayPutElement(filter, &index, (void*)&data);
index = 5;
data = visCustPropsValue;
SafeArrayPutElement(filter, &index, (void*)&data);
index = 6;
data = -1;
SafeArrayPutElement(filter, &index, (void*)&data);
MyCellChangedEvent.SCMSetFilterSRC(filter);

////////////////////////////////////////////////
I added SCMSetFilterSRC to the generated CVEvent class

void SCMSetFilterSRC(SAFEARRAY *pVar) // notice the change in parameters
{
HRESULT hr;

VARIANT returnval;
EXCEPINFO Excepinfo;
unsigned int uArgErr;
DISPPARAMS dp;

VariantInit(&returnval);

VARIANT vArray;
vArray.vt = VT_ARRAY | VT_BYREF | VT_I2; // required OR'ing of VT types.
vArray.pparray = &pVar;

dp.rgvarg = &vArray;
dp.cArgs = 1;
dp.cNamedArgs = 0;
dp.rgdispidNamedArgs = NULL;


/*
// ------------------------------------
GetMemberInfo(m_lpDispatch);
DISPID dispid;
//LPOLESTR szNames[] = {L"AddAdvise"};
OLECHAR FAR* szMember = L"SetFilterSRC";
hr =
m_lpDispatch->GetIDsOfNames(IID_NULL,&szMember,1,LOCALE_SYSTEM_DEFAULT,&dispid);
// ---- the code above checks the type of each argument -------------
*/
hr = m_lpDispatch->Invoke( 0x60020019,
IID_NULL,
LOCALE_SYSTEM_DEFAULT,
DISPATCH_METHOD,
&dp,
NULL,
NULL,
NULL);
return;
}

// -----------------------------------------------------------------------------------------
#include "CVShape.h"
#include "CVConnects.h"
#define ODS(s) OutputDebugString(s);
// New class derived from IDispatch created by mdurrett (md)
class CMyDispatch : public IDispatch {
protected:
ULONG m_cRef;

public:
CMyDispatch();
~CMyDispatch();

// IUnknown
STDMETHODIMP QueryInterface(REFIID, void **);
STDMETHODIMP_(ULONG) AddRef(void);
STDMETHODIMP_(ULONG) Release(void);

// IDispatch
STDMETHODIMP GetIDsOfNames(REFIID riid, OLECHAR FAR *FAR *rgszNames, unsigned int cNames, LCID lcid, DISPID FAR *rgDispId);
STDMETHODIMP GetTypeInfo(unsigned int iTInfo, LCID lcid, ITypeInfo FAR *FAR *ppTInfo);
STDMETHODIMP GetTypeInfoCount(unsigned int FAR *pctinfo);
STDMETHODIMP Invoke(DISPID dispIdMember, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS FAR *pDispParams, VARIANT FAR *pVarResult, EXCEPINFO FAR *pExcepInfo, unsigned int FAR *puArgErr);
};

CMyDispatch::CMyDispatch()
{
m_cRef = 0;
}

CMyDispatch::~CMyDispatch()
{
}

STDMETHODIMP CMyDispatch::QueryInterface(REFIID riid, void **ppv)
{
HRESULT hr = E_NOINTERFACE;
*ppv = NULL;

if (IsEqualGUID(riid,IID_IUnknown) || IsEqualGUID(riid, IID_IDispatch)) {
*ppv = static_cast<IDispatch*>(this);
hr = S_OK;
}

return hr;
}

STDMETHODIMP_(ULONG) CMyDispatch::AddRef(void)
{
ODS("CMyDispatch::AddRef\r\n");
return ++m_cRef;
}

STDMETHODIMP_(ULONG) CMyDispatch::Release(void)
{
ODS("CMyDispatch::Release\r\n");
return --m_cRef;
}

STDMETHODIMP CMyDispatch::GetIDsOfNames(REFIID riid, OLECHAR FAR *FAR *rgszNames, unsigned int cNames, LCID lcid, DISPID FAR *rgDispId)
{
ODS("CMyDispatch::GetIDsOfNames\r\n");
*rgDispId = 0;

if (wcscmp(rgszNames[0],L"VisEventProc") == 0) //wideCstringcompare
{
*rgDispId = 1000; // arbitrary selection of 1000. Use whatever is appropriate
return S_OK;
}
return E_FAIL;

}

STDMETHODIMP CMyDispatch::GetTypeInfo(unsigned int iTInfo, LCID lcid, ITypeInfo FAR *FAR *ppTInfo)
{
ODS("CMyDispatch::GetTypeInfo\r\n");
return E_NOTIMPL;
}

STDMETHODIMP CMyDispatch::GetTypeInfoCount(unsigned int FAR *pctinfo)
{
ODS("CMyDispatch::GetTypeInfoCount\r\n");
return E_NOTIMPL;
}



void GetMemberInfo(IDispatch *pDisp)
{
ITypeInfo *pTypeInfo = NULL;

HRESULT hr = pDisp->GetTypeInfo(0,0,&pTypeInfo);
if (!FAILED(hr)) {
BSTR bstrName;
pTypeInfo->GetDocumentation(MEMBERID_NIL,&bstrName,NULL,NULL,NULL);
char s[1024];
wsprintf(s,"Object is of type \"%S\".\r\n",bstrName);
ODS(s);
SysFreeString(bstrName);
}
}

STDMETHODIMP CMyDispatch::Invoke(DISPID dispIdMember, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS FAR *pDispParams, VARIANT FAR *pVarResult, EXCEPINFO FAR *pExcepInfo, unsigned int FAR *puArgErr)
{
char s[1024];
wsprintf(s,"CMyDispatch::Invoke -- dispid = (%x) %d\r\n",dispIdMember,dispIdMember);
ODS(s);
if (dispIdMember == 1000) {
ODS("Event proc called!\r\n");
int lCode = pDispParams->rgvarg[5].iVal;
wsprintf(s,"Code = %d\r\n",lCode);
ODS(s);

GetMemberInfo(pDispParams->rgvarg[4].pdispVal); // IVApplication
GetMemberInfo(pDispParams->rgvarg[1].pdispVal); // IVShape

CVApplication vApp;
vApp.AttachDispatch(pDispParams->rgvarg[4].pdispVal);
vApp.m_lpDispatch->AddRef();
/*
CVShape vShape;
vShape.AttachDispatch(pDispParams->rgvarg[1].pdispVal);
vShape.m_lpDispatch->AddRef();

//CVShape vShape2(pDispParams->rgvarg[1].pdispVal);

ODS(vApp.get_ProductName());
ODS("\r\n");

ODS(vShape.get_Name());
ODS("\r\n"); */
}
/*
// Sample event handler switch from earlier application
// included for your consideration.
CVApplication app;
CVShape shape;
CVConnects connects;

try
{
app = (CVApplication) source;

switch (eventCode)
{
case VISEVTADD + (short) Visio.VisEventCodes.visEvtShape:
int ScopeID;
ScopeID = m_parentApp.BeginUndoScope("Shape Add");
shape = (Visio.Shape) subject;
HandleShapeAdd( app, shape );
m_parentApp.EndUndoScope(ScopeID,true);
break;
case VISEVTADD + (short) Visio.VisEventCodes.visEvtConnect:
connects = (Visio.Connects) subject;
HandleConnectionAdd( app, connects );
break;
case (short)Visio.VisEventCodes.visEvtDel + (short)Visio.VisEventCodes.visEvtShape:
shape = (Visio.Shape) subject;
HandleShapeDelete( app, shape );
break;
case (short)Visio.VisEventCodes.visEvtApp + (short)Visio.VisEventCodes.visEvtNonePending:
HandleNoEventsPending( app);
break;
case (short)Visio.VisEventCodes.visEvtIdle + (short)Visio.VisEventCodes.visEvtApp:
// System.Diagnostics.Debug.WriteLine("Calling HandleVisioIsIdle");
HandleVisioIdle ( app );
break;
default:
break;
}
}
catch (Exception err)
{
MessageBox.Show("Exception in IVisEventProc.VisEventProc: "
+ err.Message, "Visio2003Read");
}
return null;
}
*/
return S_OK;

}

// ------------------------- endof CMyDispatch() ------------------------------------------
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top