During the past few days, I have experimented with an ActiveX control called
SpriteX that can be used for simple sprite animations. It is shareware and can be downloaded from http://www.catalystpics.co.uk/spritex.htm . I am, however, not able to get it to work properly and I don't quite understand why. Therefore, I thought that I might describe what I have done step-by-step in case someone with more experience from this could explain to me what I should change in order to make it work. The goal is to wrap this control using the Basic MVP Component pattern, because I want to be able to use a number of these controls in Shells. 1) The first thing I did after downloading and installing the control was to open an AX Control Browser and examining it. This works and events are generated. 2) I opened the AX Component Wizard and generated the two interfaces of the control, _DSpriteX and _DSpriteEvents. 3) I subclassed AXControlSite with a new class that I called SpriteX. 4) I added the SpriteX class>>spriteX which looks like this (comments removed): SpriteX class>>spriteX | spriteX | spriteX := self progId: 'SPRITEX.SpriteXCtrl.1'. spriteX dispControl: (spriteX controlUnknown queryInterface: _DSpriteX). ^ spriteX 5) After that I added this instance side accessing method: SpriteX>>dispControl: interface dispControl := interface 6) I then added another instance side method used to test the control: SpriteX>>aboutBox "open the about box of the control." dispControl aboutBox 7) I then registered the new SpriteX class as a resource like this: SpriteX makeResource: 'Default view' inClass: SpriteX 8) Now it was time to create a shell for testing the control. I made it a subclass of Shell and called it SpriteTest. 9) I added an instance variable called spriteX to keep the SpriteX presenter (which is also the view). After that I created #createComponents like this: SpriteTest>>createComponents super createComponents. spriteX := self add: SpriteX spriteX name: 'SpriteX' 10) since the control doesn't have a proper model (instead it has a number of sprites and a background) I decided not to override the default #defaultModel class method. 11) I added a new view to SpriteTest using the VC and saved it as 'Default view'. Therefore, I didn't have to override #defaultView either. 12) Thinking that I was finished, I evaluated: SpriteTest show which gave me the first walkback: 01:13:50, den 30 december 2000: 'SpriteX does not understand #parentPresenter:' SpriteX(Object)>>doesNotUnderstand: SpriteTest(CompositePresenter)>>add:name: SpriteTest>>createComponents SpriteTest(CompositePresenter)>>initialize SpriteTest(Presenter)>>on: SpriteTest class(Presenter class)>>on: SpriteTest class(Presenter class)>>new SpriteTest class(Shell class)>>create: SpriteTest class(Presenter class)>>create SpriteTest class(Presenter class)>>show 13) I guessed that this was because of me using the view as both view and presenter (not finding #parentPresenter: since it belongs to Presenter and not View) and therefore added an instance variable called parentPresenter to SpriteX and generated accessors for it. Then I tried again: 01:22:18, den 30 december 2000: 'SpriteX does not understand #view:' SpriteX(Object)>>doesNotUnderstand: [] in SpriteTest(CompositePresenter)>>view: OrderedCollection>>do: SpriteTest(CompositePresenter)>>view: SpriteTest(Shell)>>view: SpriteTest class(Shell class)>>create: SpriteTest class(Presenter class)>>create SpriteTest class(Presenter class)>>show 14) I repeated the above process with an instance variable called view. Then I tried again. The result this time was that the 'Active-X Control Site Copyright Object Arts Ltd' was shown instead of the SpriteX control. Normally this means that the control hasn't been properly registered, but after modifying AXControlSite class>>example2 I found out that this was not the case this time. By debugging the code and examining the SpriteX instance that was created, I found one thing that seemed strange. Although the SpriteX instance's #parentPresenter is the SpriteTest instance, it's #parentView isn't the ShellView of SpriteTest but instead a DesktopView. In #example2 when the parentView is set manually to a ShellView which seems more logical. I therefore tried to do something similar by modifying number 9) above: SpriteTest>>createComponents super createComponents. spriteX := self add: (SpriteX spriteXOn: self view) name: 'SpriteX' Unfortunately, this doesn't work, since the 'self view' at that time is a DeafObject and not a proper view. This leads to a number of questions: a) are there any major design flaws in what I have described above? b) is the analysis in 14) correct or is there another reason for the strange behaviour? c) asked in another thread: does my adding of #parentPresenter: and #view to SpriteX have anything to do with the strange result and in that case, what should be done instead? d) and of course: what should I change in order to make it work? If someone is still reading this I would be very grateful for any help in solving the problem. By the way, if anyone would like to take a look at the code, the package is only 29kB (but of course the ActiveX control is a bit larger). Thanks in advance Mikael Svane [hidden email] |
Mikael,
I know sod all about the ActiveX stuff but looking at the examples (especially AXControlSite>>exanmple3) they don't appear to try to provide a Presenter for the View. The only linkage is seems to be that the AXControlSite view knows who it's parent view is, and that should automatically be done for you anyway when the views are created. Try deleting the #createComponents method completely (which should get rid of your #parentPresenter problem?) and communicate directly with the view. SpriteText>>onViewOpened super onViewOpened. spriteX := self view viewNamed: 'SpriteX'. But remember that it's just a guess from a position of complete ignorance <g> Ian |
Ian,
Thank you very much. This solved both the #parentPresenter: and the #view: problems. However, the control still showed the Object Arts text instead of the right one. Inspecting the SpriteX instance of SpriteTest showed that it's progId was not the one that I had specified but instead was the AXControlSite>>defaultProgId. Changing SpriteTest>>onViewOpened to this: SpriteTest>>onViewOpened super onViewOpened. spriteX := self view viewNamed: 'SpriteX'. spriteX progId: 'SPRITEX.SpriteXCtrl.1' solved the problem. I still haven't found why AXControlSite class>>progId: (see SpriteX class>>spriteX in the original post) doesn't work in this case, but I will investigate. > >But remember that it's just a guess from a position of complete ignorance ><g> If my entire program didn't consist of "guesses from a position of complete ignorance" it would probably work better. What you wrote seems to be more of an educated guess to me ;) Thanks a lot for your help! Mikael Svane [hidden email] |
>
>SpriteTest>>onViewOpened > super onViewOpened. > spriteX := self view viewNamed: 'SpriteX'. > spriteX progId: 'SPRITEX.SpriteXCtrl.1' > >solved the problem. I still haven't found why AXControlSite class>>progId: >(see SpriteX class>>spriteX in the original post) doesn't work in this case, >but I will investigate. > There is a simple reason for this. Since the SpriteX is no longer created using SpriteX class>>spriteX (which was evaluated in SpriteTest>>createComponents which was removed), the default progId is used. However, simply adding SpriteX>>defaultProgId doesn't work. For some reason spriteX progId: 'SPRITEX.SpriteXCtrl.1' must be used. /Mikael [hidden email] |
Mikael,
Glad I could help with the original problem. > However, simply adding SpriteX>>defaultProgId doesn't work. I can hopefully explain that as well as it's probably just a manifestation of behaviour that you have to be aware of when creating View subclasses. #defaultProgId is called from the view's #initialize method (when it is used in the way you intend here) and the #initialize method is only called when the view is initially created. Just adding #defaultProgId to a class will not make any diference to existing instances (including the one stored in the binary resource) of the class. Try adding the #defaultProgId method, recreate the resource (using #makeResource) and then recreate your Test shell to use the new resource. Using 'mutate' in the VC will also work but only for the shellview instance containing the subview you mutate (I think?) Ian |
Free forum by Nabble | Edit this page |