The TImageListEx Component

The TImageListEx component is a TImageList descendant that can use the images from another image list to generate disabled images, which can be used on toolbars and other user interface elements.

There are several benefits of the TImageListEx component:

  • It eliminates the need for creating disabled glyphs.

  • It eliminates the need for adding the disabled glyphs to an additional TImageList component at design time.

  • It can drastically reduce the size of the .dfm file and of the entire application, especially in large applications that use a lot of glyphs.

  • It's extremely fast, taking only milliseconds to disable all images in an image list, even when there are number of images.

  • It's extremely lightweight. (If you add it to an application that already uses the standard TImageList component, it won't increase the size of the executable at all, and if you add it to an application that doesn't use the standard TImageList component, the overhead is only 2 KB.)

To create the TImageListEx component, you have to derive it from the standard TImageList component and then create the DisableImage function for disabling an image and the AcquireDisabled procedure that uses the DisableImage function to disable all images from another image list.

The DisableImage function is not really complex. It first determines the "transparent" color by extracting the bottom-right pixel of the source image. Then it uses the "transparent" pixel to determine which pixels should be converted to grayscale and which should be copied. All pixels that match the "transparent" pixel are directly copied to the destination bitmap and all other pixels are first converted to grayscale and then copied to the destination image. Finally, it returns the "transparent" pixel as Result because we have to pass this value to the AddMasked method of TImageList component when adding images to the image list.

The following listing shows the entire DisableImage function.

Listing 28-4: Disabling an image

image from book
type   TImageListEx = class(TImageList)   private     { Private declarations }   protected     { Protected declarations }     function DisableImage(Source, Dest: TBitmap): TColor;   end; ... function TImageListEx.DisableImage(Source, Dest: TBitmap): TColor; type   TMyPixel = record     Blue: Byte;     Green: Byte;     Red: Byte;   end;   PMyPixelArray = ^TMyPixelArray;   TMyPixelArray = array[0..32767] of TMyPixel; var   pSrc: PMyPixelArray;   pDest: PMyPixelArray;   x: Integer;   y: Integer;   gray: Integer;   { these will hold the transparent color }   tr: Integer;   tg: Integer;   tb: Integer; begin   { first, make sure both are pf24bit }   Source.PixelFormat := pf24bit;   Dest.PixelFormat := pf24bit;   { pixel at [W-1,H-1] in the Source is treated as "transparent" }   pSrc := Source.ScanLine[Pred(Source.Height)];   with pSrc[Pred(Source.Width)] do   begin     tr := Red;     tg := Green;     tb := Blue;   end;   for y := 0 to Pred(Source.Height) do   begin     pSrc := Source.ScanLine[y];     pDest := Dest.ScanLine[y];     for x := 0 to Pred(Source.Width) do     begin       { if px <> transparent then grayscale it }       if (pSrc[x].Red <> tr) or (pSrc[x].Green <> tg) or          (pSrc[x].Blue <> tb) then       begin         gray := (pSrc[x].Red * 3 +           pSrc[x].Blue * 4 +  pSrc[x].Green * 2) div 9;         pDest[x].Red := gray;         pDest[x].Green := gray;         pDest[x].Blue := gray;       end else       begin         { if transparent then copy it }         pDest[x].Red := pSrc[x].Red;         pDest[x].Green := pSrc[x].Green;         pDest[x].Blue := pSrc[x].Blue;       end; // if pSrc     end;      // for x   end;        // for y   { return the color used as transparent; we need to pass this     to the AddMasked method when adding images to the image list }   Result := RGB(tr, tg, tb); end;
image from book

The AcquireDisabled procedure accepts a source TCustomImageList object as the sole parameter and simply loops through its images, converting them to grayscale using the DisableImage function we created above.

To access a particular bitmap in a TImageList, you have to call the GetBitmap method, which accepts the image's index and a TBitmap where the GetBitmap method will store the requested image:

function GetBitmap(Index: Integer; Image: TBitmap): Boolean;

Finally, after you've acquired the original glyph from the source list and converted it to grayscale using the DisableImage function, you have to call the TImageList's AddMasked method to add the new glyph to the list. When calling the AddMasked method, you have to pass the glyph's transparent color as the MaskColor parameter to have the TImageList component generate the glyph's mask, which is used to draw the glyph transparently.

The following listing shows the AcquireDisabled procedure.

Listing 28-5: The AcquireDisabled procedure

image from book
procedure TImageListEx.AcquireDisabled(AList: TCustomImageList); var   cnt: Integer;   newImage: TBitmap;   tempSource: TBitmap;   transparent: TColor; begin   { use AList's image size }   Width := AList.Width;   Height := AList.Height;   { make sure there are no old images in the list }   Clear;   tempSource := TBitmap.Create;   try     newImage := TBitmap.Create;     try       for cnt := 0 to Pred(AList.Count) do       begin         { erase the old images because the GetBitmap method doesn't }         tempSource.Assign(nil);         newImage.Assign(nil);         { resize the new image }         newImage.Width := Width;         newImage.Height := Height;         { get image from the source image list }         AList.GetBitmap(cnt, tempSource);         { generate the new image }         transparent := DisableImage(tempSource, newImage);         { add the new image to the list }         AddMasked(newImage, transparent);       end;     finally       newImage.Free;     end;   finally     tempSource.Free;   end; end;
image from book

Using the TImageListEx Component

To use the TImageListEx component in an application, you have to do three things:

  • Remove an existing TImageList component that contains disabled glyphs.

  • Add the TImageListEx component to the Designer Surface and assign it to the appropriate Disabled properties of the components that used the original TImageList component.

  • Call the TImageListEx component's AcquireDisabled method in the main form's OnCreate event handler and pass the TImageList that contains normal glyphs to create appropriate disabled glyphs.

For instance, you can use the Delphi Text Editor example that we created earlier to test this component. First, remove the original disabled TImageList component and drop a TImageListEx component on the Designer Surface. Then, assign the TImageListEx component to the DisabledImages property of the main toolbar and write the following line in the OnCreate event handler of the main form:

procedure TMainForm.FormCreate(Sender: TObject); begin   ImageListEx1.AcquireDisabled(Normal); end; 

The TImageListEx will correctly create all disabled glyphs, except for the Delete button. The original Delete glyph cannot be successfully converted because this glyph, unlike almost all other GlyFX glyphs, treats the bottom-right pixel as a part of the image instead of as the "transparent" pixel. The following figure shows the original (erroneous) glyph and the updated glyph that can be successfully converted to grayscale by the TImageListEx component.

image from book
Figure 28-6: The troublesome Delete glyph

The toolbar in the following figure shows what the disabled glyphs generated by the TImageListEx component look like.

image from book
Figure 28-7: The final version of the Delphi Text Editor that uses the TImageListEx component

Finally, Figure 28-8 shows the impact of the TImageListEx component on the size of the Delphi Text Editor's executable. Although the Delphi Text Editor only had 10 disabled glyphs, the TImageListEx component managed to reduce the size of the executable by 17,408 bytes (17 KB).

image from book
Figure 28-8: The difference in the size of the executable after using the TImageListEx component

Inside Delphi 2006
Inside Delphi 2006 (Wordware Delphi Developers Library)
ISBN: 1598220039
EAN: 2147483647
Year: 2004
Pages: 212
Authors: Ivan Hladni

Similar book on Amazon © 2008-2017.
If you may any questions please contact us: