Getting started with Icons?

Getting started with Icons?

Post by TimM » Fri, 30 Sep 2005 23:19:33

If I want to add a pushbutton with an Icon to one of the existing
Dolphin browsers - how do I get started in uderstanding how Icon's

In the ViewComposer I can add a button, and I can see the Image aspect
that I can edit and add some code to.

I am assuming I do something like: Icon fromId: x

In browsing senders of this method "x" can be a string or an int. I see
lots of different callers to this - but can't figure out how I can work
out where these id's are coming from and how I can pick out some of the
small icons that Dolphin already uses.

If I use a resource program - I can see icon resources in some of the
Dolphin*.dll files but if I enter Icon fromId: 84 in the view composer
it doesn't seem to show the icon I would expect. If I use the string
option - it seems like there are good many icons that aren't associated
with strings - and those that are - I'm not sure how I can select one
of the different sizes of icon associated with the "key".

So basically I am confused - I only have half an idea of what I'm doing
and am not sure where to read up on this...

Anyone have any tips for me?


Getting started with Icons?

Post by Chris Uppa » Sat, 01 Oct 2005 02:24:58

imM wrote:

I find the whole field pretty confusing (mostly MS's fault) and have yet to
find a good overview. The MS documentation simply stinks. Even Petzold wasn't
very much help.

Here's my current (gappy) understanding. I hope that it's some help, or at
least that someone else can fill in the gaps for both of us.

The thing to realise is that Windows has two completely different ways of
loading icons into a running program. One is to load them from a .ICO file;
the other is to load them from the "resources" bound into some .EXE or .DLL
(with the current program's .EXE as a special case of that). There are
separate APIs for the two operations, and they don't even look similar to each
other... (And, come to that, the actual binary layout of the Icon data is not
quite the same in the two cases, which just makes things more "fun", though it
shouldn't affect you unless you want to write an icon/resource editor.)

(BTW, one of the reasons that Petzold wasn't very much help is that he seemed
to concentrate on only the first of these, when the second is more common
use -- at least in the Dolphin system.)

Dolphin tries hard to hide this complexity, and does a good job for the most
part. The downside is that the code gets pretty complicated, and it's hard to
work out the underlying conventions that drive what's going on just from
reading it. (There seem to be blizzards of FileLocators flashing around, most
of which seem redundant, for instance.)

Anyway, the way to create an Icon from a .ICO file is 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. For instance there is a ImageRelativeFileLocator which
interprets the name as if it were relative to the location of the image you are
running. There are several other possible file locators you can use, or you
can write your own.

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. If you provide an absolute pathname then the
ImageRelativeFileLocator won't change what you've given it at all, so you can
say things like:

Icon fromFile: 'C:\Somewhere\filename.ico'.

and that will work wherever the image was placed.

As an aside, Icon>>printOn: produces confusing output since 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.

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 just for loading icons, so 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:\

Getting started with Icons?

Post by TimM » Sat, 01 Oct 2005 09:27:36

ey that was awesome - thanks for the description.

So I think I am still with you in understanding - however what happens in
the View Composer if you place a PushButton - To Toggle, and put an
expression in the Image aspect?

I was hacking the default view for the System Browser - and figured the Icon
fromId: would coincide with the icons in DolphinDR005.DLL but I cant' make
heads or tails of what the ID numbers mean - all the icon viewers I use give
numbers that when I use them in the compser just give me an exclamation mark
icon (which I think means it didnt find anything).

For some random numbers that work - it also seems pretty random what icon
size gets put in my button. If I use the string variation - and use a name
that my resource viewer (e.g. ResHacker) shows - again its not clear what
size icon will display. My button is 16x16 but I have no idea how to get
that sized icon into my button...

Its all a bit of a mystery - but I think I'm almost there in

Does this ring any bells with anyone else?


"Chris Uppal" < XXXX@XXXXX.COM > wrote in message
news:433c2403$0$38038$ XXXX@XXXXX.COM ...


Getting started with Icons?

Post by rush » Sat, 01 Oct 2005 14:33:11

Maybe if you save your icon only with one resolution, for instance 16x16.
But I am not completely sure that windows is also not trying to be smart
about icon sizes, and that it uses different sizes of icon depending on the
screen resolution, large/small font settings and phase of the Moon.

As for guessing Id's during the initial development, you can often get away
with by finding a class that uses it and implementing >>icon as:

^ThatClass icon

Another story is when you want to have deployed app, preferably as a single
exe. There is a good description on the wiki, but I can not find the url
now. In short, first you would make your own version of togo stub, and
instruct Lagoon to use it. Then you would use reshacker or similar to add
icons you need to your stub. Good idea is that you name them the same way
they are named in the file system, for instance TRUE.ICO. The last touch is
to add method to some well known and accessable place, like session manager,
that loads icon given string name. That method would look if current session
maneger is runtime, and if yes fetch the icon from the stub, othervise fetch
the icon from the file.


Getting started with Icons?

Post by Andy Bowe » Sat, 01 Oct 2005 17:29:46


All of the icons in DolphinDR005.DLL have string based (not integer
based) IDs. It's possible that some resource viewers may also display
integer IDs but these won't work correctly using Icon>>fromId:. All of
the string IDs are based on the original icon filenames and many of
these filenames actually mirror the names of the classes that the icons
are meant to represent. However, there are a number of additional
icons in there that aren't associated with particular classes so I
thought it would be easiest just to dump off a directory listing of all
the icons from which DolphinDR005.DLL is composed. You can find this
listing at the end of this message (actually the listing is from the
Dolphin 6 version of the DLL so may contain a few names that aren't in
the D5 version).

So to get an icon for the Class Browser use:

Icon fromId: 'ClassBrowserShell.ico'

I think it is a bit of a mystery to everyone. In general Windows will
often pick the first format from the icon file and use that. Usually
that is the largest format and scaling down to small sizes may or may
not produce a good result.

I guess that you haven't come to toolbars yet. These are yet another
magical mystery tour since, in D5 at least, they don't use icons but a
separate underlying bitmap of images for the buttons. This is all
gruesome beyond belief (remember the Dolphin is just reflecting the
underlying Windows unpleasantness here) which is why in D6 we have
introduced another sort of toolbar button, ToolbarIconButton, which
will automatically generate the underlying bitmaps from the icon
associated with the button's CommandDescription.

One of the great things about this automatic generation of the bitmaps
is that it is much easier to change the size of the toolbar in D6
because the icons can be dynamically rendered at whatever size you
choose. In D5 if you wish to create a toolbar with different sized
buttons you'll have to manually re-render yourself a new image bitmap.

I hope this has helped rather than hindered...

Best regards,

Andy Bower
Dolphin Support

Address Book.ico
Check spelling.ico

Getting started with Icons?

Post by Andy Bowe » Sat, 01 Oct 2005 18:27:24


BTW, I think I should have mentioned that if you are doing your own
drawing of icons (rather than letting Windows do it for you inside one
of its own controls) it is possible to explicitly choose which size of
image you wish to use. You do this using an ImageManager which is a
Smalltalk wrapper around the underlying WinImageList common control. In
particular, for icons, there is a Singleton instance of
IconImageManager that can be used to hold the various sizes of image
that an icon contains. You may find it instructive to look at the
StatusBarItem>>drawImageOn:in: method.

Best regards,

Andy Bower
Dolphin Support

Getting started with Icons?

Post by Chris Uppa » Sat, 01 Oct 2005 18:59:25

As far as I can tell, the underlying Windows APIs for adding resources simply
don't work unless the name is all UPPERCASE (or numeric).

In general , I don't think that extra logic should be necessary. Once you
have an override of SessionManager>>defaultResLibPath (so that it will look for
resources in the .exe) it should be sufficient to (say) use an icon like
Icon fromFile: 'MYICON.ICO'
and if there is a resource of the same name in the .exe then that will be found
without looking for the file. At least, I /think/ that's how it works...

-- chris

Getting started with Icons?

Post by Chris Uppa » Sat, 01 Oct 2005 19:00:03

I'm not sure what you mean here ? The brief (brief 'cos I may be completely
missing the point) explanation is that the expression is evaluated, and the
result is sent to the PushButton object as the argument to its #image: method.
The little workspace is then updated to display the #printString of the value
answered by the PushButton's #image method (i.e. the Icon instance you
created). When the view is saved as a resource, the Icon instance is saved
with it as part of the STBed byte array. When you later show the view, the
view is reconstructed from the saved bytes, the Icon instance getting
re-created along with everything else. When the Icon is actually displayed, it
will use the embedded record of the filename and/or resource library to
recreate the underlying Windows "icon" by re-reading the file or re-loading
from the resource. (There's also some caching going on that I don't fully

I think you must be doing something wrong (helpful comment !). For instance
the following code:

button := PushButton show.
button command: #exit.
button image: (Icon fromId: 134 in: ShellLibrary default).

shows exactly the same image as I see in SHELL32.DLL (in the Windows system32
folder) when I look at icon #134 in the resource editor I'm using today ("XN
Resource Editor"). Can you give a reproducible example based on that code ?

As far as I can see it's entirely up to Windows which image it will use from an
Icon. My /guess/ is that a push-button will use the same sized image as an
Icon instance will answer if you send it #extent, and that that is (somewhere
in Windows) determined by the user's settings. If you need precise control,
then it's probably better to use a Bitmap instead.

BTW, there is code in the image for deriving a Bitmap from an Icon -- it's
rather buried away in CommandMenuItem>>bitmapFromIcon: (just where you'd
/expect/ to look ;-) but it will serve as an example. A warning: if you use
code of that kind to create bitmaps of any extent other than the ones that are
already in use (16x16 and 32x32 on my machine) then that will result in the
system creating an ImageList containing representations of every icon at the
new size, and they don't go away again until the image is restarted.

-- chris

P.S. Do you think you could trim a little from replies rather than quoting an
entire long message ? TIA.

Getting started with Icons?

Post by TimM » Wed, 05 Oct 2005 17:34:33

Thanks for patiently shwoing me I'm not going crazy. I tried this example,
and it works as you suggest (even in the ViewEditor which I thought might be
different) - except that the icon is too large for the button I want to put
it in.

I think Andy sorted my problem - in that the id's shown in the Dolphin dll
are some mysterious artifact - whereas in Shell32 they were created that way
(I guess).

Anyway, it seems like if I want a small 16x16 icon for a button I'm better
off extracting it and saving it in a different file - or investigating the
bitmap option... Ahh so many things to learn!

Thanks to everyone for their input.