Newsgroups : Borland : borland.public.delphi.nativeapi.win32 : 2008 Mar : Icons returned by API function SHGetFileInfo
| Subject: | Icons returned by API function SHGetFileInfo |
| Posted by: | "Enquiring Mind" (enquiring.mind@nospam.btopenworld.com) |
| Date: | Tue, 25 Mar 2008 12:13:00 |
Hi,
In order to explore the behaviour of the API function SHGetFileInfo, first I
created a Pascal encapsulation of the API function and its associated data
types, and then I created a form that displays all the API function's
parameters, appropriately converted to their equivalent Pascal data types,
in VCL controls. For example, the parameter "UINT uFlags" is converted to a
set data type, and is then displayed in a CheckListBox.
The API function returns the following parameters defining the requested
icon associated with the specified file:
- ShFileInfo.IconHandle:= ShFileInfoA.hIcon; {Icon handle}
- ShFileInfo.IconIndex:= ShFileInfoA.iIcon; {Icon image list index}
- function result: DWORD {Handle of icon image list, depending on
value of uFlags}
My form includes 2 private variables named FIcon: TIcon and FIconImageList:
TImageList to which I pass the handles returned by the API function. The
FIcon object is displayed in a TPaintbox component, using the component's
OnPaint event handler to draw the FIcon graphic in the top left hand corner
of the component. The icons in the FIconImageList object are displayed in
the cells of a TDrawGrid component, the appropriate drawing being executed
in the component's OnDrawCell event handler.
To exercise the API function the user selects a file, then sets the values
of the uFlags components by clicking the corresponding check boxes. Once the
API function input data has been thus input interactively, the user can
click a button to execute the API function and see the results displayed in
the user interface components corresponding to the TShFileInfoA record and
to the function result.
The first time the API is executed in the way described it functions
satisfactorily. However, in subsequent executions of the API function, for
different values of the uFlags control parameters changed to request
different types of icon (e.g. large/small, with/without link overlay,
with/without selection colour blending, open/closed, etc), the function
sometimes returns an icon handle of value zero when it should not be zero.
As far as the ImageList is concerned, although the API function usually
returns a non-zero value for the icon image list handle, after the handle
is assigned to the Handle property of the FIconImageList object, the
object's Count value is sometimes zero, suggesting that the image list is
empty, even though the value of the Icon index returned is greater than
zero, suggesting that the image list should *not* be empty.
The most worrying aspect of this behaviour is that when one resets the
control flags to the initial values that initially resulted in the correct
icon to be returned, the initial icon is not replicated.
My initial supposition is that the unsatisfactory behaviour described is
due to incorrect handling of the FIcon and FIconImageList objects. If I
understand correctly, these components do not own the image data themselves,
but are just wrappers to Icon and ImageList objects owned by the operating
system. Therefore incorrect manipulation of these objects could cause the
operating system to return incorrect results.
The first question is therefore: The API seems to return the icon data in 2
different ways: a) as an icon handle; b) as an icon index pointing to an
ImageList defined by an ImageList handle. How do these 2 representations
relate to one another?
The TIcon component has a ReleaseHandle method which I understand releases
the OS icon object. I also understand that calling FIcon.Handle:= hIcon
should simply pass a reference to the system icon object to the TIcon
object. Is that correct? In fact, after the API function is executed, my
code updates the state of the FIcon object as follows:
FIcon.ReleaseHandle;
FIcon.Handle:= ShFileInfo.IconHandle;
By contrast, the TImageList class does not have a ReleaseHandle method to
release the ImageList object owned by the system. Therefore my code updates
the state of FIconImageList as follows:
FIconImageList.Handle:= 0; {Release existing image list}
FIconImageList.Handle:= Result; {Set image list handle to handlet
returned by API fn}
The question is: does this code correctly handle the system-owned Icon and
ImageList objects, or does it somehow corrupt them? Should the FIcon and
FIconImageList objects be destroyed and recreated?
A final question: the API defines the data types of some parameters as
"DWORD", and of others as "UINT". The Windows unit indicates that these both
map to the same Pascal data type LongInt . Why does the API use 2 different
data type identifiers for the same data type?
Thanks for any guidance.
EM