| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581 |
- unit PngImageList;
- {$IF RTLVersion < 15.0 }
- This unit only compiles with Delphi 7 and higher!
- {$IFEND}
- interface
- uses
- Windows, Classes, SysUtils, Controls, Graphics, ImgList,
- {$IF CompilerVersion >= 34.0 Delphi 10.4 }
- System.UITypes,
- {$ENDIF}
- PngImage, PngFunctions;
- type
- INameMapping = interface
- ['{38EECDD8-7440-4EA2-BFD0-424E5BB2C1D5}']
- function GetName(Index: Integer): string;
- function IndexOfName(const AName: string): Integer;
- procedure ListNames(Target: TStrings);
- property Name[Index: Integer]: string read GetName;
- end;
- type
- TPngImageCollection = class;
- TPngImageCollectionItem = class;
- TPngImageCollectionItems = class;
- TPngImageList = class(TImageList, INameMapping)
- function INameMapping.GetName = GetImageName;
- function INameMapping.IndexOfName = FindIndexByName;
- procedure INameMapping.ListNames = ListImageNames;
- private
- FEnabledImages: Boolean;
- FImageNameAvailable: Boolean;
- FLocked: Integer;
- FOverlayIndex: array[TOverlay] of Integer;
- FPngImages: TPngImageCollectionItems;
- FPngOptions: TPngOptions;
- function ExtractOverlayIndex(Style: Cardinal): Integer;
- function GetHeight: Integer;
- function GetImageName(Index: Integer): string;
- function GetWidth: Integer;
- procedure SetHeight(const Value: Integer);
- procedure SetPngOptions(const Value: TPngOptions);
- procedure SetWidth(const Value: Integer);
- protected
- procedure AssignTo(Dest: TPersistent); override;
- procedure CopyPngs; virtual;
- procedure DoDraw(Index: Integer; Canvas: TCanvas; X, Y: Integer; Style: Cardinal; Enabled: Boolean = True); override;
- procedure InternalInsertPng(Index: Integer; const Png: TPngImage; Background:
- TColor = clNone);
- procedure InternalAddPng(const Png: TPngImage; Background: TColor = clNone);
- function PngToIcon(const Png: TPngImage; Background: TColor = clNone): HICON;
- procedure ReadData(Stream: TStream); override;
- procedure SetEnabledImages(const Value: Boolean); virtual;
- procedure SetPngImages(const Value: TPngImageCollectionItems); virtual;
- procedure WriteData(Stream: TStream); override;
- public
- constructor Create(AOwner: TComponent); override;
- destructor Destroy; override;
- //Patched methods
- function Add(Image, Mask: TBitmap): Integer; virtual;
- function AddIcon(Image: TIcon): Integer; virtual;
- function AddPng(Image: TPngImage; Background: TColor = clNone): Integer;
- function AddImage(Value: TCustomImageList; Index: Integer): Integer; virtual;
- procedure AddImages(Value: TCustomImageList); virtual;
- function AddMasked(Image: TBitmap; MaskColor: TColor): Integer; virtual;
- {$IF CompilerVersion >= 34.0 Delphi 10.4 Sydney }
- function AddDisabledImage(Value: TCustomImageList; Index: Integer): Integer; virtual;
- procedure AddDisabledImages(Value: TCustomImageList); virtual;
- {$ENDIF}
- procedure Assign(Source: TPersistent); override;
- procedure BeginUpdate;
- procedure Clear; virtual;
- procedure Delete(Index: Integer); virtual;
- procedure EndUpdate(Update: Boolean = True);
- function FindIndexByName(const AName: string): Integer;
- procedure Insert(Index: Integer; Image, Mask: TBitmap); virtual;
- procedure InsertIcon(Index: Integer; Image: TIcon); virtual;
- procedure InsertPng(Index: Integer; Image: TPngImage; Background: TColor = clNone);
- procedure InsertMasked(Index: Integer; Image: TBitmap; MaskColor: TColor); virtual;
- procedure ListImageNames(Target: TStrings);
- procedure Move(CurIndex, NewIndex: Integer); virtual;
- function Overlay(ImageIndex: Integer; Overlay: TOverlay): Boolean;
- procedure Replace(Index: Integer; Image, Mask: TBitmap); virtual;
- procedure ReplaceIcon(Index: Integer; Image: TIcon); virtual;
- procedure ReplaceMasked(Index: Integer; NewImage: TBitmap; MaskColor: TColor); virtual;
- {$IF CompilerVersion >= 34.0 Delphi 10.4 }
- function IsImageNameAvailable: Boolean; override;
- function GetIndexByName(const AName: TImageName): TImageIndex; override;
- function GetNameByIndex(AIndex: TImageIndex): TImageName; override;
- {$ENDIF}
- property ImageName[Index: Integer]: string read GetImageName;
- published
- property ColorDepth default cd32Bit;
- property EnabledImages: Boolean read FEnabledImages write SetEnabledImages default True;
- property Height read GetHeight write SetHeight default 16;
- property ImageNameAvailable: Boolean read FImageNameAvailable write FImageNameAvailable default False;
- property PngImages: TPngImageCollectionItems read FPngImages write SetPngImages;
- property PngOptions: TPngOptions read FPngOptions write SetPngOptions default [pngBlendOnDisabled];
- property Width read GetWidth write SetWidth default 16;
- end;
- TPngImageCollection = class(TComponent)
- private
- FItems: TPngImageCollectionItems;
- public
- constructor Create(AOwner: TComponent); override;
- destructor Destroy; override;
- published
- property Items: TPngImageCollectionItems read FItems write FItems;
- end;
- TPngImageCollectionItems = class(TCollection)
- private
- FOwner: TPersistent;
- function GetItem(Index: Integer): TPngImageCollectionItem;
- procedure SetItem(Index: Integer; const Value: TPngImageCollectionItem);
- protected
- function GetOwner: TPersistent; override;
- procedure Update(Item: TCollectionItem); override;
- public
- constructor Create(AOwner: TPersistent);
- function Add(DontCreatePNG: Boolean = False): TPngImageCollectionItem; reintroduce;
- procedure Assign(Source: TPersistent); override;
- function Insert(Index: Integer; DontCreatePNG: Boolean = False): TPngImageCollectionItem; reintroduce;
- property Items[index: Integer]: TPngImageCollectionItem read GetItem write SetItem; default;
- end;
- TPngImageCollectionItem = class(TCollectionItem)
- private
- FBackground: TColor;
- FName: string;
- FPngImage: TPngImage;
- procedure SetBackground(const Value: TColor);
- procedure SetPngImage(const Value: TPngImage);
- protected
- procedure AssignTo(Dest: TPersistent); override;
- function GetDisplayName: string; override;
- public
- constructor Create(Collection: TCollection); overload; override;
- constructor Create(Collection: TCollection; DontCreatePNG: Boolean = False); reintroduce; overload;
- destructor Destroy; override;
- procedure Assign(Source: TPersistent); override;
- function Duplicate: TPngImage;
- published
- property Background: TColor read FBackground write SetBackground default clBtnFace;
- property Name: string read FName write FName;
- property PngImage: TPngImage read FPngImage write SetPngImage;
- end;
- procedure CopyImageFromImageList(Dest: TPngImage; ImageList: TCustomImageList; Index: Integer);
- implementation
- uses
- Math, Contnrs, CommCtrl, ComCtrls;
- var
- ImageListCount: Integer = 0;
- MethodPatches: TObjectList = nil;
- type
- TMethodPatch = class
- private
- Name: string;
- OldBody: packed array[0..4] of Byte;
- OldPointer: Pointer;
- NewPointer: Pointer;
- public
- constructor Create;
- destructor Destroy; override;
- procedure BeginInvokeOldMethod;
- procedure FinishInvokeOldMethod;
- function PatchBack: Boolean;
- end;
- { Global }
- function FindMethodPatch(const Name: string): TMethodPatch;
- var
- I: Integer;
- begin
- Result := nil;
- for I := 0 to MethodPatches.Count - 1 do begin
- if TMethodPatch(MethodPatches[I]).Name = Name then begin
- Result := TMethodPatch(MethodPatches[I]);
- Break;
- end;
- end;
- end;
- {$IF RTLVersion > 18.0 }
- {$POINTERMATH ON}
- {$IFEND}
- function PatchPtr(OldPtr, NewPtr: Pointer; const Name: string; Patch: TMethodPatch): Boolean;
- var
- Access: Cardinal;
- memSize: Integer;
- opCode: PByte;
- operand: PInteger;
- begin
- Result := False;
- Patch.Name := Name;
- if OldPtr <> NewPtr then begin
- Patch.OldPointer := OldPtr;
- Patch.NewPointer := NewPtr;
- opCode := OldPtr;
- operand := OldPtr;
- Inc(PByte(operand));
- memSize := SizeOf(Patch.OldBody);
- Move(opCode^, Patch.OldBody[0], memSize);
- if VirtualProtect(OldPtr, 16, PAGE_EXECUTE_READWRITE, @Access) then begin
- opCode^ := $E9; // Near jump
- {$IF RTLVersion > 18.0 }
- operand^ := PByte(NewPtr) - PByte(OldPtr) - 5;
- {$ELSE}
- operand^ := PChar(NewPtr) - PChar(OldPtr) - 5;
- {$IFEND}
- VirtualProtect(OldPtr, 16, Access, @Access);
- // {$IF not (defined(CPU386) or defined(CPUX86) or defined(CPUX64)) }
- // FlushInstructionCache(GetCurrentProcess, OldPtr, memSize);
- // {$IFEND}
- Result := True;
- end;
- end;
- if not Result then
- Patch.OldPointer := nil;
- end;
- {$IF RTLVersion > 18.0 }
- {$POINTERMATH OFF}
- {$IFEND}
- procedure ApplyMethodPatches;
- type
- TPointerCombo = record
- OldPtr: Pointer;
- NewPtr: Pointer;
- Name: string;
- end;
- function Combo(const OldPtr, NewPtr: Pointer; const Name: string): TPointerCombo;
- begin
- Result.OldPtr := OldPtr;
- Result.NewPtr := NewPtr;
- Result.Name := Name;
- end;
- const
- EmptyCombo: TPointerCombo = (OldPtr: nil; NewPtr: nil; Name: '');
- var
- Pointers: array of TPointerCombo;
- Patch: TMethodPatch;
- I: Integer;
- begin
- if ImageListCount = 0 then begin
- {$IF CompilerVersion >= 34.0 Delphi 10.4 Sydney }
- SetLength(Pointers, 17);
- {$ELSE}
- SetLength(Pointers, 15);
- {$ENDIF}
- Pointers[0] := Combo(@TCustomImageList.Add, @TPngImageList.Add, 'Add');
- Pointers[1] := Combo(@TCustomImageList.AddIcon, @TPngImageList.AddIcon, 'AddIcon');
- Pointers[2] := Combo(@TCustomImageList.AddImage, @TPngImageList.AddImage, 'AddImage');
- Pointers[3] := Combo(@TCustomImageList.AddImages, @TPngImageList.AddImages, 'AddImages');
- Pointers[4] := Combo(@TCustomImageList.AddMasked, @TPngImageList.AddMasked, 'AddMasked');
- Pointers[5] := Combo(@TCustomImageList.Clear, @TPngImageList.Clear, 'Clear');
- Pointers[6] := Combo(@TCustomImageList.Delete, @TPngImageList.Delete, 'Delete');
- Pointers[7] := Combo(@TCustomImageList.Insert, @TPngImageList.Insert, 'Insert');
- Pointers[8] := Combo(@TCustomImageList.InsertIcon, @TPngImageList.InsertIcon, 'InsertIcon');
- Pointers[9] := Combo(@TCustomImageList.InsertMasked, @TPngImageList.InsertMasked, 'InsertMasked');
- Pointers[10] := Combo(@TCustomImageList.Move, @TPngImageList.Move, 'Move');
- Pointers[11] := Combo(@TCustomImageList.Replace, @TPngImageList.Replace, 'Replace');
- Pointers[12] := Combo(@TCustomImageList.ReplaceIcon, @TPngImageList.ReplaceIcon, 'ReplaceIcon');
- Pointers[13] := Combo(@TCustomImageList.ReplaceMasked, @TPngImageList.ReplaceMasked, 'ReplaceMasked');
- Pointers[14] := Combo(@TCustomImageList.Overlay, @TPngImageList.Overlay, 'Overlay');
- {$IF CompilerVersion >= 34.0 Delphi 10.4 Sydney }
- Pointers[15] := Combo(@TCustomImageList.AddDisabledImage, @TPngImageList.AddDisabledImage, 'AddDisabledImage');
- Pointers[16] := Combo(@TCustomImageList.AddDisabledImages, @TPngImageList.AddDisabledImages, 'AddDisabledImages');
- {$ENDIF}
- MethodPatches := TObjectList.Create;
- for I := Low(Pointers) to High(Pointers) do begin
- if Pointers[I].OldPtr <> nil then begin
- Patch := TMethodPatch.Create;
- if PatchPtr(Pointers[I].OldPtr, Pointers[I].NewPtr, Pointers[I].Name, Patch) then
- begin
- MethodPatches.Add(Patch)
- end
- else
- begin
- Patch.Free;
- end;
- end;
- end;
- end;
- end;
- procedure RevertPatchedMethods;
- begin
- if ImageListCount = 0 then
- begin
- FreeAndNil(MethodPatches);
- end;
- end;
- procedure CopyImageFromImageList(Dest: TPngImage; ImageList: TCustomImageList; Index: Integer);
- var
- Icon: TIcon;
- IconInfo: TIconInfo;
- ColorBitmap, MaskBitmap: TBitmap;
- X, Y: Integer;
- AlphaLine: pngimage.PByteArray;
- Png: TPngImageCollectionItem;
- begin
- if ImageList is TPngImageList then begin
- //This is easy, just copy the PNG object from the imagelist to the PNG object
- //from the button
- Png := TPNGImageList(ImageList).PngImages[Index];
- if Png <> nil then
- Dest.Assign(Png.PngImage);
- end
- else begin
- Icon := TIcon.Create;
- ColorBitmap := TBitmap.Create;
- MaskBitmap := TBitmap.Create;
- try
- //Try to copy an icon to a PNG object, including transparency
- ImageList.GetIcon(Index, Icon);
- if GetIconInfo(Icon.Handle, IconInfo) then begin
- //First, pump the colors into the PNG object
- ColorBitmap.Handle := IconInfo.hbmColor;
- ColorBitmap.PixelFormat := pf24bit;
- Dest.Assign(ColorBitmap);
- //Finally, copy the transparency
- Dest.CreateAlpha;
- MaskBitmap.Handle := IconInfo.hbmMask;
- for Y := 0 to Dest.Height - 1 do begin
- AlphaLine := Dest.AlphaScanline[Y];
- for X := 0 to Dest.Width - 1 do
- AlphaLine^[X] := Integer(GetPixel(MaskBitmap.Canvas.Handle, X, Y) = COLORREF(clBlack)) * $FF;
- end;
- end;
- finally
- MaskBitmap.Free;
- ColorBitmap.Free;
- Icon.Free;
- end;
- end;
- end;
- { TMethodPatch }
- constructor TMethodPatch.Create;
- begin
- inherited Create;
- OldPointer := nil;
- end;
- destructor TMethodPatch.Destroy;
- begin
- if OldPointer <> nil then
- begin
- PatchBack;
- end;
- inherited Destroy;
- end;
- procedure TMethodPatch.BeginInvokeOldMethod;
- begin
- PatchBack;
- end;
- procedure TMethodPatch.FinishInvokeOldMethod;
- begin
- PatchPtr(OldPointer, NewPointer, Name, Self);
- end;
- function TMethodPatch.PatchBack: Boolean;
- var
- Access: Cardinal;
- begin
- Result := False;
- if VirtualProtect(OldPointer, 16, PAGE_EXECUTE_READWRITE, @Access) then begin
- Move(OldBody[0], OldPointer^, SizeOf(OldBody));
- VirtualProtect(OldPointer, 16, Access, @Access);
- Result := True;
- end;
- end;
- constructor TPngImageList.Create(AOwner: TComponent);
- var
- I: Integer;
- begin
- for I := Low(FOverlayIndex) to High(FOverlayIndex) do begin
- FOverlayIndex[I] := -1;
- end;
- inherited Create(AOwner);
- {$IF CompilerVersion >= 33.0 Delphi 10.3 Rio }
- StoreBitmap := False;
- {$ENDIF}
- FImageNameAvailable := False;
- ColorDepth := cd32Bit;
- if ImageListCount = 0 then
- ApplyMethodPatches;
- Inc(ImageListCount);
- FEnabledImages := True;
- FPngOptions := [pngBlendOnDisabled];
- FPngImages := TPngImageCollectionItems.Create(Self);
- FLocked := 0;
- end;
- destructor TPngImageList.Destroy;
- begin
- FPngImages.Free;
- Dec(ImageListCount);
- if ImageListCount = 0 then
- RevertPatchedMethods;
- inherited Destroy;
- end;
- //--- Patched methods ---
- function TPngImageList.Add(Image, Mask: TBitmap): Integer;
- var
- Patch: TMethodPatch;
- Png: TPngImage;
- begin
- if TObject(Self) is TPngImageList then begin
- Png := TPngImage.Create;
- try
- CreatePNG(Image, Mask, Png);
- result := AddPng(Png);
- finally
- Png.Free;
- end;
- end
- else begin
- Patch := FindMethodPatch('Add');
- if Patch <> nil then begin
- Patch.BeginInvokeOldMethod;
- try
- Result := TCustomImageList(Self).Add(Image, Mask);
- finally
- Patch.FinishInvokeOldMethod;
- end;
- end
- else
- Result := -1;
- end;
- end;
- function TPngImageList.AddIcon(Image: TIcon): Integer;
- var
- Patch: TMethodPatch;
- Png: TPngImage;
- begin
- if TObject(Self) is TPngImageList then begin
- Png := TPngImage.Create;
- try
- ConvertToPNG(Image, Png);
- result := AddPng(Png);
- finally
- Png.Free;
- end;
- end
- else begin
- Patch := FindMethodPatch('AddIcon');
- if Patch <> nil then begin
- Patch.BeginInvokeOldMethod;
- try
- Result := TCustomImageList(Self).AddIcon(Image);
- finally
- Patch.FinishInvokeOldMethod;
- end;
- end
- else
- Result := -1;
- end;
- end;
- function TPngImageList.AddPng(Image: TPngImage; Background: TColor = clNone):
- Integer;
- var
- Item: TPngImageCollectionItem;
- begin
- Result := -1;
- if Image = nil then Exit;
- BeginUpdate;
- try
- Item := FPngImages.Add(True);
- Item.PngImage := Image;
- Item.Background := Background;
- Result := Item.Index;
- InternalAddPng(Item.PngImage, Item.Background);
- Change;
- finally
- EndUpdate(false);
- end;
- end;
- function TPngImageList.AddImage(Value: TCustomImageList; Index: Integer): Integer;
- var
- Patch: TMethodPatch;
- Png: TPngImage;
- begin
- if TObject(Self) is TPngImageList then begin
- Png := TPngImage.Create;
- try
- CopyImageFromImageList(Png, Value, Index);
- if RTLVersion < 31.00 then begin
- result := AddPng(Png);
- end
- else begin
- { Since Berlin AddImage returns the new size of the list, while before it returned the index of the added image.
- Although this behaviour seems somewhat strange, it actually matches the documentation. }
- AddPng(Png);
- result := FPngImages.Count;
- end;
- finally
- Png.Free;
- end;
- end
- else begin
- Patch := FindMethodPatch('AddImage');
- if Patch <> nil then begin
- Patch.BeginInvokeOldMethod;
- try
- Result := TCustomImageList(Self).AddImage(Value, Index);
- finally
- Patch.FinishInvokeOldMethod;
- end;
- end
- else
- Result := -1;
- end;
- end;
- procedure TPngImageList.AddImages(Value: TCustomImageList);
- var
- Patch: TMethodPatch;
- I: Integer;
- Png: TPngImage;
- begin
- if TObject(Self) is TPngImageList then begin
- BeginUpdate;
- try
- //Copy every image from Value into this imagelist.
- Png := TPngImage.Create;
- try
- for I := 0 to Value.Count - 1 do begin
- CopyImageFromImageList(Png, Value, I);
- AddPng(Png);
- end;
- finally
- Png.Free;
- end;
- finally
- EndUpdate;
- end;
- end
- else begin
- Patch := FindMethodPatch('AddImages');
- if Patch <> nil then begin
- Patch.BeginInvokeOldMethod;
- try
- TCustomImageList(Self).AddImages(Value);
- finally
- Patch.FinishInvokeOldMethod;
- end;
- end;
- end;
- end;
- {$IF CompilerVersion >= 34.0 Delphi 10.4 Sydney }
- function TPngImageList.AddDisabledImage(Value: TCustomImageList; Index: Integer): Integer;
- var
- Patch: TMethodPatch;
- Png: TPngImage;
- begin
- if TObject(Self) is TPngImageList then begin
- Png := TPngImage.Create;
- try
- CopyImageFromImageList(Png, Value, Index);
- MakeDisabledImage(Png, PngOptions);
- AddPng(Png);
- result := FPngImages.Count;
- finally
- Png.Free;
- end;
- end
- else begin
- Patch := FindMethodPatch('AddDisabledImage');
- if Patch <> nil then begin
- Patch.BeginInvokeOldMethod;
- try
- Result := TCustomImageList(Self).AddDisabledImage(Value, Index);
- finally
- Patch.FinishInvokeOldMethod;
- end;
- end
- else
- Result := -1;
- end;
- end;
- procedure TPngImageList.AddDisabledImages(Value: TCustomImageList);
- var
- Patch: TMethodPatch;
- I: Integer;
- Png: TPngImage;
- begin
- if TObject(Self) is TPngImageList then begin
- BeginUpdate;
- try
- //Copy every image from Value into this imagelist.
- Png := TPngImage.Create;
- try
- for I := 0 to Value.Count - 1 do begin
- CopyImageFromImageList(Png, Value, I);
- MakeDisabledImage(Png, PngOptions);
- AddPng(Png);
- end;
- finally
- Png.Free;
- end;
- finally
- EndUpdate;
- end;
- end
- else begin
- Patch := FindMethodPatch('AddDisabledImages');
- if Patch <> nil then begin
- Patch.BeginInvokeOldMethod;
- try
- TCustomImageList(Self).AddDisabledImages(Value);
- finally
- Patch.FinishInvokeOldMethod;
- end;
- end;
- end;
- end;
- {$ENDIF}
- function TPngImageList.AddMasked(Image: TBitmap; MaskColor: TColor): Integer;
- var
- Patch: TMethodPatch;
- Png: TPngImage;
- begin
- if TObject(Self) is TPngImageList then begin
- Png := TPngImage.Create;
- try
- CreatePNGMasked(Image, MaskColor, Png);
- result := AddPng(Png);
- finally
- Png.Free;
- end;
- end
- else begin
- Patch := FindMethodPatch('AddMasked');
- if Patch <> nil then begin
- Patch.BeginInvokeOldMethod;
- try
- Result := TCustomImageList(Self).AddMasked(Image, MaskColor);
- finally
- Patch.FinishInvokeOldMethod;
- end;
- end
- else
- Result := -1;
- end;
- end;
- procedure TPngImageList.Assign(Source: TPersistent);
- var
- pngSource: TPngImageList;
- begin
- if Source is TPngImageList then begin
- pngSource := TPngImageList(Source);
- BeginUpdate;
- try
- PngImages := pngSource.PngImages;
- EnabledImages := pngSource.EnabledImages;
- PngOptions := pngSource.PngOptions;
- finally
- EndUpdate(true);
- end;
- end;
- if Source is TCustomImageList then begin
- ColorDepth := TCustomImageList(Source).ColorDepth;
- end;
- inherited;
- end;
- procedure TPngImageList.AssignTo(Dest: TPersistent);
- var
- pngDest: TPngImageList;
- begin
- inherited;
- if Dest is TPngImageList then begin
- pngDest := TPngImageList(Dest);
- pngDest.PngImages := PngImages;
- pngDest.EnabledImages := EnabledImages;
- pngDest.PngOptions := PngOptions;
- end;
- end;
- procedure TPngImageList.BeginUpdate;
- begin
- Inc(FLocked);
- end;
- procedure TPngImageList.Clear;
- var
- Patch: TMethodPatch;
- begin
- if TObject(Self) is TPngImageList then begin
- //Clear the PngImages collection and the internal imagelist.
- BeginUpdate;
- try
- FPngImages.Clear;
- ImageList_Remove(Handle, -1);
- Change;
- finally
- EndUpdate(False);
- end;
- end
- else begin
- Patch := FindMethodPatch('Clear');
- if Patch <> nil then begin
- Patch.BeginInvokeOldMethod;
- try
- TCustomImageList(Self).Clear;
- finally
- Patch.FinishInvokeOldMethod;
- end;
- end;
- end;
- end;
- procedure TPngImageList.CopyPngs;
- var
- I: Integer;
- Png: TPngImage;
- Icon: HIcon;
- item: TPngImageCollectionItem;
- begin
- //Are we adding a bunch of images?
- if FLocked > 0 then
- Exit;
- //Copy PNG images to the imagelist. These images will not be stored in the DFM.
- ImageList_Remove(Handle, -1);
- Handle := ImageList_Create(Width, Height, ILC_COLOR32 or (Integer(Masked) *
- ILC_MASK), 0, AllocBy);
- Png := TPngImage.Create;
- try
- for I := 0 to FPngImages.Count - 1 do begin
- item := FPngImages.Items[I];
- if (item.PngImage = nil) or item.PngImage.Empty then
- Continue;
- if FEnabledImages or (FPngOptions = []) then begin
- Icon := PngToIcon(item.PngImage, item.Background);
- end
- else begin
- //Basically the same as in the DrawPNG function
- Png.Assign(item.PngImage);
- MakeDisabledImage(Png, PngOptions);
- Icon := PngToIcon(Png);
- end;
- ImageList_AddIcon(Handle, Icon);
- DestroyIcon(Icon);
- end;
- finally
- Png.Free;
- end;
- end;
- procedure TPngImageList.Delete(Index: Integer);
- var
- Patch: TMethodPatch;
- begin
- if TObject(Self) is TPngImageList then begin
- //Delete an image from the PngImages collection and from the internal imagelist.
- if (Index >= 0) and (Index < Count) then begin
- BeginUpdate;
- try
- FPngImages.Delete(Index);
- ImageList_Remove(Handle, Index);
- Change;
- finally
- EndUpdate(False);
- end;
- end;
- end
- else begin
- Patch := FindMethodPatch('Delete');
- if Patch <> nil then begin
- Patch.BeginInvokeOldMethod;
- try
- TCustomImageList(Self).Delete(Index);
- finally
- Patch.FinishInvokeOldMethod;
- end;
- end;
- end;
- end;
- //--- End of patched methods ---
- procedure TPngImageList.DoDraw(Index: Integer; Canvas: TCanvas; X, Y: Integer; Style: Cardinal; Enabled: Boolean);
- var
- PaintRect: TRect;
- Options: TPngOptions;
- IndexOfOverlay: Integer;
- Png: TPngImageCollectionItem;
- begin
- //Draw a PNG directly to the Canvas. This is the preferred method to call,
- //because this omits the API calls that use a fixed background.
- PaintRect := Bounds(X, Y, Width, Height);
- if Enabled then
- Options := []
- else
- Options := FPngOptions;
- Png := FPngImages.Items[Index];
- if Png <> nil then begin
- DrawPNG(Png.PngImage, Canvas, PaintRect, Options);
- IndexOfOverlay := ExtractOverlayIndex(Style);
- if (IndexOfOverlay >= 0) and (IndexOfOverlay < Count) then begin
- Png := PngImages.Items[IndexOfOverlay];
- if Png <> nil then begin
- DrawPNG(Png.PngImage, Canvas, PaintRect, Options);
- end;
- end;
- end;
- end;
- procedure TPngImageList.EndUpdate(Update: Boolean);
- begin
- Dec(FLocked);
- if Update and (FLocked = 0) then
- CopyPngs;
- end;
- function TPngImageList.ExtractOverlayIndex(Style: Cardinal): Integer;
- var
- idx: Cardinal;
- begin
- Result := -1;
- idx := Style and ILD_OVERLAYMASK;
- if idx > 0 then begin
- idx := idx shr 8;
- if (idx > 0) then begin
- Dec(idx);
- {$WARN COMPARISON_TRUE OFF }
- if (idx >= Low(FOverlayIndex)) and (idx <= High(FOverlayIndex)) then begin
- Result := FOverlayIndex[idx];
- end;
- {$WARN COMPARISON_TRUE DEFAULT }
- end;
- end;
- end;
- function TPngImageList.FindIndexByName(const AName: string): Integer;
- var
- I: Integer;
- begin
- Result := -1;
- for I := 0 to PngImages.Count - 1 do begin
- if SameText(PngImages[I].Name, AName) then begin
- Result := I;
- Break;
- end;
- end;
- end;
- function TPngImageList.GetHeight: Integer;
- begin
- Result := inherited Height;
- end;
- function TPngImageList.GetImageName(Index: Integer): string;
- var
- item: TPngImageCollectionItem;
- begin
- Result := '';
- item := PngImages[Index];
- if item <> nil then
- Result := item.Name;
- end;
- {$IF CompilerVersion >= 34.0 Delphi 10.4 }
- function TPngImageList.IsImageNameAvailable: Boolean;
- begin
- Result := FImageNameAvailable;
- end;
- function TPngImageList.GetIndexByName(const AName: TImageName): TImageIndex;
- begin
- Result := FindIndexByName(AName);
- end;
- function TPngImageList.GetNameByIndex(AIndex: TImageIndex): TImageName;
- begin
- Result := ImageName[AIndex];
- end;
- {$ENDIF}
- function TPngImageList.GetWidth: Integer;
- begin
- Result := inherited Width;
- end;
- procedure TPngImageList.Insert(Index: Integer; Image, Mask: TBitmap);
- var
- Patch: TMethodPatch;
- Png: TPngImage;
- begin
- if TObject(Self) is TPngImageList then begin
- //Insert a new PNG based on the image and its mask.
- if Image <> nil then begin
- Png := TPngImage.Create;
- try
- CreatePNG(Image, Mask, Png);
- InsertPng(Index, Png);
- finally
- Png.Free;
- end;
- end;
- end
- else begin
- Patch := FindMethodPatch('Insert');
- if Patch <> nil then begin
- Patch.BeginInvokeOldMethod;
- try
- TCustomImageList(Self).Insert(Index, Image, Mask);
- finally
- Patch.FinishInvokeOldMethod;
- end;
- end;
- end;
- end;
- procedure TPngImageList.InsertIcon(Index: Integer; Image: TIcon);
- var
- Patch: TMethodPatch;
- Png: TPngImage;
- begin
- if TObject(Self) is TPngImageList then begin
- //Insert a new PNG based on the image.
- if Image <> nil then begin
- Png := TPngImage.Create;
- try
- ConvertToPNG(Image, Png);
- InsertPng(Index, Png);
- finally
- Png.Free;
- end;
- end;
- end
- else begin
- Patch := FindMethodPatch('InsertIcon');
- if Patch <> nil then begin
- Patch.BeginInvokeOldMethod;
- try
- TCustomImageList(Self).InsertIcon(Index, Image);
- finally
- Patch.FinishInvokeOldMethod;
- end;
- end;
- end;
- end;
- procedure TPngImageList.InsertPng(Index: Integer; Image: TPngImage; Background:
- TColor = clNone);
- var
- Item: TPngImageCollectionItem;
- begin
- if Image <> nil then begin
- BeginUpdate;
- try
- Item := PngImages.Insert(Index, True);
- Item.PngImage := Image;
- Item.Background := Background;
- InternalInsertPng(Index, Item.PngImage, Item.Background);
- Change;
- finally
- EndUpdate(False);
- end;
- end;
- end;
- procedure TPngImageList.InsertMasked(Index: Integer; Image: TBitmap; MaskColor: TColor);
- var
- Patch: TMethodPatch;
- Png: TPngImage;
- begin
- if TObject(Self) is TPngImageList then begin
- //Insert a new PNG based on the image and a colored mask.
- if Image <> nil then begin
- Png := TPngImage.Create;
- try
- CreatePNGMasked(Image, MaskColor, Png);
- InsertPng(Index, Png);
- finally
- Png.Free;
- end;
- end;
- end
- else begin
- Patch := FindMethodPatch('InsertMasked');
- if Patch <> nil then begin
- Patch.BeginInvokeOldMethod;
- try
- TCustomImageList(Self).InsertMasked(Index, Image, MaskColor);
- finally
- Patch.FinishInvokeOldMethod;
- end;
- end;
- end;
- end;
- procedure TPngImageList.InternalInsertPng(Index: Integer; const Png: TPngImage;
- Background: TColor);
- var
- I: Integer;
- Icon: HICON;
- TempList: TPngImageList;
- begin
- TempList := TPngImageList(TComponentClass(ClassType).Create(nil));
- try
- TempList.Assign(Self);
- ImageList_RemoveAll(Handle);
- for I := 0 to Index - 1 do begin
- Icon := ImageList_GetIcon(TempList.Handle, I, ILD_NORMAL);
- ImageList_AddIcon(Handle, Icon);
- DestroyIcon(Icon);
- end;
- Icon := PngToIcon(Png, Background);
- ImageList_AddIcon(Handle, Icon);
- DestroyIcon(Icon);
- for I := Index to TempList.Count - 1 do begin
- Icon := ImageList_GetIcon(TempList.Handle, I, ILD_NORMAL);
- ImageList_AddIcon(Handle, Icon);
- DestroyIcon(Icon);
- end;
- finally
- TempList.Free;
- end;
- end;
- procedure TPngImageList.InternalAddPng(const Png: TPngImage; Background: TColor
- = clNone);
- var
- Icon: HICON;
- begin
- Icon := PngToIcon(Png, Background);
- try
- ImageList_AddIcon(Handle, Icon);
- finally
- DestroyIcon(Icon);
- end;
- end;
- procedure TPngImageList.ListImageNames(Target: TStrings);
- var
- I: Integer;
- begin
- for I := 0 to PngImages.Count - 1 do begin
- Target.Add(PngImages[I].Name);
- end;
- end;
- procedure TPngImageList.Move(CurIndex, NewIndex: Integer);
- var
- Patch: TMethodPatch;
- begin
- if TObject(Self) is TPngImageList then begin
- //Move an image from one position to another. Don't try doing so in the internal
- //imagelist, just recreate it, since this method won't be called very often.
- BeginUpdate;
- try
- ImageList_Remove(Handle, CurIndex);
- InternalInsertPng(NewIndex, FPngImages[CurIndex].PngImage,
- FPngImages[CurIndex].Background);
- FPngImages[CurIndex].Index := NewIndex;
- Change;
- finally
- EndUpdate(False);
- end;
- end
- else begin
- Patch := FindMethodPatch('Move');
- if Patch <> nil then begin
- Patch.BeginInvokeOldMethod;
- try
- TCustomImageList(Self).Move(CurIndex, NewIndex);
- finally
- Patch.FinishInvokeOldMethod;
- end;
- end;
- end;
- end;
- function TPngImageList.Overlay(ImageIndex: Integer; Overlay: TOverlay): Boolean;
- begin
- Result := (ImageIndex >= 0) and (ImageIndex < Count);
- FOverlayIndex[Overlay] := ImageIndex;
- end;
- function TPngImageList.PngToIcon(const Png: TPngImage; Background: TColor): HICON;
- const
- MaxRGBQuads = MaxInt div SizeOf(TRGBQuad) - 1;
- type
- TRGBQuadArray = array[0..MaxRGBQuads] of TRGBQuad;
- PRGBQuadArray = ^TRGBQuadArray;
- TBitmapInfo4 = packed record
- bmiHeader: TBitmapV4Header;
- bmiColors: array[0..0] of TRGBQuad;
- end;
- function PngToIcon32(Png: TPngImage): HIcon;
- var
- ImageBits: PRGBQuadArray;
- BitmapInfo: TBitmapInfo4;
- IconInfo: TIconInfo;
- AlphaBitmap: HBitmap;
- MaskBitmap: TBitmap;
- X, Y: Integer;
- AlphaLine: PByteArray;
- HasAlpha, HasBitmask: Boolean;
- Color, TransparencyColor: TColor;
- begin
- //Convert a PNG object to an alpha-blended icon resource
- ImageBits := nil;
- //Allocate a DIB for the color data and alpha channel
- with BitmapInfo.bmiHeader do begin
- bV4Size := SizeOf(BitmapInfo.bmiHeader);
- bV4Width := Png.Width;
- bV4Height := Png.Height;
- bV4Planes := 1;
- bV4BitCount := 32;
- bV4V4Compression := BI_BITFIELDS;
- bV4SizeImage := 0;
- bV4XPelsPerMeter := 0;
- bV4YPelsPerMeter := 0;
- bV4ClrUsed := 0;
- bV4ClrImportant := 0;
- bV4RedMask := $00FF0000;
- bV4GreenMask := $0000FF00;
- bV4BlueMask := $000000FF;
- bV4AlphaMask := $FF000000;
- end;
- AlphaBitmap := CreateDIBSection(0, PBitmapInfo(@BitmapInfo)^,
- DIB_RGB_COLORS, Pointer(ImageBits), 0, 0);
- try
- //Spin through and fill it with a wash of color and alpha.
- AlphaLine := nil;
- HasAlpha := Png.Header.ColorType in [COLOR_GRAYSCALEALPHA,
- COLOR_RGBALPHA];
- HasBitmask := Png.TransparencyMode = ptmBit;
- TransparencyColor := Png.TransparentColor;
- for Y := 0 to Png.Height - 1 do begin
- if HasAlpha then
- AlphaLine := Png.AlphaScanline[Png.Height - Y - 1];
- for X := 0 to Png.Width - 1 do begin
- Color := Png.Pixels[X, Png.Height - Y - 1];
- ImageBits^[Y * Png.Width + X].rgbRed := Color and $FF;
- ImageBits^[Y * Png.Width + X].rgbGreen := Color shr 8 and $FF;
- ImageBits^[Y * Png.Width + X].rgbBlue := Color shr 16 and $FF;
- if HasAlpha then
- ImageBits^[Y * Png.Width + X].rgbReserved := AlphaLine^[X]
- else if HasBitmask then
- ImageBits^[Y * Png.Width + X].rgbReserved := Integer(Color <>
- TransparencyColor) * 255;
- end;
- end;
- //Create an empty mask
- MaskBitmap := TBitmap.Create;
- try
- MaskBitmap.Width := Png.Width;
- MaskBitmap.Height := Png.Height;
- MaskBitmap.PixelFormat := pf1bit;
- MaskBitmap.Canvas.Brush.Color := clBlack;
- MaskBitmap.Canvas.FillRect(Rect(0, 0, MaskBitmap.Width,
- MaskBitmap.Height));
- //Create the alpha blended icon
- IconInfo.fIcon := True;
- IconInfo.hbmColor := AlphaBitmap;
- IconInfo.hbmMask := MaskBitmap.Handle;
- Result := CreateIconIndirect(IconInfo);
- finally
- MaskBitmap.Free;
- end;
- finally
- DeleteObject(AlphaBitmap);
- end;
- end;
- function PngToIcon24(Png: TPngImage; Background: TColor): HIcon;
- var
- ColorBitmap, MaskBitmap: TBitmap;
- X, Y: Integer;
- AlphaLine: PByteArray;
- IconInfo: TIconInfo;
- TransparencyColor: TColor;
- begin
- ColorBitmap := TBitmap.Create;
- MaskBitmap := TBitmap.Create;
- try
- ColorBitmap.Width := Png.Width;
- ColorBitmap.Height := Png.Height;
- ColorBitmap.PixelFormat := pf32bit;
- MaskBitmap.Width := Png.Width;
- MaskBitmap.Height := Png.Height;
- MaskBitmap.PixelFormat := pf32bit;
- //Draw the color bitmap
- ColorBitmap.Canvas.Brush.Color := Background;
- ColorBitmap.Canvas.FillRect(Rect(0, 0, Png.Width, Png.Height));
- Png.Draw(ColorBitmap.Canvas, Rect(0, 0, Png.Width, Png.Height));
- //Create the mask bitmap
- if Png.Header.ColorType in [COLOR_GRAYSCALEALPHA, COLOR_RGBALPHA] then
- for Y := 0 to Png.Height - 1 do begin
- AlphaLine := Png.AlphaScanline[Y];
- for X := 0 to Png.Width - 1 do
- if AlphaLine^[X] = 0 then
- SetPixelV(MaskBitmap.Canvas.Handle, X, Y, clWhite)
- else
- SetPixelV(MaskBitmap.Canvas.Handle, X, Y, clBlack);
- end
- else if Png.TransparencyMode = ptmBit then begin
- TransparencyColor := Png.TransparentColor;
- for Y := 0 to Png.Height - 1 do
- for X := 0 to Png.Width - 1 do
- if Png.Pixels[X, Y] = TransparencyColor then
- SetPixelV(MaskBitmap.Canvas.Handle, X, Y, clWhite)
- else
- SetPixelV(MaskBitmap.Canvas.Handle, X, Y, clBlack);
- end;
- //Create the icon
- IconInfo.fIcon := True;
- IconInfo.hbmColor := ColorBitmap.Handle;
- IconInfo.hbmMask := MaskBitmap.Handle;
- Result := CreateIconIndirect(IconInfo);
- finally
- ColorBitmap.Free;
- MaskBitmap.Free;
- end;
- end;
- begin
- if GetComCtlVersion >= ComCtlVersionIE6 then begin
- //Windows XP or later, using the modern method: convert every PNG to
- //an icon resource with alpha channel
- Result := PngToIcon32(Png);
- end
- else begin
- //No Windows XP, using the legacy method: copy every PNG to a normal
- //bitmap using a fixed background color
- Result := PngToIcon24(Png, Background);
- end;
- end;
- procedure TPngImageList.ReadData(Stream: TStream);
- begin
- if not (csReading in ComponentState) then
- inherited;
- //Make sure nothing gets read from the DFM
- end;
- procedure TPngImageList.Replace(Index: Integer; Image, Mask: TBitmap);
- var
- Item: TPngImageCollectionItem;
- Patch: TMethodPatch;
- Icon: HICON;
- begin
- if TObject(Self) is TPngImageList then begin
- //Replace an existing PNG based with a new image and its mask.
- if Image <> nil then begin
- BeginUpdate;
- try
- Item := FPngImages[Index];
- CreatePNG(Image, Mask, Item.PngImage);
- Icon := PngToIcon(Item.PngImage, Item.Background);
- ImageList_ReplaceIcon(Handle, Index, Icon);
- DestroyIcon(Icon);
- Change;
- finally
- EndUpdate(False);
- end;
- end;
- end
- else begin
- Patch := FindMethodPatch('Replace');
- if Patch <> nil then begin
- Patch.BeginInvokeOldMethod;
- try
- TCustomImageList(Self).Replace(Index, Image, Mask);
- finally
- Patch.FinishInvokeOldMethod;
- end;
- end;
- end;
- end;
- procedure TPngImageList.ReplaceIcon(Index: Integer; Image: TIcon);
- var
- Item: TPngImageCollectionItem;
- Patch: TMethodPatch;
- Icon: HICON;
- begin
- if TObject(Self) is TPngImageList then begin
- //Replace an existing PNG based with a new image.
- if Image <> nil then begin
- BeginUpdate;
- try
- Item := FPngImages[Index];
- ConvertToPNG(Image, Item.PngImage);
- Icon := PngToIcon(Item.PngImage, Item.Background);
- ImageList_ReplaceIcon(Handle, Index, Icon);
- DestroyIcon(Icon);
- Change;
- finally
- EndUpdate(False);
- end;
- end
- end
- else begin
- Patch := FindMethodPatch('ReplaceIcon');
- if Patch <> nil then begin
- Patch.BeginInvokeOldMethod;
- try
- TCustomImageList(Self).ReplaceIcon(Index, Image);
- finally
- Patch.FinishInvokeOldMethod;
- end;
- end;
- end;
- end;
- procedure TPngImageList.ReplaceMasked(Index: Integer; NewImage: TBitmap; MaskColor: TColor);
- var
- Item: TPngImageCollectionItem;
- Patch: TMethodPatch;
- Icon: HICON;
- begin
- if TObject(Self) is TPngImageList then begin
- //Replace an existing PNG based with a new image and a colored mask.
- if NewImage <> nil then begin
- BeginUpdate;
- try
- Item := FPngImages[Index];
- CreatePNGMasked(NewImage, MaskColor, Item.PngImage);
- Icon := PngToIcon(Item.PngImage, Item.Background);
- ImageList_ReplaceIcon(Handle, Index, Icon);
- DestroyIcon(Icon);
- Change;
- finally
- EndUpdate(False);
- end;
- end
- end
- else begin
- Patch := FindMethodPatch('ReplaceMasked');
- if Patch <> nil then begin
- Patch.BeginInvokeOldMethod;
- try
- TCustomImageList(Self).ReplaceMasked(Index, NewImage, MaskColor);
- finally
- Patch.FinishInvokeOldMethod;
- end;
- end;
- end;
- end;
- procedure TPngImageList.SetEnabledImages(const Value: Boolean);
- begin
- if FEnabledImages xor Value then begin
- FEnabledImages := Value;
- CopyPngs;
- end;
- end;
- procedure TPngImageList.SetHeight(const Value: Integer);
- begin
- if inherited Height <> Value then begin
- inherited Height := Value;
- Clear;
- end;
- end;
- procedure TPngImageList.SetPngImages(const Value: TPngImageCollectionItems);
- begin
- if FPngImages <> Value then begin
- FPngImages.Assign(Value);
- Change;
- end;
- end;
- procedure TPngImageList.SetPngOptions(const Value: TPngOptions);
- begin
- if FPngOptions <> Value then begin
- FPngOptions := Value;
- CopyPngs;
- end;
- end;
- procedure TPngImageList.SetWidth(const Value: Integer);
- begin
- if inherited Width <> Value then begin
- inherited Width := Value;
- Clear;
- end;
- end;
- procedure TPngImageList.WriteData(Stream: TStream);
- begin
- if not (csWriting in ComponentState) then
- inherited;
- //Make sure nothing gets written to the DFM
- end;
- { TPngImageCollection }
- constructor TPngImageCollection.Create(AOwner: TComponent);
- begin
- inherited Create(AOwner);
- FItems := TPngImageCollectionItems.Create(Self);
- end;
- destructor TPngImageCollection.Destroy;
- begin
- FItems.Free;
- inherited Destroy;
- end;
- { TPngImageCollectionItems }
- constructor TPngImageCollectionItems.Create(AOwner: TPersistent);
- begin
- inherited Create(TPngImageCollectionItem);
- FOwner := AOwner;
- end;
- function TPngImageCollectionItems.Add(DontCreatePNG: Boolean = False): TPngImageCollectionItem;
- begin
- {$WARN SYMBOL_DEPRECATED OFF}
- Result := TPngImageCollectionItem.Create(Self, DontCreatePNG);
- Added(TCollectionItem(Result));
- end;
- procedure TPngImageCollectionItems.Assign(Source: TPersistent);
- begin
- inherited Assign(Source);
- Update(nil);
- end;
- function TPngImageCollectionItems.GetItem(Index: Integer): TPngImageCollectionItem;
- begin
- if (Index >= 0) and (Index < Count) then
- Result := TPngImageCollectionItem(inherited Items[Index])
- else
- Result := nil;
- end;
- function TPngImageCollectionItems.GetOwner: TPersistent;
- begin
- Result := FOwner;
- end;
- function TPngImageCollectionItems.Insert(Index: Integer; DontCreatePNG: Boolean = False): TPngImageCollectionItem;
- begin
- Result := Add(DontCreatePNG);
- Result.Index := Index;
- end;
- procedure TPngImageCollectionItems.SetItem(Index: Integer; const Value: TPngImageCollectionItem);
- begin
- if (Index >= 0) and (Index < Count) then
- inherited Items[Index] := Value;
- end;
- procedure TPngImageCollectionItems.Update(Item: TCollectionItem);
- begin
- inherited Update(Item);
- if FOwner is TPngImageList then
- TPngImageList(FOwner).CopyPngs;
- end;
- constructor TPngImageCollectionItem.Create(Collection: TCollection);
- begin
- inherited Create(Collection);
- FPngImage := TPngImage.Create;
- FName := Format('PngImage%d', [Index]);
- FBackground := clBtnFace;
- end;
- constructor TPngImageCollectionItem.Create(Collection: TCollection; DontCreatePNG: Boolean = False);
- begin
- inherited Create(Collection);
- if DontCreatePng then
- FPngImage := nil
- else
- FPngImage := TPngImage.Create;
- FName := Format('PngImage%d', [Index]);
- FBackground := clBtnFace;
- end;
- destructor TPngImageCollectionItem.Destroy;
- begin
- FPngImage.Free;
- inherited Destroy;
- end;
- procedure TPngImageCollectionItem.Assign(Source: TPersistent);
- begin
- if Source is TPngImageCollectionItem then begin
- PngImage.Assign(TPngImageCollectionItem(Source).PngImage);
- Background := TPngImageCollectionItem(Source).Background;
- Name := TPngImageCollectionItem(Source).Name;
- end
- else
- inherited Assign(Source);
- end;
- { TPngImageCollectionItem }
- procedure TPngImageCollectionItem.AssignTo(Dest: TPersistent);
- begin
- inherited AssignTo(Dest);
- if (Dest is TPngImageCollectionItem) then
- TPngImageCollectionItem(Dest).PngImage := PngImage;
- end;
- function TPngImageCollectionItem.Duplicate: TPngImage;
- begin
- Result := TPngImage.Create;
- Result.Assign(FPngImage);
- end;
- function TPngImageCollectionItem.GetDisplayName: string;
- begin
- if Length(FName) = 0 then
- Result := inherited GetDisplayName
- else
- Result := FName;
- end;
- procedure TPngImageCollectionItem.SetBackground(const Value: TColor);
- begin
- if FBackground <> Value then begin
- FBackground := Value;
- Changed(False);
- end;
- end;
- procedure TPngImageCollectionItem.SetPngImage(const Value: TPngImage);
- begin
- if FPngImage = nil then
- FPngImage := TPngImage.Create;
- FPngImage.Assign(Value);
- Changed(False);
- end;
- initialization
- finalization
- MethodPatches.Free;
- end.
|