Sorry for the delay - I'm afraid there isn't anything obvious I can see. However, note that all the IConnection* interfaces are fully exposed in Python - so it should be able to avoid the "WithEvents" type helpers and "port" the code below directly - ie, manually doing the QI for the IConnect* interfaces, etc. You might find win32com/client/connect.py and win32com/demos/connect.py useful as these do the low-level connection-point wrangling so may either be useful directly or as a guide to using them from Python.

Cheers,

Mark.

On 1/03/2012 1:01 AM, Darren McElfresh wrote:
Thanks for your help on this!

I expect an "event" to make a callback on my event handler.

I updated my code to not utilize getevents, since I'm using
DispatchWithEvents, and removed my call to MsgWaitForMultipleObjects and
updated the call to PumpWaitingMessages in a loop, to just be
PumpMessages; however it still doesn't seem to work.

So at this point I basically have:
class Events():
def OnChange(self, e=defaultNamedNotOptArg):
....
....
event_source = view.newItemEventSource(
server.typeForName(server.TypeNames.CHANGEREQUEST) )
event_monitor = win32com.client.DispatchWithEvents( event_source, Events )
pythoncom.PumpMessages()

The C++ code snippets are the following
class CMyListener :
// _StItemSink is the default source (outgoing) dspinterface for
// StItemEventSource objects.
public IDispatchImpl<_IStItemSink, &DIID__IStItemSink, &LIBID_StarTeam>,
public CComObjectRoot
{
public:
CMyListener() {}
BEGIN_COM_MAP(CMyListener)
COM_INTERFACE_ENTRY(IDispatch)
COM_INTERFACE_ENTRY(_IStItemSink)
END_COM_MAP()
....
// _IStItemSink is a dspinterface.
// We must implement IDispatch::Invoke().
STDMETHOD(Invoke)( DISPID dispIdMember,
REFIID riid, LCID lcid,
WORD wFlags,
DISPPARAMS FAR* pDispParams,
VARIANT FAR* pVarResult,
EXCEPINFO FAR* pExcepInfo,
unsigned int FAR* puArgErr )
{
....
}
....
// Create the event source for CHANGEREQUEST items.
CComPtr<IStItemEventSource> source;
hr = stView->newItemEventSource(type, &source);
if (!VerifyHR(hr, IID_IStView, stView)) {
return(false);
}

// The event source is the connection point container.
CComPtr<IConnectionPointContainer> cpc;
hr = source->QueryInterface(IID_IConnectionPointContainer, (void**)&cpc);
if (!VerifyHR(hr, IID_IStItemEventSource, source)) {
return(false);
}

// Find the connection point for Item events.
// We save it so that we can call IConnectionPointContainer::Unadvise()
later.
hr = cpc->FindConnectionPoint(DIID__IStItemSink, &m_cp);
if (!VerifyHR(hr, IID_IConnectionPointContainer, cpc)) {
return(false);
}

// Instantiate our listener.
CComObject<CMyListener>* listener = NULL;
hr = CComObject<CMyListener>::CreateInstance(&listener);
if (!VerifyHR(hr)) {
return(false);
}

// Slip in a pointer to the parent dialog.
listener->m_dlg = this;

// Connect the listener.
// We save the cookie so that we can call
IConnectionPointContainer::Unadvise() later.
hr = m_cp->Advise(listener, &m_cookie);
if (!VerifyHR(hr, IID_IConnectionPoint, m_cp)) {
return(false);

Any ideas on what I'm missing? Is it that the object is an Dispatch
Interface, and so I'm not handling that correctly?

Thanks,
Darren


------------------------------------------------------------------------
*From:* Mark Hammond <skippy.hamm...@gmail.com>
*To:* Darren McElfresh <dmcelfr...@yahoo.com>
*Cc:* "python-win32@python.org" <python-win32@python.org>
*Sent:* Tuesday, February 28, 2012 5:15 PM
*Subject:* Re: [python-win32] Help Needed on Handling Events from a
Proprietary COM Object

On 29/02/2012 8:26 AM, Darren McElfresh wrote:
 > I’ve read through numerous posts on how to get this to work, but I’ve
 > realized it is time to ask for help.
 > In general I have a COM object that returns an event handler:
 > /event_source = com_object.newEventSource( arg_data )/
 > I’ve tried establishing the connection points necessary by creating an
 > event class derived on the sink co-class of this event source:
 > /class Events(win32com.client.getevents(COM_LIB.CLSID)):/
 > I included all of the methods that were mentioned in the generated code
 > from makepy.From there I tried to utilize DispatchWithEvents to connect
 > the listener:
 > /event_monitor = win32com.client.DispatchWithEvents( event_source,
Events )/

Using DispatchWithEvents means you shouldn't need to use getevents
manually at all - it does the getevents for you. So just defining your
Events class without a base-class should work - check out the docstring
for DispatchWithEvents.

 > Everything seems fine at this point, but when I use try to listen it
 > never seems to fire:
 > /rc = win32event.WaitForSingleObject( event_monitor.event, TIME )/

What is event_monitor.event? I guess it must be an integer event handle,
but it is worth checking it is sane. Also, that doesn't really make
sense as an event sink - presumably you have referenced the 'event'
attribute before an event has fired, so the actual firing of an event
doesn't seem to need to do anything - it just sets the handle object and
wouldn't need to make a callback into your handler. Generally the firing
of an event will explicitly call a method you supply, but that doesn't
seem to be the case here.

Even if that was "normal" for your object, you might need
MsgWaitForMultipleObjects - a message loop way well be needed to deliver
the event calls (ie, so the event handler functions can be called).

 > I’ve even tried (even though I don’t think it is necessary for single
 > threaded applications):
 > /pythoncom.PumpWaitingMessages()/

A single threaded application will have to do *something* while it is
waiting for the events to fire, so unless you are in a UI like
pythonwin, you *will* need something like PumpMessages - otherwise your
thread will just terminate. PumpWaitingMessages only pumps what is
queued now - you need PumpMessages to pump "forever" - or until you call
PostQuitMessage to kill the pump, presumably in response to a future event)

But I'm missing something - either you expect an "event" to set a
Windows event handle (and therefore probably need
MsgWaitForMultipleObjects) or you expect an "event" to make a callback
on your event handler (in which case you need something like
PumpMessages) - but the 2 scenarios are quite different depending on
what is expected to happen.

 > However that didn’t seem to have any impact either.No matter what I try
 > – I can’t get my handlers to fire.I have sample code on how to do this
 > in C++, and I have already taken the sample Java code and have my own
 > version of that working; however I’d prefer to use Python if I can get
 > it to work.
 > I can provide my code (or the samples), but it is somewhat lengthy so I
 > was hoping someone would see what I was missing right away?

Maybe you could just provide a summary of the relevant C++ code?

Mark




_______________________________________________
python-win32 mailing list
python-win32@python.org
http://mail.python.org/mailman/listinfo/python-win32

_______________________________________________
python-win32 mailing list
python-win32@python.org
http://mail.python.org/mailman/listinfo/python-win32

Reply via email to