Hi All,
I want to know that is the idea for the use of List's #getImageBlock in runtime. I understands that the block should return an icon index, but I can't figure out how I should make a consistent managment of my resources between the development and runtime. What is suposed to do to have an application locating the images in runtime as in developent? thanks, Sebastian |
Sebastian,
"Sebastián" <[hidden email]> wrote in message news:[hidden email]... > Hi All, > > I want to know that is the idea for the use of List's #getImageBlock > in runtime. > > I understands that the block should return an icon index, but I can't > figure out how I should make a consistent managment of my resources > between the development and runtime. The very simplest way is to refer to icon resources by the filenames. Keep copies of your icon files in the same directory as your development image. When you deploy your application, you can either put the icon files in the same directory as the executable file, or (before you deploy!) you can add them as resources to the stub file the image stripper uses for deployment. Whether this is also the best way is open to question, but it is simple. Hope that helps, Don > > What is suposed to do to have an application locating the images in > runtime as in developent? > > thanks, > > Sebastian > |
Don,
I'm already doing the GUIToGo resource edition to embed the resources on the exe, and, as yu said, refering them by their names. What I want to have is a consistent way to work between development and runtime. Now, in development (and runtime) I'm also getting the icons of the by their names or as toolbar with an index. What I dont get is the #getImageBlock that wants an index (not being a toolbar). I'm trying to understand the intention of the choice of location of the icons in this way, so I can use it in the right way or customize to make it work in my way. Thanks, Sebastian |
Sebastian,
"Sebastián" <[hidden email]> wrote in message news:[hidden email]... > Don, > > I'm already doing the GUIToGo resource edition to embed the resources > on the exe, and, as yu said, refering them by their names. What I want > to have is a consistent way to work between development and runtime. > Now, in development (and runtime) I'm also getting the icons of the by > their names or as toolbar with an index. What I dont get is the > #getImageBlock that wants an index (not being a toolbar). I'm trying to > understand the intention of the choice of location of the icons in this > way, so I can use it in the right way or customize to make it work in > my way. you would put something like: [:item| item mySpecialListIcon imageIndex ] Or do I still misunderstand? Sorry if I'm being obtuse. Don > > Thanks, > > Sebastian > |
In reply to this post by Sebastián Sastre
Sebastián wrote:
> What I want > to have is a consistent way to work between development and runtime. > Now, in development (and runtime) I'm also getting the icons of the by > their names or as toolbar with an index. What I dont get is the > #getImageBlock that wants an index (not being a toolbar). I'm trying to > understand the intention of the choice of location of the icons in this > way, so I can use it in the right way or customize to make it work in > my way. I'm not sure what you are asking here. Is your question about how to locate icon (etc) files in a uniform way in both a development environment and in a deployed application ? If so then you may well find that a suitable ResourceLocator is the key. There's quite a bit about this question in the archives, or we can talk more about it here if you like. Or is your question about how to find a suitable icon /index/ ? If so then I don't think you need to bother about it. Icons look after their own indexes, so (as far as I know) there is never any reason to produce an image index that doesn't come from sending #imageIndex to an actual Icon. I don't really understand why the #getImageBlock is expected to answer an index, it would make much more sense (to my mind) if it just produced for an Icon. (There is, BTW, some very heavy caching of Icons in the system -- indeed the #imageIndex is part of that, normally hidden, sub-system, it has nothing to do with anything visible to a user). -- chris |
Chris,
actually I'm trying to locate resources in an uniform way in runtime and development, so I'll take a look at ResourceLocator. If you has some advice to this regard please tell me. In the other hand I also was mispointed (amplified by a little bug I found just a minutes ago in my code) by the #getImageBlock expecting an image index instead of an image. Perhaps calling that block #getImageIndexBlock would be a happier alternative. thank you for the clarity, regards, Sebastian |
Sebastián,
> actually I'm trying to locate resources in an uniform way in runtime > and development, so I'll take a look at ResourceLocator. If you has > some advice to this regard please tell me. BTW: I misnamed the locators; they are "FileLocators" not "ResourceLocators". Sorry if that confused anyone. This is an attempt to collect together what I know about resource location in Dolphin. It may be more than you want to read ;-) OTOH, it repeats stuff that I've said before in other posts, so it may be more than anyone else wants to read either... Another warning: this is all based on D5; I haven't looked to see what has changed in this area in D6 (I know there are at least a couple of enhancements). ====================== *** Some Background: *** When Dolphin reads an icon or bitmap, there are two fundamentally different ways it can do it (corresponding to two fundamentally different Windows features). It can load it from a "resource" embedded in an executable file (such as the current executable or some DLL), or it can load it from a file. One way to create an Icon is from a .ICO file, using by an expression like: Icon fromFile: 'filename.ico' usingLocator: aFileLocator. where the FileLocator is an instance of one of the subclasses of FileLocator whose job is to turn a "relative" filename into something that the Window's OS can actually open. (More on FileLocators below.) A slightly simpler form of the above is: Icon fromFile: 'filename.ico'. which is just the same except that it will use the default locator (which is an ImageRelativeFileLocator). (As an aside: when you look at an Icon (or whatever) in the VC, the information coming from the Icon>>printOn: is misleading. it /looks/ like a valid Icon creation expression (indeed it is valid -- just wrong), but the expression doesn't reflect the FileLocator that is actually in use. What's more the standard FileLocators don't have useful implementations of #printOn: either.) The alternative method of loading icons is from the resources compiled into a DLL (or .EXE). Here the fully general creation expression is something like: Icon fromId: 134 in: ShellLibrary default. Here you give an "id" which can be either a String or an Integer to find the correspondingly named icon resource in an instance of ExternalLibrary. ExternalLibraries are normally used for wrapping access to another DLL's code, not merely for loading icons, and you may well want to load icons from some arbitrary DLL (or .EXE) that doesn't already have a corresponding ExternalLibrary subclass. The special subclass ExternalResourceLibrary is intended to cover that case. You can say things like: notepad := ExternalResourceLibrary open: 'C:\Windows\system32\notepad.exe'. icon := Icon fromId: 2 in: notepad. notepad close. A couple of special cases. One is that if you miss off the library: Icon fromId: 428. or: Icon fromId: 'ASPECTBUFFER.ICO'. then Dolphin will look in the current SessionManager's #defaultResLibPath. By default that just points to the DolphinDR005.DLL resource DLL -- which isn't much use for deployed .exes unless you also ship that DLL with your application. It's normal to override that method to answer something like: defaultResLibPath ^ self imageFileName. in your applications' custom SessionManagers. A second special case is that you can provide nil as the ResourceLibrary, which is interpreted (by Windows) as a request to load resources from the current application's .exe. E.g: Icon fromId: '!APPLICATION' in: nil finds the application's "main" icon. I said above that there are "two fundamentally different ways" of loading an Icon. Actually Dolphin tries hard to merge them. The way it works is this: when you create an Icon with: Icon fromFile: 'filename.ico' usingLocator: aFileLocator. or Icon fromId: 'ASPECTBUFFER.ICO' in: anExternalLibrary the name part ('filename.ico' or 'ASPECTBUFFER.ICO') is stored in the Icon object as its #identifier. When Dolphin tries to load the data for that icon, it will attempt to use the #identifier with the corresponding Windows API to load the data from the requested place (file or DLL). If that fails, then it falls back to attempting to use the #identifier to load the data from the #defaultResLibPath. That (combined with the above override of #defaultResLibPath) can be very handy, because it means that you can (if you do it right) make Dolphin look for icons in external files in a development image, but look for Windows "resources" bound into the .EXE when deployed (more of this below). *** FileLocators *** Now, onto how FileLocators really fit into this picture, and some ideas about how they can be used. (We'll forget about resources in DLLs and EXEs for a minute -- I'll come back to that later.) When you create an Icon (or similar) the Icon instance stores the supplied filename in its #identifier, and also the FileLocator that you supplied (or the system default if you didn't supply one). When the image data for that Icon is needed, the FileLocator is used to convert the #identifier into a filename. The image data itself is not stored when Dolphin is closed down, just the information needed to reload it. That applies to deployed executables too, so the key to using Icons in deployed executables is to ensure that the Icon instances (whether stored inside "view resources" which you created with the VC, or created on the fly) have FileLocators which will be able to find the file corresponding to the #identifier when Dolphin (or the deployed exe) starts up. The simplest (but worst ;-) way is to use the absolute filename as the #identifier. Icon fromFile: 'C:\My Stuff\My Icons\filename.ico' FileLocators treat absolute pathnames specially, and don't try to resolve them. So that Icon will always look for its data in that file. The next simplest, is to use an ImageRelativeFileLocator (which, you may remember, is the default). Icon fromFile: 'filename.ico'. or Icon fromFile: 'filename.ico' usingLocator FileLocator default. or even: Icon fromFile: 'filename.ico' usingLocator: ImageRelativeFileLocator current. An ImageRelativeFileLocator (or rather, /the/ ImageRelativeFileLocator since its a Singleton) looks up Icons' #identifiers relative to the current image (which is the executable itself when deployed). So the above Icon would look for 'filename.ico' in the same directory as your development image, and at runtime would look in the same directory as your application. I prefer to put icons and such into a special 'Resources\' sub-directory, so we can elaborate that a little: Icon fromFile: 'Resources\filename.ico'. which will look in the Resources subdirectory of the place where your development image lives, or in the Resources subdirectory of where the application lives. Now let's get a little more elaborate still. I don't like putting my icons in the same folder as my image (or even in a sub-directory of it). I want to put the icons with the package that uses them. So this is where we get creative and define a custom FileLocator that understands /my/ way of doing things. We can define a PackageRelativeFileLocator which includes the name of a package as part of its definition. When it is asked to resolve: 'filename.ico' it first checks to see if it's in a development image. If it is, then it finds package with that name, asks the Package where it lives, and then resolves the filename relative to that. In a deployed executable it acts just like an ImageRelativeFileLocator. Icon fromFile: 'filename.ico' usingLocator: (PackageRelativeFileLocator packageNamed: 'MyStuff.pac') I have an implementation of that on my website, and a (slightly earlier) version of it is included as standard in D6. As before we can use a Resources\ sub-directory if we wish: Icon fromFile: 'Resources\filename.ico' usingLocator: (PackageRelativeFileLocator packageNamed: 'MyStuff.pac') *** Bound Resources *** That's pretty flexible, but we can go one or two steps further if we want. Next we have the option of binding icon files (etc) into the .exe itself as Windows "resources". To do that you use a resource editor such as "ResWhacker", "XN Resource Editor" or MS's Visual Studio (the editor in VC 6 is better than the one in VS 2003). You edit your executable to add the icon as a resource. Give the resource a name like: "FILENAME.ICO" (It has to be all upper-case or the lookup will fail at runtime!) which is the same as the Icon's #identifier. In D6 you can do that after the executable has been deployed. In D5 you have to edit the stub .EXE /before/ you deploy. Once you have done that (as I described above), the Dolphin runtime will find the data in the executable itself if it can't find it via the icon's FileLocator. But now we hit a snag. If we're using a Resources\ subdirectory, then the Icon's #identifier will be: 'Resources\filename.ico' and so we'd like to be able to use that (in upper-case, of course) as the name of the resource bound into the .EXE. Problem is that doesn't work -- Windows lets you /define/ a resource with that name (if I remember correctly) but it can't find it at runtime. So now for the last step in this over-long description. One way to fix this problem would be to change the various definitions of #loadFromInstance: so that they stripped off the directory part of any resource name before handing it to Windows. That might work, but I prefer to use a different approach. Enter my culminating custom FileLocator <drum roll>... PackageResourceLocator !!! This is very similar to a PackageRelativeFileLocator except that it also holds the name of a sub-directory ('Resources/' by default), where it "knows" that resources are kept. Icon fromFile: 'filename.ico' usingLocator: (PackageResourceLocator packageNamed: 'MyStuff.pac') This will automatically look in the Resources sub-directory of the image or package directory. And, since the Icon's #identifier is just 'filename.ico', Windows will be also able to find it in the executable (if it's there). That's also in package 'CU Package-relative File Locator' package on my website (under Miscellanea) if you're interested. I've described my own custom FileLocators -- they are useful for me, and maybe they'll be useful to other people too -- but the important point is that by defining your own FileLocators you can make Dolphin work /your/ way. ====================== That's it. Whew.... -- chris |
Chris, this is a very useful summary. Your Package*Locators are similar to
what I've wanted to do for a while (one of those low-priority items that never reached escape velocity). One problem for me was the desire to avoid hard-coding the package name in a method; whether I've expended more effort avoiding that remains an open question. This does leave me wondering how difficult it would be to make it all simpler for new users, though. It seems like integrating your locator classes with some means of binding packages' icons into the deployed image could remove some annoying barriers. It might be possible to utilize ResHacker's command-line features combined with your package-relative stuff to create custom stubs at (or just before) deployment time. (ResHacker can easily do bulk loading of resources into DLL and EXE files. Of course, Dolphin will eventually have that capability itself; I'm sure ImageStripper>>updateIconResource: is going to be done any day now. ;^) I'm thinking of a process like: scan the package's dependencies, exclude the OA packages, round up all the icon files in the packages' directories, write a resource script for the icons, and compile them into a new stub with ResHacker. I think I might look at how hard it would be to come up with a rudimentary first draft in the next week or so. Then we just need some way to manage resource files (icons, manifests, etc.) in STS... Don |
Don,
> One problem for me was the desire > to avoid hard-coding the package name in a method; whether I've expended > more effort avoiding that remains an open question. What I do is use a class-side helper method like: =========== resourceLocator "private -- answer a FileLocator that will find files in our standard location for resources" ^ PackageResourceLocator packageNamed: ##(self owningPackageName). =========== It does have to be recompiled if I move a class into another package or rename the owning package, but it's still better that hard-coding the name. (Especially as I put all my packages in the same directory anyway ;-) > This does leave me wondering how difficult it would be to make it all > simpler for new users, though. It seems like integrating your locator > classes with some means of binding packages' icons into the deployed image > could remove some annoying barriers. I've been pondering the same question, or a very similar one: "how can I make it simpler for /me/" ;-) What I lack is a good way of identifying the external resources that each package uses. I have a half-way solution which I use when I'm rebuilding the ZIP files to go on my website (and automatic process). Each package (that I put on the website) has a list of necessary external files (icons, bitmaps, DLLs, etc) that have to be included in the ZIP. That list is stored in the Package object's propertyAt: ExternalResourceFileNames which is set in the package's post-install script. If you have any of my software then you can probably find examples of that. It's a bit clunky, and I'd like to find something requireing less manual configuration, but it does work. I suppose that could be extended to all packages, and used by a custom ImageStripper[*]. (Come to think of it, that could also gather up any necessary DLLs, etc, as part of the same operation.) ([*] Ideally, factored out of the stripper class itself. We have to use ImageStripper subclasses for other reasons, so it should be easy to use this stuff from /any/ ImageStripper.) > I'm thinking of a process like: scan the package's dependencies, exclude > the OA packages, round up all the icon files in the packages' > directories, write a resource script for the icons, and compile them into > a new stub with ResHacker. Unfortunately that would be too coarse a selection for me -- as I said, I keep everything together... Another thing I'd want to do is to copy in any Dolphin resources that it used (the Booleans' icons, for instance). And that's a bit tricky to identify until after image-stripping has finished. Maybe it'd be possible to hack something up using the new XML manifest, but that would mean each deployment was dependent on the previous one -- which I'd rather avoid). > It might be possible to utilize ResHacker's command-line features combined > with your package-relative stuff to create custom stubs at (or just > before) deployment time. (ResHacker can easily do bulk loading of > resources into DLL and EXE files. Of course, Dolphin will eventually > have that capability itself; I'm sure ImageStripper>>updateIconResource: > is going to be done any day now. ;^) FWIW I put together some stuff for manipulating resouces a while back. It uses the Windows APIs directly. Unfortunately, there's a nasty bug in the Windows stuff and deleting resources corrupts the resource segment. I did find a (rather ugly) workaround, but have never gone back to build it into the classes properly, so I haven't published that stuff yet (although I've always intended to do so). I have just remembered that I put it on my "ephemera" website when I was asking here for help with testing it last year, and have never removed it. So if anyone wants to play with it, it's still at: http://ephemera.metagnostic.org/code/RWT.zip That includes both the correct version and the one with the workaround. Read /all/ the class comment of WindowsResourceWriter to understand why you should not use that class directly, but use its sub-class WindowsResourceWriterAlt instead. -- chris |
Free forum by Nabble | Edit this page |