Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

TImageIndex & Image Property Editor

466 views
Skip to first unread message

Roger Misteli

unread,
Sep 27, 2000, 3:00:00 AM9/27/00
to
Hoi :-)

I made a small component which is derived from TSpeedButton but uses an
ImageList and an ImageIndex property to get the actual image from an
imagelist. However, I encountered two minor problems that bug me:

1. The image is cropped in the half. I imagine this is because of the
enabled/disabled image, however, my current code inside SetImageIndex
looks like this:
procedure TImageListSpeedbutton.SetImageIndex(const Value:
TImageIndex);
begin
FImageIndex:=Value;
if (Value>=0) and Assigned(FImages) and (Value<FImages.Count) then
FImages.GetBitmap(Value, Glyph)
else
Glyph.Assign(NIL);
end;

which, in my opinion, only retrieves exactly the image it should
retrieve..

2. If you look at the TTreeView (and others) component and have a look
at the ImageIndex property, there is the D5 Imageindex Property Editor
registered and it also shows that already, however, not so in mine. My
code for the Images property looks like this:

procedure TImageListSpeedbutton.SetImageList(const Value:
TCustomImageList);
begin
if Assigned(FImages) then
FImages.UnRegisterChanges(FChangeLink);
FImages:=Value;
if Assigned(FImages) then
FImages.RegisterChanges(FChangeLink);
end;

I see, that it wants to use the correct property editor (because of the
list property type I get now), but it displays now images at all, but
both the Image property is set and the imagelist associated with that
property is filled with images (of the same size). And when I enter a
value that I am sure of appears in the image list, the button actually
changes the image (to that half cropped image version), but the
ImageIndex property keeps the value -1.

Does anyone have an idea what I do wrong here and would be so nice to
help me maybe :-)

Thanks in advance,
Rog

Peter Below (TeamB)

unread,
Sep 30, 2000, 3:00:00 AM9/30/00
to
In article <39D20DAC...@abanet.ch>, Roger Misteli wrote:
> I made a small component which is derived from TSpeedButton but uses an
> ImageList and an ImageIndex property to get the actual image from an
> imagelist. However, I encountered two minor problems that bug me:
>
> 1. The image is cropped in the half. I imagine this is because of the
> enabled/disabled image, however, my current code inside SetImageIndex
> looks like this:

You have to set the NumGlyph property to 1.

> 2. If you look at the TTreeView (and others) component and have a look
> at the ImageIndex property, there is the D5 Imageindex Property Editor
> registered and it also shows that already, however, not so in mine. My
> code for the Images property looks like this:

Your description of the problem confuses me badly. *Where*, exactly, is the
problem, in the setting of the ImageIndex property or the images property?

Peter Below (TeamB) 10011...@compuserve.com)
No e-mail responses, please, unless explicitly requested!


Roger Misteli

unread,
Oct 5, 2000, 3:00:00 AM10/5/00
to
> You have to set the NumGlyph property to 1.

Thanks. I found that out later on too, forgot about it :-)

> Your description of the problem confuses me badly. *Where*, exactly, is the
> problem, in the setting of the ImageIndex property or the images property?

Well, actually in both. If I set the ImageIndex, it jumps back to -1 and
if I drop down the images property editor, where usually all images of
the imagelist are shown, I don't see anything (and it looks like it
hasn't any values in there).
However, if I set the ImageIndex property manually, it changes the image
according to the new value, even though the value in the Object
Inspector jumps back to -1.

Here is what I wrote so far, maybe this explains it better (I hope its
allowed to post this here):

type
TImageListSpeedbutton = class(TSpeedbutton)
private
FImages: TCustomImageList;
FImageIndex: TImageIndex;
FChangeLink: TChangeLink;
procedure SetImageIndex(const Value: TImageIndex);
procedure SetImageList(const Value: TCustomImageList);
procedure ImageListChange(Sender: TObject);
protected
public
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
published
property Images: TCustomImageList read FImages write
SetImageList;
property ImageIndex: TImageIndex read FImageIndex write
SetImageIndex default -1;
end;

constructor TImageListSpeedbutton.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
FChangeLink:=TChangeLink.Create;
FChangeLink.OnChange:=ImageListChange;
FImageIndex:=-1;
end;

destructor TImageListSpeedbutton.Destroy;
begin
inherited Destroy;
end;

procedure TImageListSpeedbutton.SetImageIndex(const Value:
TImageIndex);
begin
FImageIndex:=Value;
if (Value>=0) and Assigned(FImages) and (Value<FImages.Count) then
FImages.GetBitmap(Value, Glyph)
else
Glyph.Assign(NIL);
end;

procedure TImageListSpeedbutton.ImageListChange(Sender: TObject);
begin
// ImageIndex:=ImageIndex;
end;

Peter Below (TeamB)

unread,
Oct 5, 2000, 3:00:00 AM10/5/00
to
In article <39DC4FAD...@abanet.ch>, Roger Misteli wrote:
> Well, actually in both. If I set the ImageIndex, it jumps back to -1 and
> if I drop down the images property editor, where usually all images of
> the imagelist are shown, I don't see anything (and it looks like it
> hasn't any values in there).

> constructor TImageListSpeedbutton.Create(AOwner: TComponent);


> begin
> inherited Create(AOwner);
> FChangeLink:=TChangeLink.Create;
> FChangeLink.OnChange:=ImageListChange;
> FImageIndex:=-1;

You are failing to create the imagelist here. You cannot simply hook an
external instance of an imagelist to the FImages field, the property editor for
imagelists *expects* the control to have its own internal instance of TImgelist
and the Set method for the property *must* use Assign to copy the imagelist
passed to it to the internal list.

> end;
>
> destructor TImageListSpeedbutton.Destroy;
> begin
> inherited Destroy;

You will need to destroy the internal imagelist here. You also should free the
TChangeLink, otherwise you have a memory leak, i think.

> procedure TImageListSpeedbutton.SetImageIndex(const Value:
> TImageIndex);
> begin
> FImageIndex:=Value;

Usually a set method will first check if the passed value is different than the
current value of the property. If not it can exit immediately.

> if (Value>=0) and Assigned(FImages) and (Value<FImages.Count) then
> FImages.GetBitmap(Value, Glyph)
> else
> Glyph.Assign(NIL);
> end;
>

> procedure TImageListSpeedbutton.SetImageList(const Value:
> TCustomImageList);
> begin
assert( assigned( Fimages ));
FImages.UnRegisterChanges(FChangeLink);
FImages.Assign( value );
FImages.RegisterChanges(FChangeLink);
> end;

Sebastian Modersohn (ChoosePill)

unread,
Oct 6, 2000, 3:00:00 AM10/6/00
to
> You are failing to create the imagelist here. You cannot simply hook an
> external instance of an imagelist to the FImages field, the property
editor for
> imagelists *expects* the control to have its own internal instance of
TImgelist
> and the Set method for the property *must* use Assign to copy the
imagelist
> passed to it to the internal list.
Excuse me for jumping in, but IMHO I don't think this is correct. (Sorry
found no honest way to say that)

I've written several components which are using ImageLists and they don't
have their own instance of TImageList which they copy by a call to Assign in
its Setter method. That would waste resources extremely. AFAIK you just have
to hold a reference to the ImageList, check in the overriden Notification
method if its removed, call RegisterFreeNotification and setup the
TChangeLink in the setter method. For the ImageIndex property editor to work
I had to write a descendant of TComponentImageIndexPropertyEditor with an
overriden GetImageListAt method and register that descendant as a property
editor. That's all to get it working.

Greetings

--
Sebastian Modersohn
ChoosePill components
www.choosepill.com


Peter Below (TeamB)

unread,
Oct 6, 2000, 3:00:00 AM10/6/00
to
In article <8rj6m0$8a...@bornews.borland.com>, Sebastian Modersohn
(ChoosePill) wrote:
> Excuse me for jumping in, but IMHO I don't think this is correct. (Sorry
> found no honest way to say that)
>

You may be correct here. I generalized from the behaviour of other
"object"-type properties without consulting the source (always an error, i
know <g>).

Roger Misteli

unread,
Oct 11, 2000, 3:00:00 AM10/11/00
to
Thanks to you both, Sebastian and Peter

> method if its removed, call RegisterFreeNotification and setup the

Overriding Notification is clear, but what the heck is
RegisterFreeNotification (same as FreeNotification?). I cannot find that
one in the help files.

> TChangeLink in the setter method.

Dumb question, but what exactly would you have to do in the ChangeLink?
If there is a change within the imagelist, the original picture is still
in the Glyph property currently. Or should I just update the image
according to the still existing (and same) imageindex?

> For the ImageIndex property editor to work
> I had to write a descendant of TComponentImageIndexPropertyEditor with an
> overriden GetImageListAt method and register that descendant as a property
> editor. That's all to get it working.

Ermm.. can you maybe give me a sample?

I think I can work with the rest (this component is more a playground
then a serious project, but I want to know how it works with the
imagelists etc).

Thanks for the help, its appreciated :-)
Rog

Sebastian Modersohn (ChoosePill)

unread,
Oct 24, 2000, 3:00:00 AM10/24/00
to
Hi Rog,

sorry for the late response, but I was on vacation...

> Dumb question, but what exactly would you have to do in the ChangeLink?

To have an event which informs you about changes in the ImageList (item
removed, order changed etc). If this occurs you should reload the image from
the ImageList in the Glyph.


> > For the ImageIndex property editor to work
> > I had to write a descendant of TComponentImageIndexPropertyEditor with
an
> > overriden GetImageListAt method and register that descendant as a
property
> > editor. That's all to get it working.
>
> Ermm.. can you maybe give me a sample?
>

See sources below. Of course this Editor has to be registered using
RegisterPropertyEditor.

TMyImageIndexPropertyEditor = class(TComponentImageIndexPropertyEditor)
protected
function GetImageListAt (Index: Integer): TCustomImageList; override;
end;

function TMyImageIndexPropertyEditor.GetImageListAt (Index: Integer):
TCustomImageList;
var
C: TPersistent;
begin
Result := nil;
C := GetComponent(Index);
if C is TMyComponent then
Result:=TMyComponent(C).Images;
end;

HTH

0 new messages