I have an activex control called CONTINUUMXLib. The control provides stock
quotes from a quote server. If I open this control in the Activex Control Browser, I can then send the #connect message. I sign in to a logon dialog put up by the control and then the message answers true. The control then puts out events shown at the bottom of the brower eg Event: #StatusMessage: #('24 sec since last update.') I used the ActiveX Component Wizard to generate Smalltalk classes for the control and then tried to just call the control as follows: cc := CONTINUUMXLib_DContinuumClient new "initialize" . cc connect (tried with and without the initialize) I just get Catastrophic failure (16rFFFF: Catastrophic failure) in CONTINUUMXLib_DContinuumCient(ExternalStructure)>>hresultError: -2147418113 CONTINUUMXLib_DContinuumCient>>invokeId:flags:parms:retVal: CONTINUUMXLib_DContinuumCient>>invokeId:flags:parms: CONTINUUMXLib_DContinuumCient(IDispatch)>>invokeId: CONTINUUMXLib_DContinuumCient>>connect I may have also gotten as far as getting into the logon prompt via this call at some point but i'm not sure. I am COM newbie, I was just hoping to get away with being a dumb, ignorant user of this control :) Can anyone give me a clue? I dont know all the things that the browser must be doing to host the control properly. There are a bunch of other classes generated such as ..._DSnapShotSet which fail the same way but I cant see those in the browser. -ar Dolphin 4.01.3 trial ps. I have no source for the invokeId:flags:parms.... methods, are these part of the set of methods which are only hidden in the trial? |
Here's a couple comments which may help (or not)...Plus check out
http://www.object-arts.com/wiki/html/Dolphin/UsingActiveXComponents.htm for some more detail on using ActiveX components. ar wrote: > I have an activex control called CONTINUUMXLib. The control provides stock > quotes from a quote server. If I open this control in the Activex Control > Browser, I can then send the #connect message. I sign in to a logon dialog put > up by the control and then the message answers true. The control then puts out > events shown at the bottom of the brower eg > > Event: #StatusMessage: #('24 sec since last update.') > > I used the ActiveX Component Wizard to generate Smalltalk classes for the > control and then tried to just call the control as follows: > > cc := CONTINUUMXLib_DContinuumClient new "initialize" . > cc connect > Hmmm.... you might try something like: IDispatch createObject: 'myserver.somethingelse' where IDispatch is the automation interface & 'myserver.somethingelse' is the application and program id of the server. Without more knowledge of your ActiveX control, I can't help fill in the blanks. Perhaps there's some documentation in your control. Now perhaps the connect method is doing that for you. I don't know w/o looking at the control's imported code. > (tried with and without the initialize) > > I just get Catastrophic failure (16rFFFF: Catastrophic failure) in > > CONTINUUMXLib_DContinuumCient(ExternalStructure)>>hresultError: -2147418113 > CONTINUUMXLib_DContinuumCient>>invokeId:flags:parms:retVal: > CONTINUUMXLib_DContinuumCient>>invokeId:flags:parms: > CONTINUUMXLib_DContinuumCient(IDispatch)>>invokeId: > CONTINUUMXLib_DContinuumCient>>connect > I believe this is basically telling you that the IDispatch interface has no server connected to it. Once you get connected, you should have an instance of an interface class which you can send messages to. ... > > ps. I have no source for the invokeId:flags:parms.... methods, are these part > of the set of methods which are only hidden in the trial? > I found that most of the ActiveX & COM support method source's were blocked in the trial edition. Once I purchased the software, they automagically became unblocked. Eric |
In reply to this post by ar
ar <[hidden email]> wrote in message
news:[hidden email]... > I have an activex control called CONTINUUMXLib. The control provides stock > quotes from a quote server. If I open this control in the Activex Control > Browser, I can then send the #connect message. I sign in to a logon dialog put > up by the control and then the message answers true. The control then puts out > events shown at the bottom of the brower eg ... I am currently using the Continuum ActiveX interface from Dolphin. It took some experimentation to get it working. I don't remember the specific reasons for the problems I encountered. However I can show you what I have that works. I seem to recall that it had something to do with the fact that Continuum was expecting to be used like a visual control on a VB form even though it is not really visible. My impression of their ActiveX wrapper was that it was a bit of a "me too" affair for their C++ DLL. There are some fairly low-level aspects to it. This is what I use: ==================== "Open" contClient := AXControlSite progId: 'ContinuumClientX.ContinuumClientCtrl.1'. contClient controlDispatch connectDirect: 'userid' password: 'password' timeOut: 20000. ==================== "Read a quote from a snapshot. This is out of context, but it should give you some hints." timeOut := (TimeStamp current asSeconds) + 30. snap := AXControlSite progId: 'ContinuumX.SnapshotSetCtrl.1'. (snap controlDispatch open: self symbol) ifTrue: [snap controlDispatch init. [(TimeStamp current asSeconds < timeOut) ifFalse: [self errorText: 'Data timeout!'. "CJD 6-18-2001 If we get a timeout lets change servers and try again." self parent contClient controlDispatch nextServer. ^isUpToDate ifTrue: [isUpToDate := false. self getData] ifFalse: [nil]]. snap controlDispatch isRequestPending] whileTrue. snap controlDispatch enterRead. self timeStamp: TimeStamp current. self dayHighPrice: (snap controlDispatch retDouble: 1). "high" self dayLowPrice: (snap controlDispatch retDouble: 2). "low" self price: (snap controlDispatch retDouble: 3). "trade" self volume: (snap controlDispatch retDouble: 10). "volume" snap controlDispatch leaveRead. snap controlDispatch close. snap close. isUpToDate := true. self saveDataToDatabase. self trigger: #dataUpdated] ifFalse: [self statusText: 'Data error!'. ^nil]. ==================== "Close" contClient controlDispatch disconnect. contClient close. contClient := nil. ==================== Hopefully the code did not get too mangled. Once you get the code right it should work well with Dolphin. Chris |
Thanks Eric and Christopher.
In both posts it seems like you are not suggesting using the actual smalltalk classes which were generated. eg using IDispatch instead of the subclass ContinuumClient. I guess you guys got involved with COM on Dolphin from before it generated classes which I thought would shield me from the gory details. Anyway I think you are both saying a similar thing about the control being expected to be used like a visual control or that it doesnt have a server connected to it, but I dont understand the implementation of com well enough yet to know what that really means. (got my Inside Com and Understanding Activex on order:) . Anyway I should probably be able to tinker with that code Chris and get it to work ( I once got this to work in VSE a few years ago). Thanks again. -alan |
ar <[hidden email]> wrote in message
news:=3AVPC=[hidden email]... > Thanks Eric and Christopher. > > In both posts it seems like you are not suggesting using the actual smalltalk > classes which were generated. eg using IDispatch instead of the subclass > ContinuumClient. I guess you guys got involved with COM on Dolphin from before > it generated classes which I thought would shield me from the gory details. ... Disclaimer: I am no ActiveX in Dolphin expert, what I know has been gleaned from a little experience. I call upon the real experts to correct me or clarify things. ;) Actually it does magically use the classes you generated. ;) When you instantiate it Dolphin does some stuff behind the scenes and associates the generated class with it. I believe the classes help to make it faster, and also allow you to fix methods (I had to fix at least one). I don't think the ActiveX generated package will automatically be considered a prerequisite of your application package, so if you save the packages out and load them into a new image you will need to make sure the ActiveX generated package gets loaded. Also when you deploy your application you will need to make sure the ActiveX generated classes don't get stripped. You can easily make it a manual prerequisite (package context menu, properties). Dolphin does shield you from many of the ActiveX gory details, however there are limits to what it can automatically do for you. Based on previous conversations I have had in this group (should be in the archive) it seems that ActiveX can have a strong VB bias. ActiveX in Dolphin is not as easy as it is in VB. However with a little experience and once you know the ins and outs one can quite readily use ActiveX in Dolphin. Good luck, Chris |
In reply to this post by ar
Alan
... In both posts it seems like you are not suggesting using the actual smalltalk classes which were generated. eg using IDispatch instead of the subclass ContinuumClient. I guess you guys got involved with COM on Dolphin from before it generated classes which I thought would shield me from the gory details. It will shield you from the gory details to a reasonable extent, however it will not prevent you from getting to them. Unlike VB, Dolphin allows one to get down to the lowest levels of COM/Active-X, but on the other hand (and to some extent in consequence) some tasks are more involved. You will be better off using the generated classes than going through IDispatch, but this will happen automatically anyway (see below). Anyway I think you are both saying a similar thing about the control being expected to be used like a visual control or that it doesnt have a server connected to it, but I dont understand the implementation of com well enough yet to know what that really means. (got my Inside Com and Understanding Activex on order:) . Anyway I should probably be able to tinker with that code Chris and get it to work ( I once got this to work in VSE a few years ago). Thanks again. Chris is right. This particular control expects to be "hosted" as a full OCX, even though it is non-visual. The "Catastrophic Failure" error is the rather over-dramatic description for one of the standard error conditions E_UNEXPECTED (try 'HRESULT fromInteger: (Win32Errors at: #E_UNEXPECTED)'). In this case I imagine it is reporting that it wasn't expecting the method invocation before it had been "activated". I haven't looked at the code Chris posted in detail, but I'm sure it demonstrates how to programmatically host a visual control without actually having to put the control into a view, though of course you could do that if you wish, just as you'd have to drop the control onto a Form in VB in order to use it. You won't have wasted your time generating the interface wrapper classes, since the control host's #controlDispatch method will answer the most specific interface it can (falling back on IDispatch if the OCX's specific default interface has not been generated). If the interfaces have not been generated, then going through IDispatch is possible, but slower and considerably more clunky. Regards Blair |
In reply to this post by ar
Alan
You wrote in message news:=3AVPC=[hidden email]... > Thanks Eric and Christopher. > > In both posts it seems like you are not suggesting using the actual smalltalk > classes which were generated. eg using IDispatch instead of the subclass > ContinuumClient. I guess you guys got involved with COM on Dolphin from before > it generated classes which I thought would shield me from the gory details. It will shield you from the gory details to a reasonable extent, however it will not prevent you from getting to them (and perhaps being got at by them :-)). Unlike VB, Dolphin allows one to get down to the lowest levels of COM/Active-X, but on the other hand (and to some extent in consequence) some tasks are more involved than in VB. You will be better off using the generated classes than going through IDispatch, but this will happen automatically anyway (see below). > Anyway I think you are both saying a similar thing about the control being > expected to be used like a visual control or that it doesnt have a server > connected to it, but I dont understand the implementation of com well enough > yet to know what that really means. (got my Inside Com and Understanding > Activex on order:) . Anyway I should probably be able to tinker with that code > Chris and get it to work ( I once got this to work in VSE a few years ago). > Thanks again. Chris is right. This particular control expects to be "hosted" as a full OCX, even though it is non-visual. The "Catastrophic Failure" error is the rather over-dramatic description for one of the standard error conditions E_UNEXPECTED (try 'HRESULT fromInteger: (Win32Errors at: #E_UNEXPECTED)'). In this case I imagine it is reporting that it wasn't expecting the method invocation before it had been "activated". I haven't looked at the code Chris posted in detail, but I'm sure it demonstrates how to programmatically host a visual control without actually having to put the control into a view, though of course you could do that if you wish, just as you'd have to drop the control onto a Form in VB in order to use it. You won't have wasted your time generating the interface wrapper classes, since the control host's #controlDispatch method will answer the most specific interface it can (falling back on IDispatch if the OCX's specific default interface has not been generated). If the interfaces have not been generated, then going through IDispatch is possible, but slower and considerably more clunky. Regards Blair |
In reply to this post by Christopher J. Demers
Chris,
>This is what I use: Thanks, that code worked for me, using the AXControlSite. Now I'm trying to get events. Here is my test code: cc := AXControlSite progId:'ContinuumClientX.ContinuumClientCtrl.1' . q := cc controlDispatch. q when: #StatusMessage: perform: [ : text |Transcript cr; nextPutAll: text ]. q trigger: #StatusMessage: with: 'test' . "this works on 2nd evaluation (?)" q connect. I dont get the heartbeat event from the server. (like the browser does). What am i missing? -alan |
Alan
You wrote in message news:GnQZPHc1Wd6nSC0m=+[hidden email]... > .... > Thanks, that code worked for me, using the AXControlSite. Now I'm trying to > get events. Here is my test code: > > cc := AXControlSite progId:'ContinuumClientX.ContinuumClientCtrl.1' . > q := cc controlDispatch. > q when: #StatusMessage: perform: [ : text |Transcript cr; nextPutAll: text ]. > q trigger: #StatusMessage: with: 'test' . "this works on 2nd evaluation (?)" > q connect. > > I dont get the heartbeat event from the server. (like the browser does). What > am i missing? The events are triggered off the "presenter" of the control site (start browsing in AXControlSite>>connectSink). By default, as in this case, this will be the AXControlSite itself. Therefore your #when:etc messages should be sent to 'cc' rather than 'q'. As background information there are 3 mechanisms by which one may receive events from a control: 1) Specific/individual events, as defined in the default 'source' interface of the control. These are they which you are trying to receive above. By default the triggering of individual events is enabled. 2) A generic event, #axEvent:withArguments:, handlers of which receive all the specific events with the name of the event being the first argument. This is how the control browser receives all events from a control without having to explicitly register handlers for each and every one of them. This is mostly useful for generic hosts (such as the control browser). By default the generic event is disabled, aAXControlBrowser>>updateControlInfo shows how to enable it. See also AXControlBrowser>>onViewOpened (which registers a handler for the generic event), and AXControlBrowser>>onEvent:withArguments: (the generic event handler) 3) Property changing and changed notifications. This is a separate, generic, mechanism by which OCXs request permission from their host to change the value of a property, and subsequently notify observers that a property value has been changed. Again see AXControlBrowser>>onViewOpened (which registers handlers for the property change notifications) and AXControlBrowser>>onPropertyChanging:accept: and AXControlBrowser>>onPropertyChanged: (the handlers for the changing and changed notifications respectively). As for why you don't see any output on the Transcript at first, this is because the output is buffered and is only displayed when the buffer is flushed. Emiting a cr flushes the buffer automatically, so send #cr last rather than first. Regards Blair |
In reply to this post by ar
ar <[hidden email]> wrote in message
news:GnQZPHc1Wd6nSC0m=+[hidden email]... > Thanks, that code worked for me, using the AXControlSite. Now I'm trying to > get events. Here is my test code: > > cc := AXControlSite progId:'ContinuumClientX.ContinuumClientCtrl.1' . > q := cc controlDispatch. > q when: #StatusMessage: perform: [ : text |Transcript cr; nextPutAll: text ]. > q trigger: #StatusMessage: with: 'test' . "this works on 2nd evaluation (?)" > q connect. > > I dont get the heartbeat event from the server. (like the browser does). What > am i missing? Sorry for the delay, I just came back from a visit to Florida. Unfortunately I can not help you with this as I have not used qfeed events. My program does not use the streaming feature, but rather polls snapshots for different stocks at preset intervals. My understanding is that you can only stream data for one symbol at a time with qfeeds. Hopefully Blair's comments will help you. Good luck, Chris |
I am getting a message, 'HRESULT Error: Type mismatch' when calling a
generated method in a _DTRecordSet. The method is defined as: getRecString: nRecord fIx: fIx "Answer the <BSTR> result of invoking the COM Object's GetRecString() method." ^(self invokeId: 28 with: nRecord with: fIx) My call is: self getRecString: 0 flx: 3 nRecord and flx are definitely supposed to be integers (indexes) For some reason, the doc I have for this method does not match: bool TRecordSet::GetRecString(RECIX r, FLDIX f, LPTSTR lpStr, int maxCount); I cant account for the difference but I'm pretty sure that the generated st code above is the correct wrapping of this function. btw does Steve Waring still hang out here (fellow Dolphin/Qfeed user who has gone a lot further with it than I ) |
Free forum by Nabble | Edit this page |