How do I do this?
I've found Laurent's fragment on the Wiki: sink := AXEventSink target: someComponent sourceTypeInfo: (_IComponentEvents typeInfoIfNone: [^nil]). sink connect: someComponent. someComponent when: #onSomeEvent send: #doSomething to: aListener so, I think if I have someComponent = NewsControl_nntp new. (to continue from my previous posting) the only think I don't know what to do with is _IComponentEvents. That's not a global, it seems, so how do I work out what it will be for my component? And if the doc for the control says it's a (say) DoneConnect event, will it just be #DoneConnect in Dolphin? P. (still near ignorant about all this stuff) |
Paul,
"Paul Hudson" <[hidden email]> wrote in message news:Xns9214D4EEAE69Ephudsonpoboxcom@127.0.0.1... [snip] > sink := AXEventSink target: someComponent sourceTypeInfo: > (_IComponentEvents typeInfoIfNone: [^nil]). > sink connect: someComponent. > someComponent when: #onSomeEvent send: #doSomething to: > aListener [snip] > the only think I don't know what to do with is > _IComponentEvents. That's not a global, it seems, so how do I > work out what it will be for my component? Usually, you should get an event interface that's generated along with the class (maybe something like NewsControlnntpEvents). Sometimes, though, they get a name that doesn't put them very close to their related class. Take a look in the package you created and see. If it's just the three classes to wrap the three controls, that would be a bit depressing, but if the events are supposed to be available for COM use, I think there's got to be typelib info for generating their interfaces. HTH Don > > And if the doc for the control says it's a (say) DoneConnect > event, will it just be #DoneConnect in Dolphin? > > P. (still near ignorant about all this stuff) > > |
In reply to this post by Paul Hudson
"Paul Hudson" <[hidden email]> wrote in message
news:Xns9214D4EEAE69Ephudsonpoboxcom@127.0.0.1... > How do I do this? In your case , you could do it like this: nntp := NewsControl_Nntp createObject: 'NewsControl.Nntp'. tiSink := nntp coclassTypeInfo defaultSourceInterface. sink := AXEventSink target: nntp sourceTypeInfo: tiSink. This is essentially the way that AXControlSite (for hosting visual controls) wires up to the default event set of OCXs - see AXControlSite>>connectSink. > > And if the doc for the control says it's a (say) DoneConnect > event, will it just be #DoneConnect in Dolphin? Not necessarily, and not in this particular case where it will be #DoneConnect:Rs:. The event name will be a selector formed from the event method definition in the type library so as to take the correct number of arguments. Essentially this means that it if there are any arguments it will be a keyword selector the first keyword of which will be the event name with a colon suffix. Subsequent keywords are formed from the names of the argument, the first argument name being dropped since the first keyword has already been constructed from the event name. This is basically the pattern we use for constructing FFI calls names. So you can either peruse the IDL to work out the event names, or use the type library analyzer to tell you, for example: tiSink functions collect: [:each | each selector] In this case it appears that the control will work as an OCX, so it is easiest just to load it up in the Active-X Control Browser tool (on the Additional Tools menu, one opened press Ctrl+N and select 'NewsControl.Nntp' from the list). In the browser the right most list pane displays the event names. If you hover over the entries the IDL for that even is displayed, including any help string. You can drag & drop the event names from the list directly into your code. Regards Blair |
"Blair McGlashan" <[hidden email]> wrote in
news:acd0ns$oj355$[hidden email]: > "Paul Hudson" <[hidden email]> wrote in message > news:Xns9214D4EEAE69Ephudsonpoboxcom@127.0.0.1... >> How do I do this? > > In your case , you could do it like this: > > nntp := NewsControl_Nntp createObject: > 'NewsControl.Nntp'. tiSink := nntp coclassTypeInfo > defaultSourceInterface. sink := AXEventSink target: > nntp sourceTypeInfo: tiSink. > > This is essentially the way that AXControlSite (for hosting > visual controls) wires up to the default event set of OCXs > - see AXControlSite>>connectSink. Thanks. I'm still not getting the events, though. Where will they go to? (nntp, or sink)? Is there some way of detecting when and which events get triggered? (Debugging the expression doesn't seem to be enough) What I've tried is: nntp host: 'localhost'; port: 119; username: 'xxx';password: 'yyy'. nntp when: #DoneDisconnect:Rs: send: #doDisconnect:Rs: to: nntp. nntp connect. (expecting a DNU from nntp, because the username and password are invalid, and the doc (and ActiveX browser) for the control says it sends this). But I get nothing I'm aware I seem to be asking stupid questions - is there something I should be reading first? P. |
Paul Hudson <[hidden email]> wrote in
news:Xns9215D820C41Fphudsonpoboxcom@127.0.0.1: > > Thanks. I'm still not getting the events, though. Where > will they go to? (nntp, or sink)? Right, got there. The answer's nntp. > Is there some way of detecting when and which events get > triggered? (Debugging the expression doesn't seem to be > enough) sink isTracingEnabled: true. I think. > What I've tried is: > > nntp host: 'localhost'; port: 119; username: > 'xxx';password: 'yyy'. > nntp when: #DoneDisconnect:Rs: send: #doDisconnect:Rs: to: > nntp. > nntp connect. I missed sink connect: nntp. No idea why I need it, though :-) > (expecting a DNU from nntp, because the username and > password are invalid, and the doc (and ActiveX browser) for > the control says it sends this). However, I didn't get a DNU (I did now get a message on the Transcript, which was enough to get me going). Is there some reason why this error doesn't raise a DNU? P. (voodoo chicken programming, currently) |
Paul
"Paul Hudson" <[hidden email]> wrote in message news:Xns9216C8304D1C8phudsonpoboxcom@127.0.0.1... > Paul Hudson <[hidden email]> wrote in > news:Xns9215D820C41Fphudsonpoboxcom@127.0.0.1: > > > > Thanks. I'm still not getting the events, though. Where > > will they go to? (nntp, or sink)? > > Right, got there. The answer's nntp. > ... I thought you might, which is why I did not reply (sometimes the teacher must let the student do his own exploration :-)) >... > I missed > > sink connect: nntp. > > No idea why I need it, though :-) As part of a two stage construct protocol that allows one to set up optional parameters on the sink before connecting it, since some objects might send an event as soon as they receive a new connection. > > (expecting a DNU from nntp, because the username and > > password are invalid, and the doc (and ActiveX browser) for > > the control says it sends this). > > However, I didn't get a DNU (I did now get a message on the > Transcript, which was enough to get me going). > > Is there some reason why this error doesn't raise a DNU? Yes, the implementation of IDispatch::Invoke() traps exceptions in order to convert them to HRESULT error codes to be passed back to the client - this is what one wants in a runtime app., because one can't pass exceptions over COM method boundaries. At development time it is unhelpful ("suppressing" errors is almost always unhelpful of course), so it needs some sensible way to control whether it happens at development time. Problem is the error may be "expected" - one might be testing an exceptional condition - so just behaving differently in runtime vs development sessions would not necessarily be sufficient. Regards Blair |
Ok, next problem :-(
The control supports getting a list of newsgroups. This takes some time, so it appears the control returns immediately, and later calls an event to say it's done. How do I arrange to block the method that calls the "get list" method until the event has been called? Semaphore seems to be what I want, but it looks like the event call back is in the same process as my main method (?), so I get deadlock.... (I've got getList: nttp getList. "calls the control" event wait. "event is a Semaphore" "then process the data" and eventGetList: aReturnCode Rs: aMessage "..." event signal. "data's there, go process it". ) So, an overall question is what thread/process are events called in, and do I have any control over this? As usual,pointers to relevant documentation welcomed. P. |
Paul,
> The control supports getting a list of newsgroups. This takes > some time, so it appears the control returns immediately, and > later calls an event to say it's done. > > How do I arrange to block the method that calls the "get list" > method until the event has been called? > > Semaphore seems to be what I want, but it looks like the event > call back is in the same process as my main method (?), so I > get deadlock.... My first thought is to start a background thread to control the logic and have it wait on the semaphore. Since many Windows widgets like to be synchronized with the message queue, you can use #queueDeferredAction: to make the get list call after the semaphore is signalled. What kind of user interface do you want? If it's a progress-dialog, then you might want to take a look at the timed evaluator on my web site. It works for the situations I've tried, but, I won't take offense if you make a backup first :) Have a good one, Bill -- Wilhelm K. Schwab, Ph.D. [hidden email] |
"Bill Schwab" <[hidden email]> wrote in
news:acqsfr$orf$[hidden email]: > Paul, > >> The control supports getting a list of newsgroups. This >> takes some time, so it appears the control returns >> immediately, and later calls an event to say it's done. >> >> How do I arrange to block the method that calls the "get >> list" method until the event has been called? >> >> Semaphore seems to be what I want, but it looks like the >> event call back is in the same process as my main method >> (?), so I get deadlock.... > > My first thought is to start a background thread to control > the logic and have it wait on the semaphore. Yep, did that after the posting, but it seems the wrong way about (I'd like the control logic in the main thread and the events in the background thread). Also makes playing with the functionality from a Workspace a bit tricky (since that is the foreground thread, unless I've missed a trick) - or every method that has this "kick an action off, wait for event" pattern - and there's a lot in this control - needs to fork, which seems a bit ugly. Ideally, I'd have a way of getting events handled on another thread... Since many > Windows widgets like to be synchronized with the message > queue, you can use #queueDeferredAction: to make the get > list call after the semaphore is signalled. I probably don't know enough about Windows to be sure, but is the Windows message queue here anything much to do with the component I'm using (which is not a UI component)? If it does, then this might be it, but my suspicion is not (the event gets called when data arrives from a socket (in VB), using the async Winsock calls. This could take ages, so my guess is it's not a UI message queue. > What kind of user interface do you want? Haven't got as afar as a UI yet. Mostly, I'm just wrapping the control in a class that presents a more usable interface/model, then thinking about the P and V parts. If it's a > progress-dialog, then you might want to take a look at the > timed evaluator on my web site. It works for the > situations I've tried, but, I won't take offense if you > make a backup first :) Thanks. Your site was on my Smalltalk bookmarks already. I think it's not what I want now, but I'll be sure to check it out later. P. |
Free forum by Nabble | Edit this page |