Toolbox: How do I show a window that hasn't been shown before?
Chris Mahoney (1684) 2165 posts |
I think I’m down to my last remaining issue :) In my C Toolbox app, I’ve implemented save and load functionality. Save is working, and Load is working… if you load “into” an existing window. My problem is that if my app isn’t running, and the user double-clicks on one of its files in Filer, then my app starts up and loads the file into memory but doesn’t bring up a window. Normally I let the Toolbox handle windows. I have my main window on the icon bar icon’s “show object” so that it pops up when clicked. I grab and record the window’s ID in its “before showing” event. However, if my app has only just been launched, then the “before showing” event hasn’t yet run and I don’t know the window’s ID. I therefore have nothing to pass to toolbox_show_object. How can I open a window that hasn’t been “seen” yet? Is there some code I should be using, or is there a way (e.g. in ResEd) to ask the Toolbox to open window X “on load”? |
Chris Hall (132) 3554 posts |
Yes, !PhotoDesk does the same. Just open the window, using the open window poll event pointing to the window definition. When your app starts it will be able to use OS_GetEnv to see what started it and identify (if it was a file double-clicked on) the filename that was double-clicked on. It can then open a window showing it. Simple. If it is already running then when the user double -clicks on a file, a message is sent to all running apps to see whether any need to respond to that filetype. |
Colin (478) 2433 posts |
The Toolbox_ObjectAutoCreated event should be generated at start up for the window used by the iconbar object. I find it easier to create the object with toolbox_create_object at startup then you are not waiting for events to happen. You can then use iconbar_set_show() to set the window that is opened on select. |
Steve Drain (222) 1620 posts |
I think you will get all the AutoCreated events before anything else happens and using BASIC, with Basalt or not, trapping that event is the easiest place to create variables for object handles. Doing it that way keeps the creation of resources out of the program, which I feel is neater, and means that ResTest shows the whole interface. Perhaps C is not quite as amenable in that respect. ;-) |
Colin (478) 2433 posts |
Nah even in basic I find it easier not to use AutoCreated. If you are going to create a window on startup or on a wimp message you have to use toolbox_create_object and you know the id after calling that and would initialise any variables at that point so you may as well use the same code for all instances. |
Steve Drain (222) 1620 posts |
You do not have to create the object in the program in that situation – you set the Object flag ‘AutoCreate’ in ResEd and procede as I suggested. Then “all object are alike to me” which reduces the need to think too carefully about what has to be done in the code. I acknowledge that there might be circumstances where delaying the creation of an object to some time after the start is appropriate – but I cannot think of one. ;-) |
Colin (478) 2433 posts |
You do if creation of the window is optional ie the program is run by clicking on a file or just clicking on the program also for Message_DataOpen messages and generally any situation where you want multiple instances of the same object determined at runtime eg text editor windows. |
Steve Drain (222) 1620 posts |
Of course. I once realised that, but, you know, age etc. Apart from that, are there any others? I have never written anything that did, which is a more honest comment. ;-) |
Steve Drain (222) 1620 posts |
Ignore us. We a just quibbling of a matter of programming style. Such exchanges are, perhaps, useful, because they may elucidate what can be done. If the TB is suitable, it is lot quicker and simpler to program than the sequence you wrote. Like a lot of others, I’ve been there and done that. ;-) |
Colin (478) 2433 posts |
Any editor – paint, artworks, easywriter, edit, filers – ftpc. Basically anything where you can’t define all windows beforehand. My point is though that using toolbox_create_object explicitly can always be used whereas Toolbox_ObjectAutoCreated is limited to certain circumstances so why bother learning 2 methods. In Chris’s example though neither is necessary. As he has specified the window to open in the iconbar object there will be only one instance of the window so he can just read the id from the iconbar_get_show method instead of waiting for a Toolbox_ObjectAutoCreated event. |
Steve Drain (222) 1620 posts |
He can, but IMHO that is a very cack-handed way of doing things, which requires a specific knowledge of how the Res file has been constructed. It contradicts my OO principles. ;-)
You will get such an event before everything else, if you have registered it, so there is no waiting for it. There are many paths to a working program. |
Colin (478) 2433 posts |
Ah but my OO principles ensure that when I create an object which includes a window that all the variables are constructed before I leave the constructor. Your method can’t do that it has to wait for an event. If the object contains 2 windows that isn’t a problem with my method. If you are creating your object in a Toolbox_ObjectAutoCreated event which of the 2 windows created events do you create your object in? It also seems odd to me creating an object after a sub object is created. It’s interesting that you prefer the event method as when I wrote a C++ toolbox library I couldn’t see what problem it was trying to solve – which usually means I don’t understand something – people don’t write things for no reason. Obviously it fits in with your world view so seems natural to you. The other thing I’ve never used is the objects client handle but have been thinking recently that this may be useful in BASIC. |
Steve Drain (222) 1620 posts |
I think we must be talking at crossed-purposes here. You do not create an object in response to this event – the TB has already done that – but you do get the object template name and the id block from which to create the handle variable. The only reference to an object I am concerned with is its handle. Everything else is either an attribute of, or an operation on, that object. I should never need the window handle in the normal course of things, even though I have used it in my version of Steve Fryatt’s MouseInfo. If an object uses more than one window does that matter? The TB handles that.
variables==attributes? I can appreciate that, but it can be done in the AutoCreated event instead. Even so, that can sometimes throw up a problem. In the later versions of Basalt I made the INITIALISE keyword generate a Toolbox_Initialised event (not in the TB itself) so that some things could be set up immediately [Edit: after the AutoCreated events].
That is not what happens – see above – so it does not matter which order the AutoCreated events come in. I expect they are are dealt with recursively, so a child object would come before its parent.
Nor I, but I have foreseen its use in associations. |
Chris Mahoney (1684) 2165 posts |
I go away for a few hours, and… :) Thanks for the tips. The Toolbox manual seems to agree that capturing Toolbox_ObjectAutoCreated is the way to go – at least it implies that that’s the reason for the event’s existence:
It’s working; I pass the resulting object ID to toolbox_show_object and the window pops up as expected. Now I’ve found another bug, but one thing at a time… Edit: Remaining bug fixed. The problem was that when the app is first loaded, it was running the “Load” function before event_poll had run enough times to grab the Toolbox_ObjectAutoCreated event (which may (or may not!) have been what Colin was originally getting at re: “waiting for events”). I got around it with a simple while loop where I call event_poll until my object ID variable is set, and only then do I check argc/argv and load the file. |
Steve Drain (222) 1620 posts |
You could try the thing I did with Basalt. Raise an event (SWI Toolbox_RaiseToolboxEvent), with a number of your choice, immediately after Toolbox_Initialise. That event will be in the queue after the AutoCreated events, so when you trap it you should be able to rely on the object handles. |
Chris Mahoney (1684) 2165 posts |
I changed my “load” code slightly, so it’s cleaner than it was, but still loops around event_poll a few times. At this stage I’m just going to leave it alone since it is all working :) I’ve tidied up a few more things too, so the code is a bit cleaner and easier to follow, so that always helps. Now I just need to hook up a discard/cancel/save box, which I don’t foresee too many issues with. |
Colin (478) 2433 posts |
I think we are :-) The confusion is probably my use of the word object – I’m not just talking about toolbox objects. I see toolbox objects as just objects in my program. My program creates its own (nothing to do with toolbox) objects. The object I create can be made up of various other objects which may include several toolbox objects. When I construct this object I need all the contained objects to be constructed – for toolbox objects that means I need the ObjectId and you can’t get the ObjectId at a time of your choosing using a wimp poll event.
Getting the ObjectIDs in the above with wimp_polls is tricky. Where you would initialise your variables in the AutoCreated event that is the equivalent of me calling construct (without the toolbox_create stuff but initialising the ObjectIds) in an AutoCreated event. Anyway good to see that Chris has his program working and seen the pitfalls of the AutoCreated event – he’s probably thinking ‘you ask a simple question…’ :-) |
Steve Drain (222) 1620 posts |
Thanks for that clarification. I have nothing more than an onlooker’s interest in C++, but I have wondered how it could integrate with the Toolbox. It seems clear that if you are dealing with other constructors, then constucting TB objects in the same way is natural. For more general purposes, letting the TB do the constucting (creating) is the simpler option. I admit that I came up against its limitations when you want to initialise objects, say from a Choices file, and it took me some years to come up with the method I pointed out above. There are other ways, but not as elegant IMHO. ;-) |