From b22caceecef5c875cb514ed2ddbe0eb19442c165 Mon Sep 17 00:00:00 2001 From: david Date: Sun, 1 Mar 2009 18:53:09 +0000 Subject: [PATCH] git-svn-id: https://192.168.0.254/svn/Componentes.Terceros.PNGComponents@16 a60baaea-e768-c94d-9a73-13206b75eb30 --- .../1.2.0/1/Design/PngComponentEditors.pas | 223 +++ internal/1.2.0/1/Design/PngComponents.dcr | Bin 0 -> 2292 bytes .../1.2.0/1/Design/PngComponentsRegister.pas | 41 + .../1.2.0/1/Design/PngImageListEditor.dfm | 574 ++++++++ .../1.2.0/1/Design/PngImageListEditor.pas | 1216 ++++++++++++++++ internal/1.2.0/1/Docs/Changelog.txt | 45 + internal/1.2.0/1/Docs/License.txt | 73 + internal/1.2.0/1/Docs/PngComponents.html | 105 ++ internal/1.2.0/1/Docs/pngimage.chm | Bin 0 -> 162254 bytes .../1.2.0/1/Example Images/Computer_32.png | Bin 0 -> 744 bytes .../1/Example Images/FolderClosed_32.png | Bin 0 -> 406 bytes .../1.2.0/1/Example Images/FolderOpen_32.png | Bin 0 -> 424 bytes .../1/Example Images/RemoteComputer_32.png | Bin 0 -> 879 bytes internal/1.2.0/1/Packages/PngComponents.dpk | 44 + internal/1.2.0/1/Packages/PngComponents.dproj | 118 ++ internal/1.2.0/1/Packages/PngComponents.res | Bin 0 -> 5164 bytes .../1.2.0/1/Packages/PngComponentsDesign.dpk | 41 + .../1.2.0/1/Packages/PngComponentsDesign.res | Bin 0 -> 5196 bytes internal/1.2.0/1/Source/PngBitBtn.pas | 240 ++++ .../1.2.0/1/Source/PngButtonFunctions.pas | 120 ++ internal/1.2.0/1/Source/PngCheckListBox.pas | 206 +++ internal/1.2.0/1/Source/PngFunctions.pas | 552 ++++++++ internal/1.2.0/1/Source/PngImageList.pas | 1252 +++++++++++++++++ internal/1.2.0/1/Source/PngSpeedButton.pas | 147 ++ 24 files changed, 4997 insertions(+) create mode 100644 internal/1.2.0/1/Design/PngComponentEditors.pas create mode 100644 internal/1.2.0/1/Design/PngComponents.dcr create mode 100644 internal/1.2.0/1/Design/PngComponentsRegister.pas create mode 100644 internal/1.2.0/1/Design/PngImageListEditor.dfm create mode 100644 internal/1.2.0/1/Design/PngImageListEditor.pas create mode 100644 internal/1.2.0/1/Docs/Changelog.txt create mode 100644 internal/1.2.0/1/Docs/License.txt create mode 100644 internal/1.2.0/1/Docs/PngComponents.html create mode 100644 internal/1.2.0/1/Docs/pngimage.chm create mode 100644 internal/1.2.0/1/Example Images/Computer_32.png create mode 100644 internal/1.2.0/1/Example Images/FolderClosed_32.png create mode 100644 internal/1.2.0/1/Example Images/FolderOpen_32.png create mode 100644 internal/1.2.0/1/Example Images/RemoteComputer_32.png create mode 100644 internal/1.2.0/1/Packages/PngComponents.dpk create mode 100644 internal/1.2.0/1/Packages/PngComponents.dproj create mode 100644 internal/1.2.0/1/Packages/PngComponents.res create mode 100644 internal/1.2.0/1/Packages/PngComponentsDesign.dpk create mode 100644 internal/1.2.0/1/Packages/PngComponentsDesign.res create mode 100644 internal/1.2.0/1/Source/PngBitBtn.pas create mode 100644 internal/1.2.0/1/Source/PngButtonFunctions.pas create mode 100644 internal/1.2.0/1/Source/PngCheckListBox.pas create mode 100644 internal/1.2.0/1/Source/PngFunctions.pas create mode 100644 internal/1.2.0/1/Source/PngImageList.pas create mode 100644 internal/1.2.0/1/Source/PngSpeedButton.pas diff --git a/internal/1.2.0/1/Design/PngComponentEditors.pas b/internal/1.2.0/1/Design/PngComponentEditors.pas new file mode 100644 index 0000000..a36113c --- /dev/null +++ b/internal/1.2.0/1/Design/PngComponentEditors.pas @@ -0,0 +1,223 @@ +unit PngComponentEditors; + +interface + +uses + Windows, SysUtils, Forms, Classes, Controls, PngImageList, TypInfo, + DesignIntf, DesignEditors, ColnEdit; + +type + TPngImageListEditor = class(TComponentEditor) + public + procedure Edit; override; + procedure ExecuteVerb(Index: Integer); override; + function GetVerb(Index: Integer): string; override; + function GetVerbCount: Integer; override; + end; + + TPngImageCollectionEditor = class(TComponentEditor) + public + procedure Edit; override; + procedure ExecuteVerb(Index: Integer); override; + function GetVerb(Index: Integer): string; override; + function GetVerbCount: Integer; override; + end; + + TPngButtonEditor = class(TComponentEditor) + public + procedure Edit; override; + procedure ExecuteVerb(Index: Integer); override; + function GetVerb(Index: Integer): string; override; + function GetVerbCount: Integer; override; + end; + + TPngImageListImagesEditor = class(TStringProperty) + public + procedure Edit; override; + function GetAttributes: TPropertyAttributes; override; + function GetValue: string; override; + end; + + TPngImageCollectionItemsEditor = class(TPngImageListImagesEditor) + public + procedure Edit; override; + end; + + TEditProperty = class + private + FPropery: string; + procedure EnumProperty(const Prop: IProperty); + public + constructor Create(Component: TComponent; const Prop: string; Designer: IDesigner); + end; + +implementation + +uses + PngImageListEditor; + +resourcestring + SEditImage = '&Edit image...'; + SRecreateImages = '&Recreate images...'; + SEditImages = '&Edit images...'; + SEditing = 'Editing %s.%s'; + SPNGObjectsHaveBeenCopied = 'The PNG objects have been copied to the internal imagelist.'; + +//This type is neccesary to be able to call CopyPngs without having to make it +//public in the TPngImageList class. +type + TPngImageListAccess = class(TPngImageList); + +procedure EditProperty(Component: TComponent; const Prop: string; Designer: IDesigner); +begin + TEditProperty.Create(Component, Prop, Designer).Free; +end; + +{ TPngImageListEditor } + +procedure TPngImageListEditor.Edit; +var + Component: TPngImageList; +begin + Component := GetComponent as TPngImageList; + EditProperty(Component, 'PngImages', Designer); // do not localize +end; + +procedure TPngImageListEditor.ExecuteVerb(Index: Integer); +begin + case Index of + 0: Edit; + 1: begin + TPngImageListAccess(GetComponent).CopyPngs; + MessageBox(0, PChar(SPNGObjectsHaveBeenCopied), + PChar(string(GetComponent.ClassName)), MB_ICONINFORMATION or MB_OK); + end; + end; +end; + +function TPngImageListEditor.GetVerb(Index: Integer): string; +begin + case Index of + 0: Result := SEditImages; + 1: Result := SRecreateImages; + end; +end; + +function TPngImageListEditor.GetVerbCount: Integer; +begin + Result := 2; +end; + +{ TPngImageCollectionEditor } + +procedure TPngImageCollectionEditor.Edit; +var + Component: TPngImageCollection; +begin + Component := GetComponent as TPngImageCollection; + EditProperty(Component, 'Items', Designer); // do not localize +end; + +procedure TPngImageCollectionEditor.ExecuteVerb(Index: Integer); +begin + Edit; +end; + +function TPngImageCollectionEditor.GetVerb(Index: Integer): string; +begin + Result := SEditImages; +end; + +function TPngImageCollectionEditor.GetVerbCount: Integer; +begin + Result := 1; +end; + +procedure TPngButtonEditor.Edit; +begin + EditProperty(GetComponent, 'OnClick', Designer); // do not localize +end; + +{ TPngButtonEditor } + +procedure TPngButtonEditor.ExecuteVerb(Index: Integer); +begin + EditProperty(GetComponent, 'PngImage', Designer); // do not localize +end; + +function TPngButtonEditor.GetVerb(Index: Integer): string; +begin + Result := SEditImage; +end; + +function TPngButtonEditor.GetVerbCount: Integer; +begin + Result := 1; +end; + +{ TEditProperty } + +constructor TEditProperty.Create(Component: TComponent; const Prop: string; Designer: IDesigner); +var + Components: IDesignerSelections; +begin + inherited Create; + FPropery := Prop; + Components := TDesignerSelections.Create; + Components.Add(Component); + GetComponentProperties(Components, tkAny, Designer, EnumProperty); +end; + +procedure TEditProperty.EnumProperty(const Prop: IProperty); +begin + if Prop.GetName = FPropery then + Prop.Edit; +end; + +{ TPngImageListImagesEditor } + +procedure TPngImageListImagesEditor.Edit; +var + ImageList: TPngImageList; + dlg: TPngImageListEditorDlg; +begin + dlg := TPngImageListEditorDlg.Create(nil); + ImageList := GetComponent(0) as TPngImageList; + dlg.Caption := Format(SEditing, [ImageList.Name, GetName]); + dlg.Images.Items.Assign(ImageList.PngImages); + dlg.ImageWidth := ImageList.Width; + dlg.ImageHeight := ImageList.Height; + if dlg.ShowModal = mrOK then begin + ImageList.PngImages.Assign(dlg.Images.Items); + Designer.Modified; + end; +end; + +function TPngImageListImagesEditor.GetAttributes: TPropertyAttributes; +begin + Result := inherited GetAttributes + [paDialog, paReadOnly]; +end; + +function TPngImageListImagesEditor.GetValue: string; +begin + Result := '(PNG images)'; // do not localize +end; + +{ TPngImageCollectionItemsEditor } + +procedure TPngImageCollectionItemsEditor.Edit; +var + Collection: TPngImageCollection; + dlg: TPngImageListEditorDlg; +begin + Collection := GetComponent(0) as TPngImageCollection; + dlg := TPngImageListEditorDlg.Create(nil); + dlg.Caption := Format(SEditing, [Collection.Name, GetName]); + dlg.Images.Items.Assign(Collection.Items); + if dlg.ShowModal = mrOK then begin + Collection.Items.Assign(dlg.Images.Items); + Designer.Modified; + end; +end; + +end. diff --git a/internal/1.2.0/1/Design/PngComponents.dcr b/internal/1.2.0/1/Design/PngComponents.dcr new file mode 100644 index 0000000000000000000000000000000000000000..83ad90b5a6401aa8f0611b86fc737fb78125e455 GIT binary patch literal 2292 zcmd6oF>BjU6oqd>p@O8yrb{;oP5uELI&^3qhc+~63UQ%7!<(04J-qlqq5dl!yTw}< z58X5gM5k<$yToA7>$&&6C#eum9qQ}II-GZOWxWsG5D~>VjIjsgU!{+TUcxcvn8x&h z-qRbp!TB7Y5e?}h+%a9lx7F)CedHSqAfCD7h^!r>-@~Pd@JCA76TTsFC|a#nSl}PX zCu2|ew!hg>p65TYBE`CItH(O(NBvD?pov6pqF$cePa+dVn+^PIt0I=0zSYL%;WvGt zU3)@a>+qY_izhj2I-$U8bsIFkKB-zAV!`GWg+xAovTHNyw#jId{7 zmSxehte4;G`gd}=j`OVivMtN<*J%<@9@pEiHR?EtKmUNqC7Ml?Xt(VtGVAqvw!P&` z;uO)e)O}7cgem9_K>yX|> z;Ir=^_+{&spJ>NVwBzS|;g?}AJ--Zl=^l^ZOC@m}!?(q{yj#jb!9F8KRqP95bSvOn z#C27{cU2Tc)2FJc%y0a(DDuui-dVs9u=m9spqne0)kDSnp5pej>zdoC@jnq%nW+E( literal 0 HcmV?d00001 diff --git a/internal/1.2.0/1/Design/PngComponentsRegister.pas b/internal/1.2.0/1/Design/PngComponentsRegister.pas new file mode 100644 index 0000000..e538dd9 --- /dev/null +++ b/internal/1.2.0/1/Design/PngComponentsRegister.pas @@ -0,0 +1,41 @@ +unit PngComponentsRegister; + +interface + +uses + Classes, DesignIntf, TypInfo, + PngSpeedButton, PngBitBtn, PngImageList, PngCheckListBox, PngComponentEditors; + +procedure Register; + +implementation + +const + SPageName = 'Png'; + +procedure Register; +begin + //Register all components + RegisterComponents(SPageName, [TPngSpeedButton, TPngBitBtn, TPngImageList, + TPngImageCollection, TPngCheckListBox]); + + //Register component editors + RegisterComponentEditor(TPngImageList, TPngImageListEditor); + RegisterComponentEditor(TPngImageCollection, TPngImageCollectionEditor); + RegisterComponentEditor(TPngBitBtn, TPngButtonEditor); + RegisterComponentEditor(TPngSpeedButton, TPngButtonEditor); + + //Register property editors + RegisterPropertyEditor(TypeInfo(TPngImageCollectionItems), TPngImageList, + 'PngImages', TPngImageListImagesEditor); // do not localize + RegisterPropertyEditor(TypeInfo(TPngImageCollectionItems), TPngImageCollection, + 'Items', TPngImageCollectionItemsEditor); // do not localize + + //Hide properties that should be omitted + UnlistPublishedProperty(TPngSpeedButton, 'NumGlyphs'); // do not localize + UnlistPublishedProperty(TPngSpeedButton, 'Glyph'); // do not localize + UnlistPublishedProperty(TPngBitBtn, 'NumGlyphs'); // do not localize + UnlistPublishedProperty(TPngBitBtn, 'Glyph'); // do not localize +end; + +end. diff --git a/internal/1.2.0/1/Design/PngImageListEditor.dfm b/internal/1.2.0/1/Design/PngImageListEditor.dfm new file mode 100644 index 0000000..3a8c8f5 --- /dev/null +++ b/internal/1.2.0/1/Design/PngImageListEditor.dfm @@ -0,0 +1,574 @@ +object PngImageListEditorDlg: TPngImageListEditorDlg + Left = 202 + Top = 128 + BorderIcons = [biSystemMenu] + Caption = 'Editing PngImageList' + ClientHeight = 288 + ClientWidth = 461 + Color = clBtnFace + Font.Charset = ANSI_CHARSET + Font.Color = clWindowText + Font.Height = -11 + Font.Name = 'Tahoma' + Font.Style = [] + OldCreateOrder = False + Position = poScreenCenter + OnClose = FormClose + OnCreate = FormCreate + OnResize = FormResize + OnShow = FormShow + PixelsPerInch = 96 + TextHeight = 13 + object pnlMain: TPanel + Left = 0 + Top = 0 + Width = 461 + Height = 249 + BevelOuter = bvNone + TabOrder = 0 + DesignSize = ( + 461 + 249) + object gbxProperties: TGroupBox + Left = 8 + Top = 4 + Width = 177 + Height = 128 + Anchors = [akLeft, akTop, akBottom] + Caption = 'Image properties' + TabOrder = 0 + object lblName: TLabel + Left = 10 + Top = 20 + Width = 31 + Height = 13 + Caption = '&Name:' + FocusControl = edtName + end + object lblBackgroundColor: TLabel + Left = 10 + Top = 64 + Width = 86 + Height = 13 + Caption = '&Background color:' + FocusControl = cmbBackgroundColor + end + object edtName: TEdit + Left = 8 + Top = 35 + Width = 161 + Height = 21 + TabOrder = 0 + OnChange = edtNameChange + end + object cmbBackgroundColor: TComboBox + Left = 29 + Top = 79 + Width = 140 + Height = 21 + ItemHeight = 0 + TabOrder = 2 + OnChange = cmbBackgroundColorChange + OnDblClick = cmbBackgroundColorDblClick + OnExit = cmbBackgroundColorExit + end + object pnlBackgroundColor: TPanel + Left = 8 + Top = 79 + Width = 20 + Height = 21 + BevelOuter = bvNone + BorderStyle = bsSingle + TabOrder = 1 + OnClick = cmbBackgroundColorDblClick + end + end + object lbxImages: TListBox + Left = 276 + Top = 8 + Width = 177 + Height = 209 + Style = lbOwnerDrawVariable + Anchors = [akLeft, akTop, akRight, akBottom] + DragCursor = crDefault + DragMode = dmAutomatic + ItemHeight = 16 + MultiSelect = True + TabOrder = 3 + OnClick = lbxImagesClick + OnDblClick = lbxImagesDblClick + OnDragOver = lbxImagesDragOver + OnDrawItem = lbxImagesDrawItem + OnEnter = lbxImagesEnter + OnExit = lbxImagesExit + OnKeyDown = lbxImagesKeyDown + OnMeasureItem = lbxImagesMeasureItem + OnMouseUp = lbxImagesMouseUp + OnStartDrag = lbxImagesStartDrag + end + object cmbPreviewBackground: TComboBox + Left = 276 + Top = 220 + Width = 177 + Height = 21 + Style = csOwnerDrawFixed + Anchors = [akLeft, akRight, akBottom] + ItemHeight = 15 + TabOrder = 4 + OnChange = cmbPreviewBackgroundChange + OnDrawItem = cmbPreviewBackgroundDrawItem + Items.Strings = ( + 'Default background' + 'Checkerboard background' + 'Diamonds background' + 'Slashed background' + 'Backslashed background') + end + object gbxImageInfo: TGroupBox + Left = 8 + Top = 136 + Width = 177 + Height = 105 + Anchors = [akLeft, akBottom] + Caption = 'Image information' + TabOrder = 1 + object lblDimensions: TLabel + Left = 8 + Top = 20 + Width = 70 + Height = 13 + Alignment = taRightJustify + AutoSize = False + Caption = 'Dimensions:' + end + object lblColorDepth: TLabel + Left = 8 + Top = 36 + Width = 70 + Height = 13 + Alignment = taRightJustify + AutoSize = False + Caption = 'Color depth:' + end + object lblTransparency: TLabel + Left = 8 + Top = 52 + Width = 70 + Height = 13 + Alignment = taRightJustify + AutoSize = False + Caption = 'Transparency:' + end + object lblCompression: TLabel + Left = 8 + Top = 68 + Width = 70 + Height = 13 + Alignment = taRightJustify + AutoSize = False + Caption = 'Compression:' + end + object lblFiltering: TLabel + Left = 8 + Top = 84 + Width = 70 + Height = 13 + Alignment = taRightJustify + AutoSize = False + Caption = 'Filtering:' + end + object lblDimensionsValue: TLabel + Left = 82 + Top = 20 + Width = 87 + Height = 13 + AutoSize = False + ShowAccelChar = False + end + object lblColorDepthValue: TLabel + Left = 82 + Top = 36 + Width = 87 + Height = 13 + AutoSize = False + ShowAccelChar = False + end + object lblTransparencyValue: TLabel + Left = 82 + Top = 52 + Width = 87 + Height = 13 + AutoSize = False + ShowAccelChar = False + end + object lblCompressionValue: TLabel + Left = 82 + Top = 68 + Width = 87 + Height = 13 + AutoSize = False + ShowAccelChar = False + end + object lblFilteringValue: TLabel + Left = 82 + Top = 84 + Width = 87 + Height = 13 + AutoSize = False + ShowAccelChar = False + end + end + object pnlActionButtons: TPanel + Left = 193 + Top = 35 + Width = 75 + Height = 178 + Anchors = [akLeft] + BevelOuter = bvNone + TabOrder = 2 + object btnAdd: TPngBitBtn + Left = 0 + Top = 0 + Width = 75 + Height = 25 + Caption = '&Add' + TabOrder = 0 + OnClick = btnAddClick + Layout = blGlyphRight + Margin = 6 + Spacing = 3 + PngImage.Data = { + 89504E470D0A1A0A0000000D49484452000000100000001008060000001FF3FF + 610000001974455874536F6674776172650041646F626520496D616765526561 + 647971C9653C000002804944415478DA8D925D48145114C7FF33AEBB7725BF52 + 23B31E8D908C08EB210885A8C0879630B132320A3114C2972232049F22E893BE + E82125A32CF13362C3079505832CB34811524837025B4557F7EBEEECDC3BB7AB + A3D52846070E773867FEBF39FF734711426021B2CFF454C6547BADA638D29599 + A92FB648A88E33FE8A85A382852958240A1692A77CD6231A04BFBEA85396015B + 4E7BC239FB7625541424A2FECD24FA5EBF178E90FFAAE046CD7F01369579A8EB + 643E797800189E05EADC4174B5F4439D186B8CE3BC5AA79AFFDF8013DD34FFD8 + 7E72710F1033005D01DA87389E37F421F8F1934765AC5C4E31B62660637117CD + 2B3944CA738108930D0970DA81FE1F024F1B07E0EBEA1DB569E152A6F1015DDA + 5905D8E072D36D2585E4683610D56136653A1DC04408686B1BC14453874F9DF3 + 5719DC6835F80D2B20A3B0936E2E7691822C6981C3128E7820205FEBE9F662BC + FE8586E9C90B42DCBE6B01A41D6CA5C9454564472AC00C53C88539459C0AD864 + EA36E0C3A00F53B71E4445A8CE6901AC2F7849D523252493008659324FC504E9 + 6C6114C03FEEC3FC3D0908AE00A4EC7D4623AE5222F558D263A1A51B660AB950 + 7CFD06743469989D9216EE582D24ED7E428387CB088C65F552CAD115B90331F8 + 197037FB40035580BD55889BD62526ED7C4C95E36709D89FE529EAA211447A7A + A1F7BA47C163A540FC8039DD0A404AEE239A71AE8208DDF4ADCAAF72CA30DDD2 + 8EE0BBB71E592C973986DFF656005273EED3ED97AB088BCA8D4BBF81F19FF036 + 77627E64A85156AA25D2FFF7D5AE02ACCBBA16CE3B7F2A216D6B26BC9E610C37 + 3447B5C08CFC5BEC57CCCBB4C62A80CD79A9D2999C589B909E9A3EE7FD3E140B + 856BA45F37D68865C02F696882F0CDD367480000000049454E44AE426082} + PngOptions = [pngBlendOnDisabled, pngGrayscaleOnDisabled] + end + object btnDelete: TPngBitBtn + Left = 0 + Top = 29 + Width = 75 + Height = 25 + Caption = '&Delete' + TabOrder = 1 + OnClick = btnDeleteClick + Layout = blGlyphRight + Margin = 6 + Spacing = 3 + PngImage.Data = { + 89504E470D0A1A0A0000000D49484452000000100000001008060000001FF3FF + 610000001974455874536F6674776172650041646F626520496D616765526561 + 647971C9653C0000026B4944415478DA8D935948545118C7FF779B7BE7CEA233 + A913068D46E38339916225B43866B48C94630E961562D1438821E44B3D0D483E + 842F06D9824259894942168542055AD04B0D0519D1F2580E895B33317366BBB7 + 338E4533B9F487EF5CEE39DFF73BDFF91F0EA3AA2A1262D85608B2085EA75D08 + 09BCAC05A793184EE00EC664BD0759391BC578784AA346DA3EDFA8BC325FB712 + 003CDB1ED69BCEEF38B08539B93F17D7470378FFDC1BFCDAEBD02D0F904593C2 + 729D6ABEAD618FBB0C9E2A03369881A627C0D0AD51E2BBEDD02E0D90259BC2F3 + DD86D292F2A38DDBE1B27310689AC0021DAF80B1FEA7C4D7BF7B3180044EE44A + E3A2AECFB2B7A2E058C3666C5DC32018051269320FF4BC03BC0323E4FBE0BE54 + 004B012CC7D42A99E62E6BBDCB525D5308AB1E08856931929204E0FE17E0D3C0 + 6332F9B02AAD03A6E50CB2733BF21A0F8B3B2BF360A473E11852A4E1801713C0 + B77B43646AD89506D07B42592D4D5271B1057C04882D6CCBFC19929F37D34064 + 6890CC3E73A7010C9E5046739394B3DE827868219B2EC569286AF2D74FC173B4 + 2BD3F05D32337664912398733AF843F5225BB88EF64FEBE3C94E54E5AF735023 + 331EDD21732F8FA703CED231520BADB10BCE3A0B4A3601D47D28A93E80FA6078 + 7093F8BD8D8B01128A9682D3F40915CE02795745E27EFEE940E9EF2181B7A796 + 0224A4DA68741BCAB69567BB6BC0697928D1A4270CBDCAC9ABD7C88FF1D3CB01 + 12524CD481CE8C427B83B5AE1AC6FCD58851137909186FBF4C663F34AF044072 + 4B442E88C655AD4527EA24ABA308D31F7D787DA937F873E29CEE3F00BF15756A + F4BAF64CEB5A7B7072662AE40FB4C5C8C5F9E7FC0BBF2FFCE106AF47A6000000 + 0049454E44AE426082} + PngOptions = [pngBlendOnDisabled, pngGrayscaleOnDisabled] + end + object btnReplace: TPngBitBtn + Left = 0 + Top = 58 + Width = 75 + Height = 25 + Caption = '&Replace' + TabOrder = 2 + OnClick = btnReplaceClick + Layout = blGlyphRight + Margin = 6 + Spacing = 3 + PngImage.Data = { + 89504E470D0A1A0A0000000D49484452000000100000001008060000001FF3FF + 610000001974455874536F6674776172650041646F626520496D616765526561 + 647971C9653C000003464944415478DA5D525B4C5457145DE70EC3D0995B2582 + 8A112316FBD12698C6F8200A3206A90A43438C3AB5C6D6261325FAD3F4A3F607 + DBFEF92121468D1AA2898FD8001518CC84A94AC6AA959AB64322FED854014306 + 9D1106B833F7FD70DF3B62D49DEC7372CED96BEDB5F73EAC7CFFC05185E5B768 + 8A9A2E10670EE8B2D6AB4B0AC8161A8CEBD05CDE6A6B3A3DEC1233BB74597DA2 + 8B0A0C4986264AB074136C6968305BD3B0D6CB341591CEC1143FF33CA82946CC + 54D490AF6255FB3707D7221A7E8CA15FA3718FAE345282C43B04A5CDFF668E7D + BFDAB7BD0CD877258B3B5DB713FC6CD22F8B6ADDA70D9B4E477FF9040F93C0FE + 9FE378168EC65C9619342425F5866049E8817028B48E0F7E0C8C668196EE690C + 77FF1ECF9F4A8EAFDCEEFFA2F5BB0A147B80072F8023C7E34847FA7B3851DCAB + C98AE410947C3B28ECF9BA92DFB20CD04C2029036DE1098C748451B6B9123F1D + FE0C8487270F187C0E9C68BB874C24729EA96AB3695A3A5BB4EFAEB06D4F15BF + 613120E980DB0508B45FBE3E0AFEC302046B4BE0B2008BBC8048FE22259DADFD + 9007A2672C703FB0E2AFFE10D6EDD8C4571402AA418194CDCD0122030C3A7B69 + 37E992D973A1C5E306224F4D0C9FEE02E27FB6B1A2604C280FF8F98FBCB912E6 + 8C63B9DD06CF997DA5D3F93E3535F992649E3B9161453B6F09F3EA6AF945C44C + 3D7100D66B02DB5FF33825D80AC7668119C242A5E52C112C68BA2168D5757CBE + 95BB538C1C497E01B94DA0E752DBEA32F6FF7239BA806B9DC0D0FD565618880A + D3EBB7F2D0904BCD7241ECFFFF607D40752D2975E2E76A60D448ABBF8F4672E3 + 2475EB47B6A03E22E835F50E01B3C114608C8C41EBBA88BCAA5AB8366C84F3C6 + E5C0E2CD01A837C3E7A9C066721A63FD75615E4380B7543A521FE4F11798ECB8 + FAB7369118290C34ED9E5FB3D1A99F235553B7EE61B2B7A787BEE05E922939A2 + 4A037D99E5C1461FA8F6EC441AA397AE26C4C4845F97D4CFCB76EF3855B2A5D2 + 513616BE8DF1EEDF62243B48B0D49BC994545DCAAE39F8A557991131D4DE999A + 1D7B16E45C793179321D5AB1CDDFBEE670131EF7FD8347172EC74D038D943981 + B78CCD2F6F3DEAE67D2DA6A4A4332FA70E701CD7ABCE6661AADAC23C8FBBC357 + 5C549D4D4D0EEBAABC8BC04FF09EBD02E1D692A4E09B28E50000000049454E44 + AE426082} + PngOptions = [pngBlendOnDisabled, pngGrayscaleOnDisabled] + end + object btnClear: TPngBitBtn + Left = 0 + Top = 87 + Width = 75 + Height = 25 + Caption = '&Clear' + TabOrder = 3 + OnClick = btnClearClick + Layout = blGlyphRight + Margin = 6 + Spacing = 3 + PngImage.Data = { + 89504E470D0A1A0A0000000D49484452000000100000001008060000001FF3FF + 610000001974455874536F6674776172650041646F626520496D616765526561 + 647971C9653C000003094944415478DA6D935B48145118C7FFB373E6BA9BDBBA + ADB58BE1A5A8970CB4A28C8A966EA696DA45ED22452515296A12BD45E14B4545 + 0F15223D1414B545216D8558A2A6899544D8432F964611994617775777DD9DE9 + 9B59A5A80E733867BE6FFEBFF3FDBFE170400D38DE02A6CA608A0C5E95C06471 + 96A6DA6E730E47068B8E76303D560270434C11C1CB426158B137088AE410F570 + 1DF70F40163C1126F933B7ADCFCA299A8B2BF5CF11ECED2DE725F1B220F1DE80 + 7D862FBF24DBA50912DAEFBF08FD05905C518EF7A514AEF35E39BE00F3938075 + C7DEE0CD83F643B2223E0AD893DA56147B3DD7765AF17000387AF665F0374016 + 155D55AF3BF2728B4E1DC9C2E2E9C07018A83DFF1A7D0FDBEE45125DC9199B73 + B2EA364D45AA15F0F501971A9E05E2008E6310C57A6B7EEEDEEAC3CB914DE270 + 94268013175EA1BFB51BE9A505A82970234906040BF0F80370E36AB701A8B601 + B1D3CAAA9C83C5B5B95842E23112739489D1F4B57C4660640C651B52318501E3 + 3140A1B56B1068BAD169002ACF2173694D464531F2D22D088FD3B1BAF9C042D9 + 106D781E50691DD7084C7191DE5F7F079EDF794200F79911ECAFB2254D63584A + 4D635C5C3C390C8831B43F8286857721E0ADBF750270A0CA0691C14EA5A524C4 + 4FE02684FA84D898DC049011E00B55FAB3B9C5B470862CD46273B19126E3804D + 8A9F625A216884B691D1B85822B868C40CD09366B3892AB93B89ECB595DCFA8D + D0A3F8EDC1807CFA086E2C047DF61C136EE68C5204606A7753FC375281C4D4EA + C535057BD535AB4C886E348C3E8A763D45B4E33184ADBBC1A7A75080727A1CC0 + DA1F4C028C1153C0B1EBCEC2A2A2C4D5CBA0C5E27DF8D1DE896FFEC65BA2DB93 + E62CDDB1484E9E0E8DFC7322E5EEFBFF04982D73911D5FF2A62DDE948295D0A8 + 8AC1962E0CF8EE56D03D69563DEEB6D45DDB3D56B783FE2DF0FEA63FF817C0AC + C463E1E19FB7A72C6BEEC685E8B9D888FEA6D67239D171598BC5BC0969337D99 + FB4A5C925D454FFDCDD07F0026641613E5DB5697332338FCB5231A1E2FB1086C + 484CB05155D142DB34678385AE732410ACFB05147F0B83A25F23860000000049 + 454E44AE426082} + PngOptions = [pngBlendOnDisabled, pngGrayscaleOnDisabled] + end + object btnUp: TPngBitBtn + Left = 0 + Top = 124 + Width = 75 + Height = 25 + Caption = '&Up' + TabOrder = 4 + OnClick = btnUpClick + Layout = blGlyphRight + Margin = 6 + Spacing = 3 + PngImage.Data = { + 89504E470D0A1A0A0000000D49484452000000100000001008060000001FF3FF + 610000001974455874536F6674776172650041646F626520496D616765526561 + 647971C9653C0000021C4944415478DAA5933B68535118C7FFE7DE247D886821 + 26197C504C8A5894D2461087BA38A874503B89521F9B858E0AA28BA08B1D1C14 + 412D48EB031D62972E6D8DD84987802D8A1645712AA6A995368F7BCFDB737223 + B44171C8E17CE783EF5E7EE7FBFEF77F89D61A8D2CD23020753E0B68BBAB07A0 + ECA121851CF211B9A928835B2A5E9294DE16C50A44C983CDAC5481E6F2EF0025 + 44BF1F6A79D27B38DD04A530FD7C863A3F0BA714E599FF038448AF8AD0C48143 + DDF13B27DB400870617411D9B1A97CB357EC931ECBF17F0374CAA37A626BF79E + 8ECB2712D81209E65C12C0B587DF309F99FC1C617E1FAFD02FAC585E03B04BA9 + 362ED4787847EAE0E923ED486E02CA3C78B4C180BE9680FB0F7258CEBE9E218C + 1F371DFC5AD781E4629447B70DECEFDD85DD51029F013CD01361076869023E2D + 294C8E4CC37BFB664C7371467155034871BDD81ABB92E8DA8B8EA8032103396C + 4805840C4098CC4C616E41A0F0E8199C8FB337941BBE4A5267A78E5244322BED + FB9AE3B156386B6CA1AB46017C334AA16C46A2A61036B5FC22F0F49EAF970BFD + 64E7B957EF56E29D5D7C730C9A0437592BB824080BA4352D1C52231B887AFF01 + FE8BC7B324399813A1CE1E574BABA301A00E60BB2075F63345C708FB7DF8AE24 + C981973F123DE9F8C698915DD9B7AB1BEB0C5E07704266A4F905CCDD1AC993ED + C7C6075DD71DB697492ACDB765904C40D9E036F35AFCA905F3B0B2A7E86AE962 + E33F53A380DF494945E019F9A78D0000000049454E44AE426082} + PngOptions = [pngBlendOnDisabled, pngGrayscaleOnDisabled] + end + object btnDown: TPngBitBtn + Left = 0 + Top = 153 + Width = 75 + Height = 25 + Caption = '&Down' + TabOrder = 5 + OnClick = btnDownClick + Layout = blGlyphRight + Margin = 6 + Spacing = 3 + PngImage.Data = { + 89504E470D0A1A0A0000000D49484452000000100000001008060000001FF3FF + 610000001974455874536F6674776172650041646F626520496D616765526561 + 647971C9653C000002174944415478DAB5934F68134114C6BFCD6E936AFF482B + 521A3555AC52D4D21EF620586C4104FF1D2C257810ADA5148AC5A35E144F7A50 + 111141105A44AD07853482C593158A2749A1912A88550F82D5DA966CB2D96E76 + 6667C7994D0824F1161C18DEEEDB79BFF7E6FB5885738E6A965235A07D68E682 + E3A9B719E3014E5D7894C22322120A26222F4617CCFF4EFCC8D2A607C3B8A444 + 86DFFD8EE85D2DBBDA1AE079E5F8B257259FD3346021F1137337279695D69184 + 3B7A5E574FB50386535153B254592CF6C620F0F207702DFA8029E1E8EBF9B0DE + DD1DED6B459D0A30AFB25042B500F0C70252A249631D30F5E2233E3D9C4C2A6D + FD53C7B3448D6D3BDC5B7B68FF26410078D9D812FA6105F8BC0AE404A866750D + C6DD7B39ACA70694ADC79E83DBCE75AB297C65FB913EEC6856C10A105EE8BE68 + 00DF5205A2EB02938F80AFC91B40E8AA123E2A000E0535ADC774E7DE73F53D07 + 119417155DA5C32601D67252004914C9780C48CC3E11730C4A7C1E202CA2996C + 13B349DCEE3CD0EB76E9E06EFEBCEF8C1C430887B733C09B57B3E2A91F08F833 + 1501C4B4C032D66E97B269D673628FB6AF03ACE04A6003E0BC4F82C49F7E1182 + 9C14D9C5A2462500D3064D9B3AD782D35BA2A75BEA3B223E21B3F01D4B13E3CB + CC324571CD5C89431580EC3A889119A86DDEFCAC73EC6C480A317F67DCB1577E + 9D11F7885558FC2F80BF4DEB62A8B1E1163C8E5CDAB82C54BCFF7F7EA66A017F + 01C92B1C3633E7F2D20000000049454E44AE426082} + PngOptions = [pngBlendOnDisabled, pngGrayscaleOnDisabled] + end + end + end + object pnlButtons: TPanel + Left = 0 + Top = 249 + Width = 461 + Height = 37 + BevelOuter = bvNone + TabOrder = 1 + DesignSize = ( + 461 + 37) + object pnlModalButtons: TPanel + Left = 152 + Top = 4 + Width = 158 + Height = 25 + Anchors = [akBottom] + BevelOuter = bvNone + TabOrder = 0 + object btnOK: TPngBitBtn + Left = 0 + Top = 0 + Width = 75 + Height = 25 + Caption = '&OK' + Default = True + ModalResult = 1 + TabOrder = 0 + PngImage.Data = { + 89504E470D0A1A0A0000000D49484452000000100000001008060000001FF3FF + 610000001974455874536F6674776172650041646F626520496D616765526561 + 647971C9653C000001D44944415478DAC5934148146118869F7F669ADD550221 + 5C5110090FDB25820E2B052D754848F010648487D214098930A443E521F02228 + E52D4AA873744828DA20483A48D6C15B5D4294D2924A6D0F5B63EB36BEF3AF44 + 222D8287061E66BEE17B9F9DEF9B1D1386213B39CC8E05DCA49E353E9257F543 + FC146BC213BED8F5D7B5B751FB34FA31BA5C97FD8661A629709D55B26505D1D9 + A58E18E771E85115188F36E30C39AF5DDF6D2C7C2BB44934B145109D43F65049 + 77554355673C164F2DCE2C4E4A72C654326FCC35D39FCC24477273B9F9E06D70 + 5AEDAF242A050D35929CF4EABD3EF5A4BC658F85C9856CB150ECA6824FA6226A + E925E337FBCF9D238E1FDC096699E394A2EF44070D7498C3A629914E60A60CF9 + A7F9871AA38738DF05254117493566B9CC41BE28768F198DB14486348754578B + 47E209A3FAD51BEC266747FB23E85451E43617B9404AD71F84236A4534CA036D + E40DB7B4BCABDA435112360BDAA37D6AB327B8CB513D60B8D1B0221E8B69AE28 + 38226C68ABA0D53EC13EF6F292731A277A5DCB625CDAF75C5270CC8612FF12B4 + 584174E3859EE318BFECBC2B1AA55FCDF76D205E4E705CC56FFB4719E000837C + E6ABC267F51A9F6D0A9615948EB41893AC4F4B9CB07762DB10FCF7AF711D7610 + 84C5CCB842D50000000049454E44AE426082} + end + object btnCancel: TPngBitBtn + Left = 83 + Top = 0 + Width = 75 + Height = 25 + Cancel = True + Caption = '&Cancel' + ModalResult = 2 + TabOrder = 1 + PngImage.Data = { + 89504E470D0A1A0A0000000D49484452000000100000001008060000001FF3FF + 610000001974455874536F6674776172650041646F626520496D616765526561 + 647971C9653C000002E24944415478DA6D93CB4F135114C6BF79B5451E022D42 + B0C5C82321206A58812B4AD8B8D2981077B22BB4087F4C1BCA232E64E38618FF + 00096C30411E0B44A031214140A10FFAA02D7DCCDCB99E3B8A4074929399CC9D + EF37F77EDF39D2D1230012C00DDCA1EA3638964B65A05C02741D600C372EC380 + 9773EC98266206AD49478F495C42BDEA541750533198DFCB064837FD3F0089FD + 352E255CCA9A4BD92C1FE640523A7C8066B5D6365FF7EAC590E66EC149F88D99 + DE4C4E3219537AF90A40B07197C7166CEFF7C8D9E30CBE7D4E2CE62E30221D76 + 6240BB5FB5DCF03A00D9D104F3C7571CBF7D6F24B7321304991100128FB9DCF6 + 506BBF5BD5B802964C636B258E54867BA5C387908A598CDDEA72061B5F3E5315 + 471DD8E93E0EDE7DC45924EFD309E074DBE63AFA3D50B80C3D914164FDCC8825 + D8A4AC604600502A02C5738C5777DD0EDD7DEE9514AD0A2C7A80FD0F9BE0BA89 + D63E37344B9C16621E4D98130A1D51986F01CA04289169A53CFCD5ED95E196A7 + BDD0640758220A295F806CC012EF6D9C211637038A8269CB180BD0F33B3201B0 + EE45F86AEF55CCB60D744021217279B0740EBB6B0944636C94C4737F63118055 + 273DF0ABA8C8309FCB639F6D7FD20245A7855C810017D8FD92C6CF241F953801 + E8B5F94723ADD6DF10FBC9B0701B1926CECCCE32405E87526428A78AD8FD5EC6 + 4901018563FA1F80C8D9E9B185DAFA3C92884A4FA410D94852F798E86CD0A015 + 4CE8E706B6D3E0511313B493A94B80441D36E674DB83E4B67AE9F6DEBA65984F + F451A30373DD0E40CBD28FA8B9B6097B0A4CCAA018576A3040EDB9DCE5BD0799 + ABD0E356544634CE26C8B019EA799419C61A65847A18544DEC966A832A057805 + A0D96697E7DB7BEB872A1D32226B09331A3727AD9CE9120046454336DEC411A4 + D064DA08B680454A7F44FA546B45586FB761C1AE4A83C90C0F9078FAD2D84B00 + 4D201887BF0E089370290F0CAB6298048051DE659DC699A15B96B17C7D7CAF03 + 44D1A75E05D8A1168889F55F525F839E0094AAF50000000049454E44AE426082} + end + end + object chkUseFilenames: TCheckBox + Left = 341 + Top = 7 + Width = 112 + Height = 17 + Anchors = [akTop, akRight] + Caption = 'Use Filenames' + Checked = True + State = cbChecked + TabOrder = 1 + end + end + object dlgOpenPicture: TOpenPictureDialog + DefaultExt = 'png' + Filter = 'Portable Network Graphics (*.png)|*.png' + Options = [ofHideReadOnly, ofPathMustExist, ofFileMustExist, ofEnableSizing] + Title = 'Browse for a PNG file' + Left = 40 + Top = 251 + end + object dlgColor: TColorDialog + Options = [cdAnyColor] + Left = 72 + Top = 251 + end + object Images: TPngImageCollection + Items = <> + Left = 8 + Top = 251 + end +end diff --git a/internal/1.2.0/1/Design/PngImageListEditor.pas b/internal/1.2.0/1/Design/PngImageListEditor.pas new file mode 100644 index 0000000..48137ee --- /dev/null +++ b/internal/1.2.0/1/Design/PngImageListEditor.pas @@ -0,0 +1,1216 @@ +unit PngImageListEditor; + +interface + +uses + Windows, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, ExtCtrls, + ExtDlgs, pngimage, PngFunctions, PngBitBtn, PngImageList, Buttons; + +type + TPngImageListEditorDlg = class(TForm) + cmbBackgroundColor: TComboBox; + cmbPreviewBackground: TComboBox; + dlgColor: TColorDialog; + dlgOpenPicture: TOpenPictureDialog; + edtName: TEdit; + gbxImageInfo: TGroupBox; + gbxProperties: TGroupBox; + lblBackgroundColor: TLabel; + lblColorDepth: TLabel; + lblColorDepthValue: TLabel; + lblCompression: TLabel; + lblCompressionValue: TLabel; + lblDimensions: TLabel; + lblDimensionsValue: TLabel; + lblFiltering: TLabel; + lblFilteringValue: TLabel; + lblName: TLabel; + lblTransparency: TLabel; + lblTransparencyValue: TLabel; + lbxImages: TListBox; + pnlActionButtons: TPanel; + pnlBackgroundColor: TPanel; + pnlMain: TPanel; + btnAdd: TPngBitBtn; + btnDelete: TPngBitBtn; + btnReplace: TPngBitBtn; + btnClear: TPngBitBtn; + btnUp: TPngBitBtn; + btnDown: TPngBitBtn; + Images: TPngImageCollection; + pnlButtons: TPanel; + pnlModalButtons: TPanel; + btnOK: TPngBitBtn; + btnCancel: TPngBitBtn; + chkUseFilenames: TCheckBox; + procedure btnAddClick(Sender: TObject); + procedure btnClearClick(Sender: TObject); + procedure btnDeleteClick(Sender: TObject); + procedure btnDownClick(Sender: TObject); + procedure btnReplaceClick(Sender: TObject); + procedure btnUpClick(Sender: TObject); + procedure cmbBackgroundColorChange(Sender: TObject); + procedure cmbBackgroundColorDblClick(Sender: TObject); + procedure cmbBackgroundColorExit(Sender: TObject); + procedure cmbPreviewBackgroundChange(Sender: TObject); + procedure cmbPreviewBackgroundDrawItem(Control: TWinControl; Index: Integer; + ARect: TRect; State: TOwnerDrawState); + procedure edtNameChange(Sender: TObject); + procedure FormClose(Sender: TObject; var Action: TCloseAction); + procedure FormCreate(Sender: TObject); + procedure FormResize(Sender: TObject); + procedure FormShow(Sender: TObject); + procedure lbxImagesClick(Sender: TObject); + procedure lbxImagesDblClick(Sender: TObject); + procedure lbxImagesDragOver(Sender, Source: TObject; X, Y: Integer; + State: TDragState; var Accept: Boolean); + procedure lbxImagesDrawItem(Control: TWinControl; Index: Integer; + ARect: TRect; State: TOwnerDrawState); + procedure lbxImagesEnter(Sender: TObject); + procedure lbxImagesExit(Sender: TObject); + procedure lbxImagesKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState); + procedure lbxImagesMeasureItem(Control: TWinControl; Index: Integer; var Height: Integer); + procedure lbxImagesMouseUp(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); + procedure lbxImagesStartDrag(Sender: TObject; var DragObject: TDragObject); + private + FDraggingIndex: Integer; + FImageHeight: Integer; + FImageWidth: Integer; + FMaxWidth: Integer; + FSelectionBodyColor: TColor; + FSelectionBorderColor: TColor; + function ConformDimensions(Png: TPngImage): Boolean; + function FirstSelected: Integer; + function LastSelected: Integer; + procedure DrawBackground(Canvas: TCanvas; const ARect: TRect; ScrollPos, Index: Integer; + BlendColor: TColor = clNone; IgnoreScrollPos: Boolean = False); + procedure GetColorProc(const S: string); + procedure ParseBackgroundColor(Sender: TObject; CanDisplayError, CanChangeText: Boolean); + procedure SelectBackgroundColor(Sender: TObject; Color: TColor); + public + property ImageHeight: Integer read FImageHeight write FImageHeight; + property ImageWidth: Integer read FImageWidth write FImageWidth; + end; + +var + PngImageListEditorDlg: TPngImageListEditorDlg; + +implementation + +uses + SysUtils, Math; + +resourcestring + SAreYouSureYouWantToDelete = 'Are you sure you want to delete %s?'; + SAnd = ' and '; + SThisWillClearTheEntireImageList = 'This will clear the entire image list. Are you sure you want to do this?'; + SIsNotAValidColorValue = '"%s" is not a valid color value'; + +{$R *.dfm} + +//For calculating OfficeXP colors +const + WeightR: single = 0.764706; + WeightG: single = 1.52941; + WeightB: single = 0.254902; + +const + SIncorrectSize = + 'The selected PNG "%s" must be %dx%d in size, while its actual size is %dx%d'; + +var + ResX, ResY: Integer; + + { Globals } + +function Blend(C1, C2: TColor; W1: Integer): TColor; +var + W2, A1, A2, D, F, G: Integer; +begin + if C1 < 0 then + C1 := GetSysColor(C1 and $FF); + if C2 < 0 then + C2 := GetSysColor(C2 and $FF); + + if W1 >= 100 then + D := 1000 + else + D := 100; + + W2 := D - W1; + F := D div 2; + + A2 := C2 shr 16 * W2; + A1 := C1 shr 16 * W1; + G := (A1 + A2 + F) div D and $FF; + Result := G shl 16; + + A2 := (C2 shr 8 and $FF) * W2; + A1 := (C1 shr 8 and $FF) * W1; + G := (A1 + A2 + F) div D and $FF; + Result := Result or G shl 8; + + A2 := (C2 and $FF) * W2; + A1 := (C1 and $FF) * W1; + G := (A1 + A2 + F) div D and $FF; + Result := Result or G; +end; + +function ColorDistance(C1, C2: Integer): Single; +var + DR, DG, DB: Integer; +begin + DR := (C1 and $FF) - (C2 and $FF); + Result := Sqr(DR * WeightR); + DG := (C1 shr 8 and $FF) - (C2 shr 8 and $FF); + Result := Result + Sqr(DG * WeightG); + DB := (C1 shr 16) - (C2 shr 16); + Result := Result + Sqr(DB * WeightB); + Result := Sqrt(Result); +end; + +function GetAdjustedThreshold(BkgndIntensity, Threshold: Single): Single; +begin + if BkgndIntensity < 220 then + Result := (2 - BkgndIntensity / 220) * Threshold + else + Result := Threshold; +end; + +function IsContrastEnough(AColor, ABkgndColor: Integer; DoAdjustThreshold: Boolean; Threshold: Single): Boolean; +begin + if DoAdjustThreshold then + Threshold := GetAdjustedThreshold(ColorDistance(ABkgndColor, $000000), + Threshold); + Result := ColorDistance(ABkgndColor, AColor) > Threshold; +end; + +procedure AdjustContrast(var AColor: Integer; ABkgndColor: Integer; Threshold: Single); +var + X, Y, Z: Single; + R, G, B: Single; + RR, GG, BB: Integer; + I1, I2, S, Q, W: Single; + DoInvert: Boolean; +begin + I1 := ColorDistance(AColor, $000000); + I2 := ColorDistance(ABkgndColor, $000000); + Threshold := GetAdjustedThreshold(I2, Threshold); + + if I1 > I2 then + DoInvert := I2 < 442 - Threshold + else + DoInvert := I2 < Threshold; + + X := (ABkgndColor and $FF) * WeightR; + Y := (ABkgndColor shr 8 and $FF) * WeightG; + Z := (ABkgndColor shr 16) * WeightB; + + R := (AColor and $FF) * WeightR; + G := (AColor shr 8 and $FF) * WeightG; + B := (AColor shr 16) * WeightB; + + if DoInvert then begin + R := 195 - R; + G := 390 - G; + B := 65 - B; + X := 195 - X; + Y := 390 - Y; + Z := 65 - Z; + end; + + S := Sqrt(Sqr(B) + Sqr(G) + Sqr(R)); + if S < 0.01 then + S := 0.01; + + Q := (R * X + G * Y + B * Z) / S; + + X := Q / S * R - X; + Y := Q / S * G - Y; + Z := Q / S * B - Z; + + W := Sqrt(Sqr(Threshold) - Sqr(X) - Sqr(Y) - Sqr(Z)); + + R := (Q - W) * R / S; + G := (Q - W) * G / S; + B := (Q - W) * B / S; + + if DoInvert then begin + R := 195 - R; + G := 390 - G; + B := 65 - B; + end; + + if R < 0 then + R := 0 + else if R > 195 then + R := 195; + if G < 0 then + G := 0 + else if G > 390 then + G := 390; + if B < 0 then + B := 0 + else if B > 65 then + B := 65; + + RR := Trunc(R * (1 / WeightR) + 0.5); + GG := Trunc(G * (1 / WeightG) + 0.5); + BB := Trunc(B * (1 / WeightB) + 0.5); + + if RR > $FF then + RR := $FF + else if RR < 0 then + RR := 0; + if GG > $FF then + GG := $FF + else if GG < 0 then + GG := 0; + if BB > $FF then + BB := $FF + else if BB < 0 then + BB := 0; + + AColor := (BB and $FF) shl 16 or (GG and $FF) shl 8 or (RR and $FF); +end; + +procedure SetContrast(var Color: TColor; BkgndColor: TColor; Threshold: Integer); +var + T: Single; +begin + if Color < 0 then + Color := GetSysColor(Color and $FF); + if BkgndColor < 0 then + BkgndColor := GetSysColor(BkgndColor and $FF); + T := Threshold; + if not IsContrastEnough(Color, BkgndColor, True, T) then + AdjustContrast(Integer(Color), BkgndColor, T); +end; + +function ResizeProportionalX(InitialValue: Integer): Integer; +begin + Result := InitialValue * ResX div 96; +end; + +function ResizeProportionalY(InitialValue: Integer): Integer; +begin + Result := InitialValue * ResY div 96; +end; + +procedure InitResolution; +var + DC: HDC; +begin + DC := GetDC(0); + ResX := GetDeviceCaps(DC, LOGPIXELSX); + ResY := GetDeviceCaps(DC, LOGPIXELSY); + ReleaseDC(0, DC); +end; + +{ TPngImageListEditorDlg } + +function TPngImageListEditorDlg.ConformDimensions(Png: TPngImage): Boolean; +begin + //Returns whether an image conforms the specified dimensions, if available + Result := ((ImageHeight = 0) and (ImageWidth = 0)) or ((ImageHeight = + Png.Height) and (ImageWidth = Png.Width)); +end; + +function TPngImageListEditorDlg.FirstSelected: Integer; +begin + //Return the first selected image + Result := 0; + while not lbxImages.Selected[Result] and (Result < lbxImages.Items.Count) do + Inc(Result); +end; + +function TPngImageListEditorDlg.LastSelected: Integer; +begin + //Return the last selected image + Result := lbxImages.Items.Count - 1; + while not lbxImages.Selected[Result] and (Result >= 0) do + Dec(Result); +end; + +procedure TPngImageListEditorDlg.DrawBackground(Canvas: TCanvas; const ARect: TRect; + ScrollPos, Index: Integer; BlendColor: TColor; IgnoreScrollPos: Boolean); +var + I, X, Y: Integer; + PatBitmap, BkBitmap: TBitmap; + Even: Boolean; +begin + //Draw the background of the listbox, if any + if Index = 0 then begin + //No background, then skip the hard part + if BlendColor = clNone then + Canvas.Brush.Color := clWindow + else + Canvas.Brush.Color := BlendColor; + Canvas.FillRect(ARect); + Exit; + end; + + //Draw the background + BkBitmap := TBitmap.Create; + PatBitmap := TBitmap.Create; + try + PatBitmap.Height := 16; + PatBitmap.Width := 16; + with PatBitmap.Canvas do begin + //First, draw the background for the pattern bitmap + if BlendColor = clNone then begin + Brush.Color := clWindow; + FillRect(Rect(0, 0, PatBitmap.Height, PatBitmap.Width)); + Brush.Color := Blend(clWindow, clBtnFace, 50); + end + else begin + Brush.Color := Blend(clWindow, BlendColor, 50); + FillRect(Rect(0, 0, PatBitmap.Height, PatBitmap.Width)); + Brush.Color := BlendColor; + end; + + //Then, draw the foreground on the pattern bitmap + Pen.Color := Brush.Color; + case Index of + 1: begin + //Checkerboard background + FillRect(Rect(PatBitmap.Width div 2, 0, PatBitmap.Width, PatBitmap.Height div 2)); + FillRect(Rect(0, PatBitmap.Height div 2, PatBitmap.Width div 2, PatBitmap.Height)); + end; + 2: begin + //Diamonds background + PatBitmap.Width := 10; + PatBitmap.Height := 10; + Polygon([Point(PatBitmap.Width div 2, 0), Point(PatBitmap.Width, + PatBitmap.Height div 2), Point(PatBitmap.Width div 2, + PatBitmap.Height), Point(0, PatBitmap.Height div 2)]); + end; + 3: begin + //Slashed background + Even := True; + I := 2; + while I < PatBitmap.Width + PatBitmap.Height do begin + if I < PatBitmap.Width then begin + MoveTo(I, 0); + LineTo(-1, I + 1); + end + else begin + MoveTo(PatBitmap.Width, I - PatBitmap.Width); + LineTo(I - PatBitmap.Width, PatBitmap.Height); + end; + if Even then + Inc(I, 1) + else + Inc(I, 3); + Even := not Even; + end; + end; + 4: begin + //Backslashed background + Even := True; + I := 2; + while I < PatBitmap.Width + PatBitmap.Height do begin + if I < PatBitmap.Width then begin + MoveTo(I, 0); + LineTo(PatBitmap.Width, PatBitmap.Height - I); + end + else begin + MoveTo(0, I - PatBitmap.Width - 1); + LineTo(PatBitmap.Width - (I - PatBitmap.Width) + 1, + PatBitmap.Height); + end; + if Even then + Inc(I, 1) + else + Inc(I, 3); + Even := not Even; + end; + end; + end; + end; + + //The actual background bitmap, its width and height are increased to compensate + //for scrolling distance + BkBitmap.Width := ARect.Left mod PatBitmap.Width + ARect.Right - ARect.Left; + if IgnoreScrollPos then + ScrollPos := 0 + else + ScrollPos := (ARect.Top + ScrollPos) mod PatBitmap.Height; + BkBitmap.Height := ScrollPos + ARect.Bottom - ARect.Top; + + //Now repeat the pattern bitmap onto the background bitmap + with BkBitmap.Canvas do begin + Y := 0; + while Y < BkBitmap.Height do begin + X := 0; + while X < BkBitmap.Width do begin + Draw(X, Y, PatBitmap); + Inc(X, PatBitmap.Width); + end; + Inc(Y, PatBitmap.Height); + end; + end; + + //And finally, draw the background bitmap to the canvas + BitBlt(Canvas.Handle, ARect.Left, ARect.Top, ARect.Right - ARect.Left, + ARect.Bottom - ARect.Top, BkBitmap.Canvas.Handle, ARect.Left mod + PatBitmap.Width, ScrollPos, SRCCOPY); + finally + BkBitmap.Free; + PatBitmap.Free; + end; +end; + +//Method for getting color values + +procedure TPngImageListEditorDlg.GetColorProc(const S: string); +begin + cmbBackgroundColor.Items.Add(S); +end; + +//Parse a background color name or code + +procedure TPngImageListEditorDlg.ParseBackgroundColor(Sender: TObject; CanDisplayError, CanChangeText: Boolean); +var + S: string; + I, ParsedColor: Integer; +begin + with cmbBackgroundColor do begin + //First, see if its a known color name + if IdentToColor(Text, ParsedColor) then begin + ItemIndex := Items.IndexOf(Text); + pnlBackgroundColor.Color := ParsedColor; + end + else begin + S := Text; + //Replace # with $ so StringToColor recognizes it + if (Length(S) > 0) and (S[1] = '#') then + S[1] := '$'; + try + //Try to convert to a real color value + ParsedColor := StringToColor(S); + if CanChangeText then begin + //And try to convert back to an identifier (i.e. if you type in $000000, it'll become clBlack) + if ColorToIdent(ParsedColor, S) then + ItemIndex := Items.IndexOf(S) + else + Text := S; + end; + pnlBackgroundColor.Color := ParsedColor; + except + //If it fails, display a message if neccesary + on EConvertError do + if CanDisplayError then begin + MessageBox(Self.Handle, + PChar(Format(SIsNotAValidColorValue, [Text])), + PChar(Self.Caption), MB_ICONERROR or MB_OK); + SetFocus; + end; + end; + end; + end; + //And finally, set the background color to every selected image + if (Sender <> lbxImages) then + for I := 0 to lbxImages.Items.Count - 1 do + if lbxImages.Selected[I] then + Images.Items[I].Background := pnlBackgroundColor.Color; +end; + +procedure TPngImageListEditorDlg.SelectBackgroundColor(Sender: TObject; Color: TColor); +var + S: string; +begin + //This happens after a background color has been slected from the color dialog + //Try to convert a color into an identifier, or else into a hexadecimal representation + if ColorToIdent(Color, S) then + cmbBackgroundColor.ItemIndex := cmbBackgroundColor.Items.IndexOf(S) + else + cmbBackgroundColor.Text := '$' + IntToHex(dlgColor.Color, 6); + ParseBackgroundColor(Sender, False, True); +end; + +procedure TPngImageListEditorDlg.btnAddClick(Sender: TObject); +var + Png: TPngImageCollectionItem; + I, Selected, FirstSelected: Integer; +begin + //The Add button is pressed, let the programmer look for an image + dlgOpenPicture.Options := dlgOpenPicture.Options + [ofAllowMultiSelect]; + if dlgOpenPicture.Execute then begin + for I := 0 to lbxImages.Items.Count - 1 do + lbxImages.Selected[I] := False; + FirstSelected := -1; + for I := 0 to dlgOpenPicture.Files.Count - 1 do begin + Png := Images.Items.Add; + with Png.PngImage do begin + //Load the image, but remove any gamma, so that the gamma won't be reapplied + //when loading the image from the DFM + LoadFromFile(dlgOpenPicture.Files[I]); + if Png.PngImage.Header.ColorType in [COLOR_RGB, COLOR_RGBALPHA, + COLOR_PALETTE] then + Chunks.RemoveChunk(Chunks.ItemFromClass(TChunkgAMA)); + end; + //Does the image conform the specified dimensions, if any? + if ConformDimensions(Png.PngImage) then begin + //Update maximum image width + if FMaxWidth < Png.PngImage.Width then + FMaxWidth := Png.PngImage.Width; + + //Invent a name for the image, and initialize its background color + if chkUseFilenames.Checked then + Png.Name := ChangeFileExt(ExtractFileName(dlgOpenPicture.Files[I]), '') + else + Png.Name := 'PngImage' + IntToStr(Images.Items.Count - 1); // do not localize + Png.Background := clWindow; + + //Finally, add it and select it + Selected := lbxImages.Items.AddObject(Png.Name, Png); + lbxImages.Selected[Selected] := True; + if FirstSelected = -1 then + FirstSelected := Selected; + end + else begin + //The image does not conform the specified dimensions + MessageBox(Handle, PChar(Format(SIncorrectSize, + [ExtractFilename(dlgOpenPicture.Files[I]), ImageWidth, ImageHeight, + Png.PngImage.Width, Png.PngImage.Height])), PChar(Caption), MB_ICONERROR or MB_OK); + Images.Items.Delete(Png.Index); + end; + end; + + //Focus the first selected (added) image + lbxImages.ItemIndex := FirstSelected; + lbxImages.SetFocus; + lbxImagesClick(nil); + end; +end; + +procedure TPngImageListEditorDlg.btnClearClick(Sender: TObject); +begin + //Clear the listbox and the collection + if (lbxImages.Items.Count > 0) and (MessageBox(Handle, + PChar(SThisWillClearTheEntireImageList), + PChar(Self.Caption), MB_ICONEXCLAMATION or MB_YESNO or MB_DEFBUTTON2) = + IDYES) then begin + lbxImages.Items.Clear; + Images.Items.Clear; + lbxImagesClick(nil); + end; +end; + +procedure TPngImageListEditorDlg.btnDeleteClick(Sender: TObject); + + function GetCommaList: string; + var + I: Integer; + S: TStringList; + begin + //Get a comma list of the names of the selected images in the form "name1, + //name2 and name3" + Result := ''; + S := TStringList.Create; + try + for I := 0 to lbxImages.Items.Count - 1 do + if lbxImages.Selected[I] then + S.Add(Images.Items[I].Name); + for I := 0 to S.Count - 1 do begin + Result := Result + S[I]; + if I < S.Count - 2 then + Result := Result + ', ' + else if I < S.Count - 1 then + Result := Result + SAnd; + end; + finally + S.Free; + end; + end; + +var + I, NewIndex: Integer; +begin + with lbxImages do + if (SelCount > 0) and (MessageBox(Handle, + PChar(Format(SAreYouSureYouWantToDelete, [GetCommaList])), + PChar(Self.Caption), MB_ICONEXCLAMATION or MB_YESNO) = IDYES) then begin + //Delete every selected image from the listbox and from the collection + NewIndex := -1; + I := 0; + while I < Items.Count do + if Selected[I] then begin + if NewIndex = -1 then + NewIndex := I; + lbxImages.Items.Delete(I); + Images.Items.Delete(I); + end + else + Inc(I); + + //Figure out the new selection index + if NewIndex > Items.Count - 1 then + NewIndex := Items.Count - 1 + else if (NewIndex = -1) and (Items.Count > 0) then + NewIndex := 0; + Selected[NewIndex] := True; + ItemIndex := NewIndex; + lbxImagesClick(nil); + end; +end; + +procedure TPngImageListEditorDlg.btnDownClick(Sender: TObject); +var + I: Integer; +begin + //Move the selected items one position down + with lbxImages do + if (SelCount > 0) and (LastSelected < Items.Count - 1) then + for I := Items.Count - 1 downto 0 do + if Selected[I] then begin + Images.Items[I].Index := I + 1; + Items.Exchange(I, I + 1); + Selected[I + 1] := True; + end; + lbxImagesClick(nil); +end; + +procedure TPngImageListEditorDlg.btnReplaceClick(Sender: TObject); +var + Item: TPngImageCollectionItem; + Index: Integer; + Png: TPngImage; +begin + //The Replace button is pressed, let the programmer look for an image + Index := FirstSelected; + Item := Images.Items[Index]; + dlgOpenPicture.FileName := Item.Name; + dlgOpenPicture.Options := dlgOpenPicture.Options - [ofAllowMultiSelect]; + with lbxImages do + if (SelCount = 1) and dlgOpenPicture.Execute then begin + Png := TPngImage.Create; + try + //First see if the image conforms the specified dimensions + Png.LoadFromFile(dlgOpenPicture.Filename); + if ConformDimensions(Png) then begin + //Then remove any gamma, so that the gamma won't be reapplied when loading the + //image from the DFM + if Png.Header.ColorType in [COLOR_RGB, COLOR_RGBALPHA] then + Png.Chunks.RemoveChunk(Png.Chunks.ItemFromClass(TChunkgAMA)); + Item.PngImage := Png; + + //Update the maximum image width + if FMaxWidth < Item.PngImage.Width then + FMaxWidth := Item.PngImage.Width; + + //Repaint and update everything, to be sure + lbxImages.Repaint; + lbxImagesClick(nil); + end + else + MessageBox(Handle, PChar(Format(SIncorrectSize, + [ExtractFilename(dlgOpenPicture.Filename), ImageWidth, ImageHeight, + Png.Width, Png.Height])), PChar(Caption), MB_ICONERROR or MB_OK); + finally + Png.Free; + end; + end; +end; + +procedure TPngImageListEditorDlg.btnUpClick(Sender: TObject); +var + I: Integer; +begin + //Move the selected items one position up + with lbxImages do + if (SelCount > 0) and (FirstSelected > 0) then + for I := 0 to Items.Count - 1 do + if Selected[I] then begin + Images.Items[I].Index := I - 1; + Items.Exchange(I, I - 1); + Selected[I - 1] := True; + end; + lbxImagesClick(nil); +end; + +procedure TPngImageListEditorDlg.cmbBackgroundColorChange(Sender: TObject); +begin + //While typing, try parsing the background color, but without any error messages + ParseBackgroundColor(Sender, False, False); +end; + +procedure TPngImageListEditorDlg.cmbBackgroundColorDblClick(Sender: TObject); +begin + //Just like in Delphi, when doubleclicking a color, the color dialog pops up + dlgColor.Color := pnlBackgroundColor.Color; + if dlgColor.Execute then + SelectBackgroundColor(Sender, dlgColor.Color); +end; + +procedure TPngImageListEditorDlg.cmbBackgroundColorExit(Sender: TObject); +begin + //When leaving the background combobox, parse the color, but this with error + //message, if neccesary + ParseBackgroundColor(Sender, True, True); +end; + +procedure TPngImageListEditorDlg.cmbPreviewBackgroundChange(Sender: TObject); +begin + //Pewview background is changes, repaint all items + lbxImages.Repaint; +end; + +procedure TPngImageListEditorDlg.cmbPreviewBackgroundDrawItem(Control: TWinControl; + Index: Integer; ARect: TRect; State: TOwnerDrawState); +var + IconWidth: Integer; +begin + with cmbPreviewBackground do begin + //Draw the background "icon" of the preview background combobox + IconWidth := (ARect.Bottom - ARect.Top) * 4 div 3; + DrawBackground(Canvas, Rect(ARect.Left, ARect.Top, ARect.Left + IconWidth, ARect.Bottom), + 0, Index, clNone, True); + Inc(ARect.Left, IconWidth); + + //Background color of the rest of the item + if odSelected in State then + Canvas.Brush.Color := clHighlight + else + Canvas.Brush.Color := clWindow; + Canvas.FillRect(ARect); + Inc(ARect.Left, 4); + + //And the text + DrawText(Canvas.Handle, PChar(Items[Index]), -1, ARect, DT_LEFT or DT_NOPREFIX + or DT_SINGLELINE or DT_VCENTER); + + Canvas.Brush.Color := clWindow; + end; +end; + +procedure TPngImageListEditorDlg.edtNameChange(Sender: TObject); +begin + //Update the selected image with the entered name, in realtime + with lbxImages do + if ItemIndex >= 0 then begin + Images.Items[ItemIndex].Name := edtName.Text; + Items[ItemIndex] := edtName.Text; + end; +end; + +procedure TPngImageListEditorDlg.FormClose(Sender: TObject; var Action: TCloseAction); +begin + Action := caFree; +end; + +procedure TPngImageListEditorDlg.FormCreate(Sender: TObject); +var + Space8H: Integer; +begin + //Initialize OfficeXP colors for selection + FSelectionBodyColor := Blend(clHighlight, clWindow, 30); + SetContrast(FSelectionBodyColor, Blend(clWindow, clBtnFace, 165), 50); + FSelectionBorderColor := clHighlight; + + //Initialize a value that keeps track of dragging + FDraggingIndex := -1; + + //Get all available color names + GetColorValues(GetColorProc); + + //Initialize the background to clWindow + cmbBackgroundColor.ItemIndex := cmbBackgroundColor.Items.IndexOf('clWindow'); // do not localize + cmbBackgroundColorChange(nil); + + //Do not specify image width and height by default (the imagelist will fill + //these up, so that you cannot select an image other than these dimensions) + ImageWidth := 0; + ImageHeight := 0; + + //Resize everything to make it fit on "large fonts" setting. Note that these + //operations are also needed on normal setting. + Space8H := lbxImages.Top; + Width := ResizeProportionalX(Width); + Height := ResizeProportionalY(Height); + Constraints.MinHeight := gbxProperties.Top + cmbBackgroundColor.Top + + cmbBackgroundColor.Height + Space8H + Space8H + gbxImageInfo.Height + Space8H + + (Height - pnlMain.Height); + Constraints.MinWidth := Width; + pnlButtons.Align := alBottom; + pnlMain.Align := alClient; + cmbPreviewBackground.ItemHeight := + ResizeProportionalY(cmbPreviewBackground.ItemHeight); + pnlBackgroundColor.Height := cmbBackgroundColor.Height; + + //Make sure the background color isn't reset when themes are enabled + pnlBackgroundColor.ParentBackground := True; + pnlBackgroundColor.ParentBackground := False; +end; + +procedure TPngImageListEditorDlg.FormResize(Sender: TObject); +begin + //There appears to be a bug that prevents a listbox from being redrawn correctly + //when the form is resized + lbxImages.Repaint; +end; + +procedure TPngImageListEditorDlg.FormShow(Sender: TObject); +var + I: Integer; +begin + //Initialize the maximum width of the images, to align text in the listbox + FMaxWidth := 0; + for I := 0 to Images.Items.Count - 1 do + if Images.Items[I].PngImage.Width > FMaxWidth then + FMaxWidth := Images.Items[I].PngImage.Width; + + //Fill the listbox with the images + for I := 0 to Images.Items.Count - 1 do + lbxImages.Items.AddObject(Images.Items[I].Name, Images.Items[I]); + if lbxImages.Items.Count > 0 then begin + lbxImages.Selected[0] := True; + lbxImages.ItemIndex := 0; + end; + lbxImages.SetFocus; + lbxImagesClick(nil); + + cmbPreviewBackground.ItemIndex := 0; + FormResize(nil); +end; + +procedure TPngImageListEditorDlg.lbxImagesClick(Sender: TObject); + + function GetDimensions(Png: TPngImage): string; + begin + //Return the formatted dimensions of an image + Result := Format('%dx%d', [Png.Width, Png.Height]); + if Png.InterlaceMethod <> imNone then + Result := Result + ' interlace'; + end; + + function GetColorDepth(Png: TPngImage): string; + begin + //Return the color depth, including whether the image is grayscale or paletted + case Png.Header.ColorType of + COLOR_GRAYSCALE, COLOR_GRAYSCALEALPHA: + Result := Format('%d-bits grayscale', [Png.Header.BitDepth]); + COLOR_RGB, COLOR_RGBALPHA: + Result := Format('%d-bits', [Png.Header.BitDepth * 3]); + COLOR_PALETTE: + Result := Format('%d-bits paletted', [Png.Header.BitDepth]); + end; + end; + + function GetTransparency(Png: TPngImage): string; + begin + //Return the formatted transparency depth, or transparency mode + if Png.Header.ColorType in [COLOR_GRAYSCALEALPHA, COLOR_RGBALPHA] then + Result := Format('%d-bits alpha', [Png.Header.BitDepth]) + else + case Png.TransparencyMode of + ptmBit: Result := 'bitmask'; + ptmPartial: Result := 'indexed'; + else + Result := 'none'; + end; + end; + + function GetCompression(Png: TPngImage): string; + begin + //Return the formatted compression level + Result := Format('level %d', [Png.CompressionLevel]); + end; + + function GetFiltering(Png: TPngImage): string; + begin + //Return the formatted filtering method + case Png.Header.FilterMethod of + FILTER_SUB: Result := 'sub'; + FILTER_UP: Result := 'up'; + FILTER_AVERAGE: Result := 'average'; + FILTER_PAETH: Result := 'paeth'; + else + Result := 'none'; + end; + end; + + function SameBackgroundColor: Boolean; + var + FirstBgColor: TColor; + I: Integer; + First: Boolean; + begin + //Determine whether the background color of all selected images is the same + FirstBgColor := clNone; + First := True; + Result := True; + for I := 0 to lbxImages.Items.Count - 1 do + if lbxImages.Selected[I] then + if First then begin + //Found the first selected and its background color + FirstBgColor := Images.Items[I].Background; + First := False; + end + else begin + //If not equal to first background color, then break, continue otherwise + Result := FirstBgColor = Images.Items[I].Background; + if not Result then + Break; + end; + end; + +const + NoneSelected = '[ none ]'; + MultipleSelected = '[ multiple ]'; +begin + with lbxImages do begin + //Refresh the enabled state of the buttons and controls + btnReplace.Enabled := SelCount = 1; + btnDelete.Enabled := SelCount > 0; + btnClear.Enabled := Items.Count > 0; + btnUp.Enabled := (SelCount > 0) and (FirstSelected > 0); + btnDown.Enabled := (SelCount > 0) and (LastSelected < Items.Count - 1); + lblName.Enabled := SelCount = 1; + edtName.Enabled := SelCount = 1; + lblBackgroundColor.Enabled := SelCount > 0; + cmbBackgroundColor.Enabled := SelCount > 0; + case SelCount of + 0: begin + //None is selected, so no information to display + lblDimensionsValue.Caption := NoneSelected; + lblColorDepthValue.Caption := NoneSelected; + lblTransparencyValue.Caption := NoneSelected; + lblCompressionValue.Caption := NoneSelected; + lblFilteringValue.Caption := NoneSelected; + end; + 1: with Images.Items[FirstSelected] do begin + edtName.OnChange := nil; + try + //One item is selected, display its properties and information + edtName.Text := Name; + SelectBackgroundColor(Sender, Background); + lblDimensionsValue.Caption := GetDimensions(PngImage); + lblColorDepthValue.Caption := GetColorDepth(PngImage); + lblTransparencyValue.Caption := GetTransparency(PngImage); + lblCompressionValue.Caption := GetCompression(PngImage); + lblFilteringValue.Caption := GetFiltering(PngImage); + finally + edtName.OnChange := edtNameChange; + end; + end; + else begin + //More than 1 is selected, so no image information can be displayed + if SameBackgroundColor then + SelectBackgroundColor(Sender, Images.Items[FirstSelected].Background) + else + SelectBackgroundColor(Sender, clNone); + lblDimensionsValue.Caption := MultipleSelected; + lblColorDepthValue.Caption := MultipleSelected; + lblTransparencyValue.Caption := MultipleSelected; + lblCompressionValue.Caption := MultipleSelected; + lblFilteringValue.Caption := MultipleSelected; + end; + end; + end; +end; + +procedure TPngImageListEditorDlg.lbxImagesDblClick(Sender: TObject); +begin + //Doubleclicking is the same as the Replace button + if lbxImages.SelCount = 1 then + btnReplaceClick(nil); +end; + +procedure TPngImageListEditorDlg.lbxImagesDragOver(Sender, Source: TObject; + X, Y: Integer; State: TDragState; var Accept: Boolean); + + procedure MoveItem(Index, Delta: Integer); + begin + //Move a single item up or down, depending on Delta + if lbxImages.Selected[Index] then begin + Images.Items[Index].Index := Index + Delta; + lbxImages.Items.Exchange(Index, Index + Delta); + lbxImages.Selected[Index + Delta] := True; + end; + end; + + function InRange(Index: Integer): Boolean; + begin + //Return whether Index exists in the listbox + Result := (Index >= 0) and (Index < lbxImages.Items.Count); + end; + +var + NewIndex, NewItemIndex, Delta, I: Integer; +begin + Accept := FDraggingIndex >= 0; + if Accept then begin + //Figure out to which index is dragged + NewIndex := lbxImages.ItemAtPos(Point(X, Y), False); + if NewIndex > lbxImages.Items.Count - 1 then + NewIndex := lbxImages.Items.Count - 1; + + //Figure out the distance (delta) of the drag + Delta := NewIndex - FDraggingIndex; + + //The destination index has to exist and has to be differend from where we + //started the drag. On to pof that, the drag destination of the first and + //last selected items have to be in range. + if (NewIndex >= 0) and (NewIndex <> FDraggingIndex) and InRange(FirstSelected + + Delta) and InRange(LastSelected + Delta) then begin + //Calc the new focus index + NewItemIndex := lbxImages.ItemIndex + Delta; + + //To prevent things to get messed up, moving downwards needs walking through the + //images in opposite direction + if Delta < 0 then + for I := 0 to lbxImages.Items.Count - 1 do + MoveItem(I, Delta) + else + for I := lbxImages.Items.Count - 1 downto 0 do + MoveItem(I, Delta); + + //Set the new focus index and tracking value of the drag + lbxImages.ItemIndex := NewItemIndex; + FDraggingIndex := NewIndex; + + lbxImagesClick(nil); + end; + end; +end; + +procedure TPngImageListEditorDlg.lbxImagesDrawItem(Control: TWinControl; Index: Integer; ARect: TRect; State: TOwnerDrawState); +var + DrawRect: TRect; + ScrollInfo: TScrollInfo; + I, ScrollPos: Integer; +begin + //Get the scrolling distance + ScrollPos := 0; + ScrollInfo.cbSize := SizeOf(ScrollInfo); + ScrollInfo.fMask := SIF_POS; + if GetScrollInfo(lbxImages.Handle, SB_VERT, ScrollInfo) then + for I := 0 to ScrollInfo.nPos - 1 do + with lbxImages.ItemRect(I) do + Inc(ScrollPos, Bottom - Top); + + //First, draw the background + if odSelected in State then + if lbxImages.Focused then + DrawBackground(lbxImages.Canvas, ARect, ScrollPos, + cmbPreviewBackground.ItemIndex, FSelectionBodyColor) + else + DrawBackground(lbxImages.Canvas, ARect, ScrollPos, + cmbPreviewBackground.ItemIndex, Blend(FSelectionBodyColor, clWindow, 50)) + else + DrawBackground(lbxImages.Canvas, ARect, ScrollPos, + cmbPreviewBackground.ItemIndex); + with lbxImages.Canvas do begin + //Then, draw a focus border, if focused + Brush.Style := bsClear; + if odFocused in State then begin + if lbxImages.Focused then + Pen.Color := FSelectionBorderColor + else + Pen.Color := Blend(FSelectionBorderColor, clWindow, 50); + Pen.Style := psSolid; + Rectangle(ARect); + end; + + //Draw the image at the center of (ARect.Left, ARect.Top, ARect.Left + FMaxWidth, ARect.Bottom) + with Images.Items[Index] do begin + DrawRect.Left := ARect.Left + (FMaxWidth - PngImage.Width) div 2 + 2; + DrawRect.Top := ARect.Top + (ARect.Bottom - ARect.Top - PngImage.Height) div 2; + DrawRect.Right := DrawRect.Left + PngImage.Width; + DrawRect.Bottom := DrawRect.Top + PngImage.Height; + PngImage.Draw(lbxImages.Canvas, DrawRect); + end; + + //Draw the image index number and the name + Font.Color := clWindowText; + DrawRect := Rect(ARect.Left + FMaxWidth + 8, ARect.Top, ARect.Left + + FMaxWidth + Canvas.TextWidth(IntToStr(lbxImages.Items.Count - 1)) + 8, + ARect.Bottom); + DrawText(Handle, PChar(IntToStr(Index)), -1, DrawRect, DT_RIGHT or + DT_NOPREFIX or DT_SINGLELINE or DT_VCENTER); + DrawRect.Left := DrawRect.Right; + DrawRect.Right := ARect.Right; + DrawText(Handle, PChar(' - ' + Images.Items[Index].Name), -1, DrawRect, + DT_END_ELLIPSIS or DT_LEFT or DT_NOPREFIX or DT_SINGLELINE or DT_VCENTER); + + //Draw the normal focusrect, so that it'll become invisible + if (odFocused in State) and lbxImages.Focused then + DrawFocusRect(ARect); + end; +end; + +procedure TPngImageListEditorDlg.lbxImagesEnter(Sender: TObject); +begin + //Just to be sure + lbxImages.Repaint; +end; + +procedure TPngImageListEditorDlg.lbxImagesExit(Sender: TObject); +begin + //Just to be sure + lbxImages.Repaint; +end; + +procedure TPngImageListEditorDlg.lbxImagesKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState); +begin + //I would expect this "ctrl"-navigation would work standardly, but appearantly + //it doesn't, so we'll have to code it ourselves + with lbxImages do + if ssCtrl in Shift then begin + case Key of + VK_DOWN: begin + if ItemIndex < Items.Count - 1 then + ItemIndex := ItemIndex + 1; + Key := 0; + end; + VK_UP: begin + if ItemIndex > 0 then + ItemIndex := ItemIndex - 1; + Key := 0; + end; + VK_SPACE: begin + Selected[ItemIndex] := not Selected[ItemIndex]; + lbxImagesClick(nil); + Key := 0; + end; + end; + end; +end; + +procedure TPngImageListEditorDlg.lbxImagesMeasureItem(Control: TWinControl; Index: Integer; var Height: Integer); +var + Temp: Integer; +begin + //Figure out the height of an item, when editing an image collection, the height + //of an image may differ + Height := Images.Items[Index].PngImage.Height + 4; + Temp := lbxImages.Canvas.TextHeight('0') + 4; + if Temp > Height then + Height := Temp; +end; + +procedure TPngImageListEditorDlg.lbxImagesMouseUp(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); +begin + //If the mouse button is released, the tracking value of the drag needs to be + //reset as well + FDraggingIndex := -1; +end; + +procedure TPngImageListEditorDlg.lbxImagesStartDrag(Sender: TObject; var DragObject: TDragObject); +var + Pos: TPoint; +begin + //Figure out where this drag start is + GetCursorPos(Pos); + FDraggingIndex := lbxImages.ItemAtPos(lbxImages.ScreenToClient(Pos), True); + if FDraggingIndex >= 0 then + lbxImages.ItemIndex := FDraggingIndex; +end; + +initialization + InitResolution; + +end. + diff --git a/internal/1.2.0/1/Docs/Changelog.txt b/internal/1.2.0/1/Docs/Changelog.txt new file mode 100644 index 0000000..c046216 --- /dev/null +++ b/internal/1.2.0/1/Docs/Changelog.txt @@ -0,0 +1,45 @@ +PngComponents 1.1: +- Common: "adopted" the project from Martijn Saly +- Common: added D2009 support (mostly changed PngObject to PngImage) +- Common: removed compatibility with versions below Delphi 7 +- Common: removed references to Thany.Inc (use RTLVersion instead) +- Common: cleaned up the code (mostly to use my formatting style) +- Editor: added "use file name" in PngImageListEditor (sets the name of the image to it's filename) + +PngComponents 1.0 RC3: +- Editor: Fixed "invalid header" exception when adding a PNG to the list. +- Editor: Everything should now look good on "large fonts" setting. +- PngBitBtn: Positioning and drawing of the glyph was sometimes a bit odd. +- PngBitBtn: Removed the need to draw an empty TBitmap glyph, prior to drawing the PNG glyph. +- PngSpeedButton: The image is now shifted down-right by 1 pixel, when the button is down but not pressed, to match the behavior of a normal SpeedButton. +- PngImageList: Fixed range check errors in PngToIcon32. +- PngImageList: Fixed possible AccessViolation in PngToIcon32. +- PngImageList: Fixed AccessViolation in AddImages. +- PngImageList: Fixed memory leak in CopyPngs. +- PngImageList: Added BeginUpdate and EndUpdate methods, to temporarily prevent the internal imagelist from being updated. +- PngImageList: The patched methods are more efficient, because they now manipulate the internal imagelist directly, rather than relying on CopyPngs. +- PngImageList: Added calls to Change in the patched methods. + +PngComponents 1.0 RC2: +- Editor: Fixed endless loop when repetitively removing the last image in a list of at least 3 (thanks to Aleksander Oven). +- Editor: Fixed possible out-of-bounds error when moving an image down using the Down button (thanks to Spiril). +- Editor: Now using Graphics.GetColorValues to retrieve available color identifiers (thanks to LJ and Ryan Mills). +- Editor: Rewritten ParseBackgroundColor and SelectBackgroundColor to use IdentToColor, StringToColor and ColorToIdent from Gaphics unit (thanks to LJ and Ryan Mills). +- Editor: It is now possible to set the background color to more than 1 selected image. +- Editor: Minor GUI fixes +- PngBitBtn: When Margin <> -1 and the button is focused, the image must be shifted 1 pixel, to match the behavior of a normal BitBtn. +- PngBitBtn: Fixed EPngHeaderNotPresent when assigning a nil to the PngImage property. +- PngBitBtn: PngImage property now behaves correctly when assigning an action. Note that the image will not be stored in the DFM if it came from a TActionList.ImageList (thanks to robvdl) +- PngSpeedButton: The same fixes that apply to PngBitBtn, applied to PngSpeedButton. +- PngImageList: Adding a default action to an imagelist no longer results in out of bounds errors (thanks to robvdl). +- PngImageList: 14 methods that couldn't be overridden are now patched (thanks to Vladimir Bochkarev). However, adding a default action to an imagelist still doesn't call the "new" Add method, but supposedly the legacy ImageList_Add() function, which cannot be patched. +- PngImageList: Fixed memory leak in CopyPngs (thanks to M. Youssfi). +- Common: Added Amount parameter to MakeImageBlended and MakeImageGrayscale. +- Common: Added function ConvertToPNG, which converts a TGraphic to a PNG object, if not already. +- Common: Added functions CreatePNG and CreatePNGMasked, which create a new PNG object based on a bitmap and a (color or bitmap) mask. +- Common: Added function CopyImageFromImageList, which effectively copies an image from a normal imagelist or a PngImageList into a PNG. +- Common: Added function SlicePNG for future use. This slices a large PNG object into smaller, equally-sized ones. +- Common: Added zlib version 1.2.2 to the PNG package (thanks to Vladimir Bochkarev). + +PngComponents 1.0 RC1: +- Initial public release \ No newline at end of file diff --git a/internal/1.2.0/1/Docs/License.txt b/internal/1.2.0/1/Docs/License.txt new file mode 100644 index 0000000..b279ad4 --- /dev/null +++ b/internal/1.2.0/1/Docs/License.txt @@ -0,0 +1,73 @@ +END-USER LICENSE AGREEMENT + +All files included in this archive are Copyright (C) 2002-2005 Martijn Saly. +Use and/or distribution of them requires acceptance of the following License +Agreement. + +-------------------------------------------------------------------------------- + +- "Author" herein refers to Martijn Saly (the creator of this package and + containing files and software). +- "Software" herein refers to all files bearing this notice, as well as any + other files and source code included with this package (typically extracted + from a .zip or .cab archive), and all content in them, regardless of whether + any modifications have been made. +- "Compile" herein refers to the automatic process of translating the Software's + source code into executable machine code by a compiler such as the one + included with Borland's Delphi or C++Builder. + +Except where otherwise noted, all of the documentation and Software included in +the this package is copyrighted by Martijn Saly (the Author). + +Copyright (C) 2002-2005 Martijn Saly. All rights reserved. + + +Use and distribution of the software is permitted provided that all of the +following terms are accepted. Terms 5 through 8 apply only to distributions +which include source code that one can Compile. + +1) The Software is provided "as-is," without any express or implied warranty. In + no event shall the Author be held liable for any damages arising from the use + or Compile of the Software. + +2) All redistributions of the Software's files must be in their original, + unmodified form. Distributions of modified versions of the files is not + permitted without express written permission of the Author. + +3) All redistributions of the Software's files must retain all copyright notices + and web site addresses that are currently in place, and must include this + list of conditions in its original, unmodified form. + +4) None of the Software's files may be redistributed for profit or as part of + another software package without express written permission of the Author. + +5) If applicable, you are permitted to Compile the Software, in orginal or + modified form, into any kind of application, including commercial or + shareware applications, or any application you are profiting from. + +6) If applicable, redistribution of any of the Software's files in object form + (including but not limited to .DCU and .OBJ formats) is strictly prohibited + without express written permission of the Author. + +7) If applicable, distribution of the Software in compiled package format + (the BPL file) is permitted, as long as the Software is distributed as part + of an application. + +8) If applicable, distribution of the Software in compiled package format + (the BPL file) is prohibed if the distribution does not specifically belong + to an application, written by the same author as the application was written + by. + +9) Full backward compatibility in future versions of the Software is not + guaranteed. In no event shall the Author be held liable for any inconvenience + or damages arising from lack of backward compatibility. + +If you do not agree to all of the above terms, you are not permitted to use or +Compile the Software in any way, and all copies of it must be deleted from your +system(s). + +---------------------------------------------------------------------------- + +Martijn Saly +martijn@thany.org +http://www.thany.org/ \ No newline at end of file diff --git a/internal/1.2.0/1/Docs/PngComponents.html b/internal/1.2.0/1/Docs/PngComponents.html new file mode 100644 index 0000000..1e3922c --- /dev/null +++ b/internal/1.2.0/1/Docs/PngComponents.html @@ -0,0 +1,105 @@ + + + + PngComponents + + + + +

PngComponents

+

This version: 1.0 RC2

+ +

What is PngComponents?

+

PngComponents is a set of components that allows you to include in your application real PNG files. PNG files on their own do not generate an enourmous advantage, but their support for an alpha-channel does indeed have quite a charm to it. The PngComponents library supports alpha-channels to their full extend, using a modified version of the excellent pngdelphi library.

+
+
+ Windows XP computer icon + Windows XP remote computer icon + Windows XP closed folder icon + Windows XP open folder icon +
+
Examples of PNG images with alpha-channels.
Note that these don't work correctly in Internet Explorer (all versions up to 6).
+
+
+

PngComponents' main and most important component is the PngImageList. This is a descendant of the normal TImageList, with in addition full support for PNGs with an alpha-channel. This will enable you to keep using most components that take advantage of imagelists, while actually feeding them icons with alphablending capabilities. Two other very nice components are the PngSpeedButton and the PngBitBtn. These two buttons do not have a Glyph anymore, but in stead, they accept a PNG file to be assigned directly to the button, without the need for an imagelist (just like the normal SpeedButton and BitBtn). And since the PNG glyphs are drawn in realtime, there's no more hassling with WM_DISPLAYCHANGE when the user changes the clBtnFace color in his display settings...

+

Two other components included in the library are the PngImageCollection, which is simply a collection of PNG images. Nothing more, nothing less. The last one is the PngCheckListBox. This one accepts PNG glyphs for the check states. Beside that, it's a completely normal CheckListBox.

+

I've also added a "fix" for Alex Desinov's awesome addon for Jordan Russell's Toolbar2000, called TBX. This fix is a replacement for the OfficeXP theme. Just replace TBXOfficeXPTheme in your uses clause with PngTBXOfficeXPTheme and that's it! Beautiful alphablended icons become possible in the OfficeXP theme as well.

+ +

Why should I use PngComponents?

+

The PngComponents library offers a major leap forward in creating nice GUI's in designtime. Not only does it speed up the implementation of alphablended icons in your application, it eases the way you can use them throughout your software. No longer do you need to put them in a resource file manually and then manually drawing them on a temporary bitmap and assigning that to somewhere. Adding beautiful alphablended icons to your interface is but a few clicks away.

+ +

Usage

+ +

Common

+

The PngBitBtn and PngSpeedButton both have two extra properties, PngImage and PngOptions. PngImage substitutes the Glyph property with a PNG image, so only PNG files can be loaded into it. PngOptions determines what a disabled glyph looks like. You can choose from a combination of having it blended and having it grayscaled.

+

The PngImageList and PngImageCollection share the same editor. This editor can be used to load PNG files into the respective component. When editing a PngImageList, the editor will only allow PNG files that have the correct dimensions. When editing a PngImageCollection, any PNG can be added. Note that in either case, it doesn't matter if you mix color depths or other properties.

+

Note: the beta versions of PngComponents required that you use a PngImageCollection and assign it to the PngImageList.PngImages property. That is no longer the case, i.o.w. the components have been separated completely.

+ +

The editor

+

As said before, the PngImageList and PngImageCollection share an editor that allows to modify the contents of the respective component:

+
    +
  • The Add button will ask for a PNG image. After that, you may set its name and background color. Note that you can select multiple files and add them all at once.
  • +
  • The Delete button deletes the currently selected image(s), after having asked for confirmation.
  • +
  • The Replace button only works when a single image is selected. It will ask for a PNG file and will replace the actual image.
  • +
  • The Clear button empties the list, after having asked for confirmation.
  • +
  • The Up button moves the currently selected images one position up, if possible.
  • +
  • The Down button moves the currently selected images one position down, if possible.
  • +
  • You can also drag images in the listbox. They'll be moved as you drag them, in realtime.
  • +
  • Remember that you can select multiple images, for your convenience.
  • +
+

The editor will show up when you doubleclick the PngImageList or PngImageCollection component. You may also select Edit images... from its context menu, or doubleclick the PngImageList.PngImages or PngImageCollection.Items property.

+ +

The ImageList

+

The ImageList has some features and issues you should probably know about:

+
    +
  • The images you add to the list are internally pumped into the "real" imagelist, so that native "API" windows controls, like listviews and treeviews, can take advantage of it. Even though PngImageList tries to make the best out of it, Windows 2000 and earlier simply do not support an alpha channel in an icon and may therefor display it incorrectly. This also applies on Windows XP and later, if you forget to add a manifest to your application. Note that themes support is not required for this to work, just a manifest is enough (themes may even be unavailable).
  • +
  • The editor will not crop or resize images that do not conform the dimensions of the imagelist. Unfortunately, this is extremely hard when working with PNG images, due to limitations in the pngdelphi library.
  • +
  • Components that do not natively support the PngImageList will not draw disabled images correctly. Those components usually have their own algorithm to generate disabled images, which will not work with the modern-style flashy colorful alpha-blended PNG images. You may want to include another imagelist with the same images, but with the EnabledImages property set to False.
  • +
+ +

The OfficeXP fix

+

A small introduction: Jordan Russell's Toolbar2000 is a set of components for creating Office 2000-style toolbars and such. Alex Desinov's TBX is an add-on package that adds even more functionality as well as theming. This allows for themes like "OfficeXP", "Office2003" and more.

+

The OfficeXP theme comes standard with TBX and it's the one getting in major trouble when using in combination with PngComponents. The alpha-blended area's look ugly, images may show dark borders, and other kinds of artefacts may show up.

+

The fix I've included is as simple as it is effective; it's a unit called PngTBXOfficeXPTheme. If you replace TBXOfficeXPTheme in your uses clauses with PngTBXOfficeXPTheme, you should be all set! You will not have the fancy looks in designtime, but in runtime your application will look better than ever.

+

Warning! If you still need TBXOfficeXPTheme included in your uses clause, then make sure PngTBXOfficeXPTheme gets initialized after TBXOfficeXPTheme, or it will not work as expected.

+ +

Miscellaneous

+

Feedback

+

I love to get feedback! You can either go to the newsgroup or send me an e-mail if you have a specific question.

+

Legal

+

See the License.txt file included in the archive. If the file is not there, the ZIP file is not a genuine PngComponents download!

+ +
+
This page is best viewed with Opera or Firefox. This page is also optmized for printing.Valid CSS 2.0! Valid XHTML 1.0 Transitional!
+ + \ No newline at end of file diff --git a/internal/1.2.0/1/Docs/pngimage.chm b/internal/1.2.0/1/Docs/pngimage.chm new file mode 100644 index 0000000000000000000000000000000000000000..c7e51b2ee777f09c80d7b41eb0162d4fbbab0e11 GIT binary patch literal 162254 zcmeFZbyQrH=Wcb5RcA-GGB5ZqmZ(?H`+W5M0sgGB3Q^A_t+=RA9t>|MK_s#DM{t)?mg4FCWPAr}0YD; zxsdKLi2l9CJ$464_t1U1zrV*2A$_upf1<}s{tYwp;-OFXW$)#Gl9Ifn9RFi`e=sN( zh!O$|rL@>MC*&eW=uE#U$^CM>P>SsMH|RFjiz1DhX**u!TI(!WJs= z7U)0ajmSc!C?X@RpsEIyxFL~5gv&yusVVH_WM^yv1Y5X(^>_v9|`X{Vp9fL|er0561q0ov42B`3K|pjYYpxNyJBGF$Dp^&W@mm`l1^x zDhyCqOf9UzpvNX6^Z63hkXS5iO+aqH%Ry`?!a;!mPGF$*gXf~xrP3kYc!bz~dnv9% z>451UjQuwjU*lCy^bf}Ifc+%!^OgPw=i=wU!=g!IE2Xl!9?_Pg!y8|DO2 z6c%d>W00*A=rF^>456v2Q1!CfD^(~J`=fX!lSXJ=#y z@v1%0$@p>DBO1k{46#@oL1q?Ckk)<=;qRKmB5>lUkXgY0L4tzCBXlqy5ulTkg_-Sd z&7kk-;a-1mV@HTbANm$Fhmx&{{-|#P1Op$mV4xEZ#ioXIO@-|Is%C+C1oo zynh{Gi1Vm_k3z0LqJ|eyY=0Uy2Lb;WA5`=z-2P8R7Lb;IHyj#863+b(3bHl%jRqIN zh7tUOnwvbhFSznqI1m0~qZSYp60Rm7d$9RKnI^R?dV;^C#&*_rkm+gvU`OzzcbYue ze-Yc*Lt@Oy!p_zP1eu19Eg#B8a1#Bc_7Hb}YuxxmyukfS!yNQ`8s1OhkT9M|7?Qta ze}V<{R|O$S{1MOo`0m~eR|}Iz8$xnkM*=YZl>aBZgQ{7=Rh~Y=)^

Q%5@+Cop7C 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

u&*W}UvwrT9YO_5KgZ+J6=(;={U9Si}2 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 z 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 literal 0 HcmV?d00001 diff --git a/internal/1.2.0/1/Example Images/Computer_32.png b/internal/1.2.0/1/Example Images/Computer_32.png new file mode 100644 index 0000000000000000000000000000000000000000..a9b6ac5e592fa12975a4aabcbb22c4a60ce438b2 GIT binary patch literal 744 zcmVP)mX%R&E0x?Y( z8I@^oW|XN}HjXnoFZa&e_uFC$YV5Z=aL&VXI7jfGT)%!R;W%PA)zx!UX^OQ2ldgVyx zHQD^p?VftGLdNA5AO-6_;vt#l6c(-{e2y0BRVQ-e@Ax=)h)r0yc^FxV<+ z&!U5)qs2rLCjvzms#UOEsF+Z-ArOs+g)ds7Aa6DTa=FTMbHW{6H9-UE(8b|@MKk|s`oMuXc|@1zHZ zhsn2hV%QK4)J;6UZlhTc+?8qp;tCNDXqDpB^r(8BzT>J{ap<|;5 z%v$Z{_F8uC&nL=%508yKzj)@%{%gHmD*gSYtsH%)*S-7rCJT5UX&`u-*k_6!WUh5Pu`+45(%laHwAsWV;0rb3rXa#}F5Q zG#jU#0WxQy8JotiuUnPj@87>*409QX9nky|$=2^sMv(BNILG|dIo%t?X)Aiul>0J0(H2M09nfdBvi07*qoM6N<$f^F`n AfB*mh literal 0 HcmV?d00001 diff --git a/internal/1.2.0/1/Example Images/FolderOpen_32.png b/internal/1.2.0/1/Example Images/FolderOpen_32.png new file mode 100644 index 0000000000000000000000000000000000000000..370b5c4ab4ca6913ca1d6bb799f9636ad88535c4 GIT binary patch literal 424 zcmV;Z0ayNsP)^G23=BWs<8}Ir?>`ux zA3n;!_2Ube4-NxP4qgThF)0QO_gJ8JUf|aK2N=|s_W=X(8Ym{_07dSAUGN=fnxc*s zMA47$cnx?D3>r`@K*0sD0gOyc4E)l{3=B8U<8?j=JbeC)f#b(#5EJBw7a*gQmlpBd zA*d4xME89GJ0FPGfDGUUVgn!sB@787%>V_|5e7&y2Lq5HKtC|(6N#0fdKdudvVA)m S=H2N40000P_zKOk8VjpZUW4@V%K&zW?BbzTV`h;`WW#YK>=M3kb0~K-GZ_PotjCoJC+iX)9+gRbKrs+ znxxCUNWQ*}*Yz&_ih}z11d+Zd!ViWIDmt_+Xmr4k-6$@fR}%7otEINWyS1~}o+|{r zI{W%0@wkg%*g-Ww0t^dWGMElDJD?g6Og$MASAOb|jar?~?l3#)pV`a|vsXOB-2G*` zOpB@xB@GHq$TtqVtiiqkZA+GrNXoSJ8S;6^syLZv5ydPwH)jc&CY2Txj|6+o!!Bxv z5_#mQu!IzlqbH)Dg`AF|G zZf`jovkQ4s3RE-eYB_T&A96Iq86A(dy?)+^>P%E0qAzZfxlv%{w{N$y_tU=%#Iyp? zV#hiz!Z}edEhuVfd9bJJ#@p|le`3rljhyqV_{v4i6r_I9>Kk + + {F25C3775-B8A8-4DEE-B53F-72E25C9DD51E} + PngComponents.dpk + Debug + DCC32 + + + true + + + true + Base + true + + + true + Base + true + + + C:\Documents and Settings\All Users\Documentos\RAD Studio\6.0\Bpl\PngComponents120.bpl + false + Png Components + true + 120 + true + true + false + 0 + 00400000 + x86 + + + false + RELEASE;$(DCC_Define) + 0 + false + + + DEBUG;$(DCC_Define) + + + + MainSource + + + + + + + + + + + + + Base + + + Cfg_2 + Base + + + Cfg_1 + Base + + + + + Delphi.Personality.12 + Package + + + + PngComponents.dpk + + + False + True + False + + + True + False + 1 + 0 + 0 + 0 + False + False + False + False + False + 3082 + 1252 + + + + + 1.0.0.0 + + + + + + 1.0.0.0 + + + + Microsoft Office 2000 Sample Automation Server Wrapper Components + Microsoft Office XP Sample Automation Server Wrapper Components + + + + 12 + + diff --git a/internal/1.2.0/1/Packages/PngComponents.res b/internal/1.2.0/1/Packages/PngComponents.res new file mode 100644 index 0000000000000000000000000000000000000000..1f003440932c578f202c4f6c27bad5636a4455b5 GIT binary patch literal 5164 zcmbW5&ud&&6vt26KwY(22tqd#M5JUPsTABuM`--{hV{pn>W)*Onh+W+#lzj@ArG|eRqa2Gh3H+U6`74&o65^ ze^D_jKDV}ZX*Gkcsj)8mNVeiFHMHjcK9g!SChfM1zG6>$5@S;Gk|((|Rc$dI zwSX7c)M1W;#vC8)x-mNv_EBG zKa_UqMn4>;^2)dPkRJn^8uxWpJ2|*l-{Z)qJYIiaL;W{;9%%GEQVkl#!ohhQy{?~{ zlGAk%Pd?8%tAk@|ZX*8V>pE$wh!Y3ah|AENYpdET9^DPNOY}$Hz+)eSL)6vhYA|KR zho;~#smne~tK+4o{({-K*1)jc+P7?1rc*p;-5Ygy!N&{e68pQ^Sa#f?>G z8GB-yYg*P4BUAnf{WjKv4+fe;cVnGmvLE=$UCV^K|NFkjqra&e?^AE9wGYHpU?&HB z!JWev2l|>ze6*4q?>yR~otzq*RH55r+8BcaefHn6r@|h=Q@)ZPu`cvmJ=6}qjJcXU zk36q_`#CtY!NK3zT6ttvfv+=m(Dj(~;p+HP#SmM`kHe^s>sLP4JB5SVt*|kz&)RoK z+OPJ|k^`K;3~cfie8q9@!Q>o7n;I9MBl)q`Rlxy`VEFzgZd*9$d@|=X?K*>lxAlH7 zP7R#{*w`rc-!a7jU|^nl^olpoxPZ)&HFc3`?3#l?zq3;7`e!Y ze&2t!(d%`plwWbod(Jknd|qqwZe%Xs2io4Rm*dBoMt9je@=Jf>d+vfC*fHPK<@_pd z)L+~*mRNXxBjD4>xmW|=gK4?n&`|KB{_1OQ&3H$%Hu0|Y`vbSJ;`ZGTQ11>{9k4=qd_blxh2e1|&#;|4YLULk{i1B-7oOm-I-+Ki|=OKSbrqA>4 zITi`1&p4KNC;FrKF5zsTk-Bjw(ubp;C5;b%%lZD78Z3eChk6d2G0xgqOtFrsGs*7< z3@-kA*nQN5+-G@`!)fQ?HD2)Tc^s5?5)S9XPJYP&@7m5#2ajt@Eu@>h$vm0&ygt|C zsmG~Y4i0>txLkK$yp!TH-&y@hc^1dJeX~x3f6M-oy^xQbw|}vF)66zyU3b|&vybhreJ;CY_vG^#{;$Em8TvnCeck`n;9rmx zJHBB44@cLnDbI>88?HINa6@BT_N7(&{KURc>#ieIj(10Go?lo0{D*uOWIXA|-ZNX3 zkC`$ccT?D=e7pAC9@&mPv^(;T?SV4y*thmnvsXQ4({4!V2eKRD0He2+ZADt2+7o+b z+lv2Ds<+j9KvI9U>@CG)&fA*#!M=8^XTp4>wL2bn-?7*GY>YpU?J9mbu`o&6KSKL+C6}5p?>`ExP?QYBUCHvXQF?+{PT~uO6`X4KD LxbK%%|5*JOxvY^K literal 0 HcmV?d00001 diff --git a/internal/1.2.0/1/Packages/PngComponentsDesign.dpk b/internal/1.2.0/1/Packages/PngComponentsDesign.dpk new file mode 100644 index 0000000..abdd0b7 --- /dev/null +++ b/internal/1.2.0/1/Packages/PngComponentsDesign.dpk @@ -0,0 +1,41 @@ +package PngComponentsDesign; + +{$R *.res} +{$R '..\Design\PngComponents.dcr'} +{$ALIGN 8} +{$ASSERTIONS ON} +{$BOOLEVAL OFF} +{$DEBUGINFO OFF} +{$EXTENDEDSYNTAX ON} +{$IMPORTEDDATA ON} +{$IOCHECKS ON} +{$LOCALSYMBOLS OFF} +{$LONGSTRINGS ON} +{$OPENSTRINGS ON} +{$OPTIMIZATION ON} +{$OVERFLOWCHECKS OFF} +{$RANGECHECKS OFF} +{$REFERENCEINFO OFF} +{$SAFEDIVIDE OFF} +{$STACKFRAMES OFF} +{$TYPEDADDRESS OFF} +{$VARSTRINGCHECKS ON} +{$WRITEABLECONST OFF} +{$MINENUMSIZE 1} +{$IMAGEBASE $400000} +{$DESCRIPTION 'Png components designtime'} +{$LIBSUFFIX '120'} +{$DESIGNONLY} +{$IMPLICITBUILD ON} +{$DEFINE RELEASE} + +requires + designide, + PngComponents; + +contains + PngComponentsRegister in '..\Design\PngComponentsRegister.pas', + PngComponentEditors in '..\Design\PngComponentEditors.pas', + PngImageListEditor in '..\Design\PngImageListEditor.pas' {PngImageListEditorDlg}; + +end. diff --git a/internal/1.2.0/1/Packages/PngComponentsDesign.res b/internal/1.2.0/1/Packages/PngComponentsDesign.res new file mode 100644 index 0000000000000000000000000000000000000000..260785bbbacdc1a583cc1dfa30779e58db57751d GIT binary patch literal 5196 zcmbW5KW`mX5XHyXQmBZFR8Tw%Ar!el4vK_C!GZ`8k$^-bFJ)E{gbS*pvE7;Yjz~;qvW8ra;|#7!P?nSYp<9J^QiSbJMR41_1~WJK%?)GYS1bc4$kA~Mg7#2 zoUVg-@_Ejo4vwk0srZwx@1?0GP8?VxE@N}9oocUmbhqHH&>wjNk9`adQCFX9z?2mq znu5c$Df=v~j+dVL)6RbJHX6(Nhi+=r%(2nKc-}Jy z8afBCu}SQ|V~RVRXv5WOAS^$N;ufC%ac$LJ>%ie1o?|Ot>}k=T9I8P-H8UWfI~g%vPUywRR0F8g@f9OAAYrd zufK9RX3gG)ne;Q4caGOcb8+tFg`N62`>{V-3%(4@H0EjZ{w>tL>_eP8?k_k-F7lz@ z_g`)FdYx+JR~+-6vkNSr*V?=rnalTqw)dOW_;IGuUG|Rr(x3RAyWj_Q%(qQBzsei+ z7dMS17M|Y-_%w1Z*TDB+R_-@66#S^a`r2DF-qEa0yleCQfm@|Gt@Ztp_w!hncTybk ze>-cI@x8CR&i{8L#$>qv{QRj;O)&Uze~}AaXm@VXP7PCQ-V5;?YN*3Xe4T~3*U&FL z!XbZXjPrv&egpBI`?&htQ}eSaUc`XU9mxMGawQ)X(c7$D#o-10oX;ceSNT6cJMS7l z6XNLSUbuO7!Seg2;N}?wnSY|}XMO?(T*iJ8n;H-IEbV~cSU2`=|-IPx2&(mz{?fc)@qhHgv=E=OL^|>BT zJzmP?@X+Up%XO#4J1#!+ozx$fXL-CoFzYq=x9l(3bJ;W5L9u;#?6l9mK09CsX6x89 zvop$lRu~guRl@B1gZ2KLneE8>{x$pDKC&zJh3sRyDxc5zy9Qq~^gUy1%fD*y6-3`Y z*3G|g^!=vtsIO;X&H6=++_dXf>+dJ_rCL`Up?18>YV-WM@#jC}dxe~O(pTOy+mMf$ zG9Y*B724Nr&mP-7+qJuPS^mD=QRZFy#vW?+eUI6(i&FZY?4mfp=uKr?lh%j!z#iFc z#s4VPx7E8tQh#pQ8;Z%Cmo)ReedSn>gn3VEcRlW!V{gr~F@8t3r}!<4b@#+>SG^lr zml!+t>L~wBt$C~!L*5Jaj=d|}aWnhW&M6*kdmg(hzV}D0gGXu_vlw$Qds|u7>@(%K z>ls+_NcySbUHewqZ*zeUfhtqjKL5u5`D||t5ue-*m84P3BLe(XAH(hHg8BUhjTYf5| SD!Z!1eMOGX#hHyiHvR?bPnD+t literal 0 HcmV?d00001 diff --git a/internal/1.2.0/1/Source/PngBitBtn.pas b/internal/1.2.0/1/Source/PngBitBtn.pas new file mode 100644 index 0000000..60faf44 --- /dev/null +++ b/internal/1.2.0/1/Source/PngBitBtn.pas @@ -0,0 +1,240 @@ +unit PngBitBtn; + +interface + +uses + Windows, Messages, Classes, Graphics, Controls, Buttons, pngimage, PngFunctions; + +type + TPngBitBtn = class(TBitBtn) + private + FPngImage: TPngImage; + FPngOptions: TPngOptions; + FCanvas: TCanvas; + FLastKind: TBitBtnKind; + FImageFromAction: Boolean; + FMouseInControl: Boolean; + IsFocused: Boolean; + function PngImageStored: Boolean; + procedure SetPngImage(const Value: TPngImage); + procedure SetPngOptions(const Value: TPngOptions); + procedure CNDrawItem(var Message: TWMDrawItem); message CN_DRAWITEM; + procedure CMMouseEnter(var Message: TMessage); message CM_MOUSEENTER; + procedure CMMouseLeave(var Message: TMessage); message CM_MOUSELEAVE; + protected + procedure ActionChange(Sender: TObject; CheckDefaults: Boolean); override; + procedure SetButtonStyle(ADefault: Boolean); override; + public + constructor Create(AOwner: TComponent); override; + destructor Destroy; override; + published + property PngImage: TPngImage read FPngImage write SetPngImage stored PngImageStored; + property PngOptions: TPngOptions read FPngOptions write SetPngOptions default [pngBlendOnDisabled]; + property Glyph stored False; + property NumGlyphs stored False; + end; + +implementation + +uses + ActnList, Themes, PngButtonFunctions; + +{ TPngBitBtn } + +constructor TPngBitBtn.Create(AOwner: TComponent); +begin + inherited Create(AOwner); + FPngImage := TPngImage.Create; + FPngOptions := [pngBlendOnDisabled]; + FCanvas := TCanvas.Create; + FLastKind := bkCustom; + FImageFromAction := False; +end; + +destructor TPngBitBtn.Destroy; +begin + FPngImage.Free; + FCanvas.Free; + inherited Destroy; +end; + +procedure TPngBitBtn.ActionChange(Sender: TObject; CheckDefaults: Boolean); +begin + inherited ActionChange(Sender, CheckDefaults); + if Sender is TCustomAction then begin + with TCustomAction(Sender) do begin + //Copy image from action's imagelist + if (PngImage.Empty or FImageFromAction) and (ActionList <> nil) and + (ActionList.Images <> nil) and (ImageIndex >= 0) and (ImageIndex < + ActionList.Images.Count) then begin + CopyImageFromImageList(FPngImage, ActionList.Images, ImageIndex); + FImageFromAction := True; + end; + end; + end; +end; + +procedure TPngBitBtn.SetButtonStyle(ADefault: Boolean); +begin + inherited SetButtonStyle(ADefault); + if ADefault <> IsFocused then begin + IsFocused := ADefault; + Refresh; + end; +end; + +function TPngBitBtn.PngImageStored: Boolean; +begin + Result := not FImageFromAction; +end; + +procedure TPngBitBtn.SetPngImage(const Value: TPngImage); +begin + //This is all neccesary, because you can't assign a nil to a TPngImage + if Value = nil then begin + FPngImage.Free; + FPngImage := TPngImage.Create; + end + else begin + FPngImage.Assign(Value); + end; + + //To work around the gamma-problem + with FPngImage do + if not Empty and (Header.ColorType in [COLOR_RGB, COLOR_RGBALPHA, COLOR_PALETTE]) then + Chunks.RemoveChunk(Chunks.ItemFromClass(TChunkgAMA)); + + FImageFromAction := False; + Repaint; +end; + +procedure TPngBitBtn.SetPngOptions(const Value: TPngOptions); +begin + if FPngOptions <> Value then begin + FPngOptions := Value; + Repaint; + end; +end; + +procedure TPngBitBtn.CNDrawItem(var Message: TWMDrawItem); +var + R, PaintRect: TRect; + GlyphPos, TextPos: TPoint; + IsDown, IsDefault: Boolean; + Flags: Cardinal; + Button: TThemedButton; + Details: TThemedElementDetails; +begin + R := ClientRect; + FCanvas.Handle := Message.DrawItemStruct^.hDC; + FCanvas.Font := Self.Font; + IsDown := Message.DrawItemStruct^.itemState and ODS_SELECTED <> 0; + IsDefault := Message.DrawItemStruct^.itemState and ODS_FOCUS <> 0; + + //Draw the border + if ThemeServices.ThemesEnabled then begin + //Themed border + if not Enabled then + Button := tbPushButtonDisabled + else if IsDown then + Button := tbPushButtonPressed + else if FMouseInControl then + Button := tbPushButtonHot + else if IsFocused or IsDefault then + Button := tbPushButtonDefaulted + else + Button := tbPushButtonNormal; + + //Paint the background, border, and finally get the inner rect + Details := ThemeServices.GetElementDetails(Button); + ThemeServices.DrawParentBackground(Handle, Message.DrawItemStruct.hDC, @Details, True); + ThemeServices.DrawElement(Message.DrawItemStruct.hDC, Details, Message.DrawItemStruct.rcItem); + R := ThemeServices.ContentRect(FCanvas.Handle, Details, Message.DrawItemStruct.rcItem); + end + else begin + //Draw the outer border, when focused + if IsFocused or IsDefault then begin + FCanvas.Pen.Color := clWindowFrame; + FCanvas.Pen.Width := 1; + FCanvas.Brush.Style := bsClear; + FCanvas.Rectangle(R.Left, R.Top, R.Right, R.Bottom); + InflateRect(R, -1, -1); + end; + //Draw the inner border + if IsDown then begin + FCanvas.Pen.Color := clBtnShadow; + FCanvas.Pen.Width := 1; + FCanvas.Brush.Color := clBtnFace; + FCanvas.Rectangle(R.Left, R.Top, R.Right, R.Bottom); + InflateRect(R, -1, -1); + end + else begin + Flags := DFCS_BUTTONPUSH or DFCS_ADJUSTRECT; + if Message.DrawItemStruct.itemState and ODS_DISABLED <> 0 then + Flags := Flags or DFCS_INACTIVE; + DrawFrameControl(Message.DrawItemStruct.hDC, R, DFC_BUTTON, Flags); + end; + //Adjust the rect when focused and/or down + if IsFocused then begin + R := ClientRect; + InflateRect(R, -1, -1); + end; + if IsDown then + OffsetRect(R, 1, 1); + end; + + //Calculate the position of the PNG glyph + CalcButtonLayout(FCanvas, FPngImage, ClientRect, IsDown, False, Caption, + Layout, Margin, Spacing, GlyphPos, TextPos, DrawTextBiDiModeFlags(0)); + + //Draw the image + if (FPngImage <> nil) and (Kind = bkCustom) and not FPngImage.Empty then begin + PaintRect := Bounds(GlyphPos.X, GlyphPos.Y, FPngImage.Width, FPngImage.Height); + if Enabled then + DrawPNG(FPngImage, FCanvas, PaintRect, []) + else + DrawPNG(FPngImage, FCanvas, PaintRect, FPngOptions); + end; + + //Draw the text + if Length(Caption) > 0 then begin + PaintRect := Rect(TextPos.X, TextPos.Y, Width, Height); + FCanvas.Brush.Style := bsClear; + DrawText(FCanvas.Handle, PChar(Caption), -1, PaintRect, + DrawTextBiDiModeFlags(0) or DT_TOP or DT_LEFT or DT_SINGLELINE); + end; + + //Draw the focus rectangle + if IsFocused and IsDefault then begin + if not ThemeServices.ThemesEnabled then begin + R := ClientRect; + InflateRect(R, -3, -3); + end; + FCanvas.Pen.Color := clWindowFrame; + FCanvas.Brush.Color := clBtnFace; + DrawFocusRect(FCanvas.Handle, R); + end; + + FLastKind := Kind; + FCanvas.Handle := 0; +end; + +procedure TPngBitBtn.CMMouseEnter(var Message: TMessage); +begin + inherited; + if ThemeServices.ThemesEnabled and not FMouseInControl and not (csDesigning in ComponentState) then begin + FMouseInControl := True; + Repaint; + end; +end; + +procedure TPngBitBtn.CMMouseLeave(var Message: TMessage); +begin + inherited; + if ThemeServices.ThemesEnabled and FMouseInControl then begin + FMouseInControl := False; + Repaint; + end; +end; + +end. diff --git a/internal/1.2.0/1/Source/PngButtonFunctions.pas b/internal/1.2.0/1/Source/PngButtonFunctions.pas new file mode 100644 index 0000000..4f9d69f --- /dev/null +++ b/internal/1.2.0/1/Source/PngButtonFunctions.pas @@ -0,0 +1,120 @@ +unit PngButtonFunctions; + +interface + +uses + Windows, Buttons, Graphics, pngimage; + +{$IF RTLVersion < 20.0 } +type + TPngImage = TPNGObject; +{$IFEND} + +procedure CalcButtonLayout(Canvas: TCanvas; PngImage: TPngImage; const Client: + TRect; Pressed, Down: Boolean; const Caption: string; Layout: TButtonLayout; + Margin, Spacing: Integer; var GlyphPos, TextPos: TPoint; BiDiFlags: LongInt); + +implementation + +uses + Classes; + +procedure CalcButtonLayout(Canvas: TCanvas; PngImage: TPngImage; const Client: + TRect; Pressed, Down: Boolean; const Caption: string; Layout: TButtonLayout; + Margin, Spacing: Integer; var GlyphPos, TextPos: TPoint; BiDiFlags: LongInt); +var + ClientSize, GlyphSize, TextSize, TotalSize: TPoint; + TextBounds: TRect; +begin + if (BiDiFlags and DT_RIGHT) = DT_RIGHT then begin + if Layout = blGlyphLeft then + Layout := blGlyphRight + else if Layout = blGlyphRight then + Layout := blGlyphLeft; + end; + + //Calculate the item sizes + ClientSize := Point(Client.Right - Client.Left, Client.Bottom - Client.Top); + + if PngImage <> nil then + GlyphSize := Point(PngImage.Width, PngImage.Height) + else + GlyphSize := Point(0, 0); + + if Length(Caption) > 0 then begin + TextBounds := Rect(0, 0, Client.Right - Client.Left, 0); + DrawText(Canvas.Handle, PChar(Caption), Length(Caption), TextBounds, + DT_CALCRECT or BiDiFlags); + TextSize := Point(TextBounds.Right - TextBounds.Left, TextBounds.Bottom - + TextBounds.Top); + end + else begin + TextBounds := Rect(0, 0, 0, 0); + TextSize := Point(0, 0); + end; + + //If the layout has the glyph on the right or the left, then both the + //text and the glyph are centered vertically. If the glyph is on the top + //or the bottom, then both the text and the glyph are centered horizontally. + if Layout in [blGlyphLeft, blGlyphRight] then + GlyphPos.Y := (ClientSize.Y - GlyphSize.Y + 1) div 2 + else + GlyphPos.X := (ClientSize.X - GlyphSize.X + 1) div 2; + + //If there is no text or no bitmap, then Spacing is irrelevant + if (TextSize.X = 0) or (GlyphSize.X = 0) then + Spacing := 0; + + //Adjust Margin and Spacing + if Margin = -1 then begin + if Spacing = -1 then begin + TotalSize := Point(GlyphSize.X + TextSize.X, GlyphSize.Y + TextSize.Y); + if Layout in [blGlyphLeft, blGlyphRight] then + Margin := (ClientSize.X - TotalSize.X) div 3 + else + Margin := (ClientSize.Y - TotalSize.Y) div 3; + end + else begin + TotalSize := Point(GlyphSize.X + Spacing + TextSize.X, GlyphSize.Y + + Spacing + TextSize.Y); + if Layout in [blGlyphLeft, blGlyphRight] then + Margin := (ClientSize.X - TotalSize.X) div 2 + else + Margin := (ClientSize.Y - TotalSize.Y) div 2; + end + end + else if Spacing = -1 then begin + TotalSize := Point(ClientSize.X - (Margin + GlyphSize.X), ClientSize.Y - + (Margin + GlyphSize.Y)); + end; + + case Layout of + blGlyphLeft: GlyphPos.X := Margin; + blGlyphRight: GlyphPos.X := ClientSize.X - Margin - GlyphSize.X; + blGlyphTop: GlyphPos.Y := Margin; + blGlyphBottom: GlyphPos.Y := ClientSize.Y - Margin - GlyphSize.Y; + end; + + if Layout in [blGlyphLeft, blGlyphRight] then + TextPos.Y := (ClientSize.Y - TextSize.Y) div 2 + else + TextPos.X := (ClientSize.X - TextSize.X) div 2; + case Layout of + blGlyphLeft: TextPos.X := GlyphPos.X + GlyphSize.X + Spacing; + blGlyphRight: TextPos.X := GlyphPos.X - Spacing - TextSize.X; + blGlyphTop: TextPos.Y := GlyphPos.Y + GlyphSize.Y + Spacing; + blGlyphBottom: TextPos.Y := GlyphPos.Y - Spacing - TextSize.Y; + end; + + //Fixup the result variables + with GlyphPos do begin + Inc(X, Client.Left + Integer(Pressed or Down)); + Inc(Y, Client.Top + Integer(Pressed or Down)); + end; + with TextPos do begin + Inc(X, Client.Left + Integer(Pressed or Down)); + Inc(Y, Client.Top + Integer(Pressed or Down)); + end; +end; + +end. diff --git a/internal/1.2.0/1/Source/PngCheckListBox.pas b/internal/1.2.0/1/Source/PngCheckListBox.pas new file mode 100644 index 0000000..0fc2eaa --- /dev/null +++ b/internal/1.2.0/1/Source/PngCheckListBox.pas @@ -0,0 +1,206 @@ +unit PngCheckListBox; + +interface + +uses + Windows, Classes, CheckLst, pngimage, PngFunctions; + +type + TPngCheckListBox = class(TCheckListBox) + private + FPngUnchecked: TPngImage; + FPngChecked: TPngImage; + FPngOptions: TPngOptions; + FPngGrayed: TPngImage; + procedure SetPngChecked(const Value: TPngImage); + procedure SetPngUnchecked(const Value: TPngImage); + procedure SetPngOptions(const Value: TPngOptions); + procedure SetPngGrayed(const Value: TPngImage); + protected + procedure DrawItem(Index: Integer; ARect: TRect; State: TOwnerDrawState); override; + function GetCheckWidth: Integer; reintroduce; + public + constructor Create(AOwner: TComponent); override; + destructor Destroy; override; + published + property PngChecked: TPngImage read FPngChecked write SetPngChecked; + property PngUnchecked: TPngImage read FPngUnchecked write SetPngUnchecked; + property PngGrayed: TPngImage read FPngGrayed write SetPngGrayed; + property PngOptions: TPngOptions read FPngOptions write SetPngOptions default [pngBlendOnDisabled]; + end; + +implementation + +uses + Graphics, StdCtrls, Math; + +{ TPngCheckListBox } + +constructor TPngCheckListBox.Create(AOwner: TComponent); +begin + inherited Create(AOwner); + FPngChecked := TPngImage.Create; + FPngUnchecked := TPngImage.Create; + FPngGrayed := TPngImage.Create; +end; + +destructor TPngCheckListBox.Destroy; +begin + FPngChecked.Free; + FPngUnchecked.Free; + FPngGrayed.Free; + inherited Destroy; +end; + +procedure TPngCheckListBox.DrawItem(Index: Integer; ARect: TRect; State: + TOwnerDrawState); + + procedure DrawCheck(R: TRect; AState: TCheckBoxState; AEnabled: Boolean); + var + Png: TPngImage; + OldColor: TColor; + begin + //Draws the check image, if it's a PNG, otherwise the inherited would have + //been called + OldColor := Canvas.Brush.Color; + Canvas.Brush.Color := Color; + Canvas.FillRect(R); + Canvas.Brush.Color := OldColor; + case AState of + cbUnchecked: Png := FPngUnchecked; + cbChecked: Png := FPngChecked; + else + Png := FPngGrayed; + end; + DrawPNG(Png, Canvas, Rect(R.Left, R.Top, R.Left + Png.Width, R.Top + + Png.Height), FPngOptions); + end; + + procedure DrawText; + var + Flags: Integer; + Data: string; + begin + //Draws the text for an item + if Assigned(OnDrawItem) then + OnDrawItem(Self, Index, ARect, State) + else begin + Canvas.FillRect(ARect); + if Index < Items.Count then begin + Flags := DrawTextBiDiModeFlags(DT_SINGLELINE or DT_VCENTER or + DT_NOPREFIX); + if not UseRightToLeftAlignment then + Inc(ARect.Left, 2) + else + Dec(ARect.Right, 2); + Data := ''; + if (Style in [lbVirtual, lbVirtualOwnerDraw]) then + Data := DoGetData(Index) + else + Data := Items[Index]; + Windows.DrawText(Canvas.Handle, PChar(Data), Length(Data), ARect, Flags); + end; + end; + end; + +var + R: TRect; + SaveEvent: TDrawItemEvent; + ACheckWidth: Integer; + Enable: Boolean; +begin + if FPngChecked.Empty and FPngUnchecked.Empty and FPngGrayed.Empty then + inherited DrawItem(Index, ARect, State) + else begin + ACheckWidth := GetCheckWidth; + if Index < Items.Count then begin + R := ARect; + Enable := Self.Enabled and ItemEnabled[Index]; + if not Header[Index] then begin + if not UseRightToLeftAlignment then begin + R.Right := ARect.Left; + R.Left := R.Right - ACheckWidth; + end + else begin + R.Left := ARect.Right; + R.Right := R.Left + ACheckWidth; + end; + DrawCheck(R, Self.State[Index], Enable); + end + else begin + Canvas.Font.Color := HeaderColor; + Canvas.Brush.Color := HeaderBackgroundColor; + end; + if not Enable then + Canvas.Font.Color := clGrayText; + end; + + if (Style = lbStandard) and Assigned(OnDrawItem) then begin + //Force lbStandard list to ignore OnDrawItem event. + SaveEvent := OnDrawItem; + OnDrawItem := nil; + try + DrawText; + finally + OnDrawItem := SaveEvent; + end; + end + else + DrawText; + end; +end; + +function TPngCheckListBox.GetCheckWidth: Integer; +begin + //CheckWidth is equal to the widest PNG + if not (FPngChecked.Empty and FPngUnchecked.Empty and FPngGrayed.Empty) then + Result := Max(FPngChecked.Width, Max(FPngUnchecked.Width, FPngGrayed.Width)) + else + Result := inherited GetCheckWidth; +end; + +procedure TPngCheckListBox.SetPngChecked(const Value: TPngImage); +begin + //This is all neccesary, because you can't assign a nil to a TPngImage + if Value = nil then begin + FPngChecked.Free; + FPngChecked := TPngImage.Create; + end + else + FPngChecked.Assign(Value); + Repaint; +end; + +procedure TPngCheckListBox.SetPngUnchecked(const Value: TPngImage); +begin + //This is all neccesary, because you can't assign a nil to a TPngImage + if Value = nil then begin + FPngUnchecked.Free; + FPngUnchecked := TPngImage.Create; + end + else + FPngUnchecked.Assign(Value); + Repaint; +end; + +procedure TPngCheckListBox.SetPngGrayed(const Value: TPngImage); +begin + //This is all neccesary, because you can't assign a nil to a TPngImage + if Value = nil then begin + FPngGrayed.Free; + FPngGrayed := TPngImage.Create; + end + else + FPngGrayed.Assign(Value); + Repaint; +end; + +procedure TPngCheckListBox.SetPngOptions(const Value: TPngOptions); +begin + if FPngOptions <> Value then begin + FPngOptions := Value; + Repaint; + end; +end; + +end. diff --git a/internal/1.2.0/1/Source/PngFunctions.pas b/internal/1.2.0/1/Source/PngFunctions.pas new file mode 100644 index 0000000..a7997da --- /dev/null +++ b/internal/1.2.0/1/Source/PngFunctions.pas @@ -0,0 +1,552 @@ +unit PngFunctions; + +interface + +uses + Windows, Graphics, ImgList, Contnrs, pngimage; + +{$IF RTLVersion < 20.0 } + {$IF RTLVersion < 15.0 } + PngComponents are only compatible with Delphi 7 and higher! + {$IFEND} +type + TPngImage = TPNGObject; +{$IFEND} + +type + TPngOption = (pngBlendOnDisabled, pngGrayscaleOnDisabled); + TPngOptions = set of TPngOption; + TRGBLine = array[Word] of TRGBTriple; + PRGBLine = ^TRGBLine; + TRGBALine = array[Word] of TRGBQuad; + PRGBALine = ^TRGBALine; + +procedure MakeImageBlended(Image: TPngImage; Amount: Byte = 127); +procedure MakeImageGrayscale(Image: TPngImage; Amount: Byte = 255); +procedure DrawPNG(Png: TPngImage; Canvas: TCanvas; const ARect: TRect; const Options: TPngOptions); +procedure ConvertToPNG(Source: TGraphic; out Dest: TPngImage); +procedure CreatePNG(Color, Mask: TBitmap; out Dest: TPngImage; InverseMask: Boolean = False); +procedure CreatePNGMasked(Bitmap: TBitmap; Mask: TColor; out Dest: TPngImage); +procedure CopyImageFromImageList(Dest: TPngImage; ImageList: TCustomImageList; Index: Integer); +procedure SlicePNG(JoinedPNG: TPngImage; Columns, Rows: Integer; out SlicedPNGs: TObjectList); + +implementation + +uses + SysUtils, PngImageList; + +function ColorToTriple(Color: TColor): TRGBTriple; +var + ColorRGB: Longint; +begin + ColorRGB := ColorToRGB(Color); + Result.rgbtBlue := ColorRGB shr 16 and $FF; + Result.rgbtGreen := ColorRGB shr 8 and $FF; + Result.rgbtRed := ColorRGB and $FF; +end; + +procedure MakeImageBlended(Image: TPngImage; Amount: Byte = 127); + + procedure ForceAlphachannel(BitTransparency: Boolean; TransparentColor: TColor); + var + Assigner: TBitmap; + Temp: TPngImage; + X, Y: Integer; + Line: pngimage.PByteArray; + Current: TColor; + begin + //Not all formats of PNG support an alpha-channel (paletted images for example), + //so with this function, I simply recreate the PNG as being 32-bits, effectivly + //forcing an alpha-channel on it. + Temp := TPngImage.Create; + try + Assigner := TBitmap.Create; + try + Assigner.Width := Image.Width; + Assigner.Height := Image.Height; + Temp.Assign(Assigner); + finally + Assigner.Free; + end; + Temp.CreateAlpha; + for Y := 0 to Image.Height - 1 do begin + Line := Temp.AlphaScanline[Y]; + for X := 0 to Image.Width - 1 do begin + Current := Image.Pixels[X, Y]; + Temp.Pixels[X, Y] := Current; + if BitTransparency and (Current = TransparentColor) then + Line[X] := 0 + else + Line[X] := Amount; + end; + end; + Image.Assign(Temp); + finally + Temp.Free; + end; + end; + +var + X, Y: Integer; + Line: pngimage.PByteArray; + Forced: Boolean; + TransparentColor: TColor; + BitTransparency: Boolean; +begin + //If the PNG doesn't have an alpha channel, then add one + BitTransparency := Image.TransparencyMode = ptmBit; + TransparentColor := Image.TransparentColor; + Forced := False; + if not (Image.Header.ColorType in [COLOR_RGBALPHA, COLOR_GRAYSCALEALPHA]) then begin + Forced := Image.Header.ColorType in [COLOR_GRAYSCALE, COLOR_PALETTE]; + if Forced then + ForceAlphachannel(BitTransparency, TransparentColor) + else + Image.CreateAlpha; + end; + + //Divide the alpha values by 2 + if not Forced and (Image.Header.ColorType in [COLOR_RGBALPHA, COLOR_GRAYSCALEALPHA]) then begin + for Y := 0 to Image.Height - 1 do begin + Line := Image.AlphaScanline[Y]; + for X := 0 to Image.Width - 1 do begin + if BitTransparency and (Image.Pixels[X, Y] = TransparentColor) then + Line[X] := 0 + else + Line[X] := Round(Line[X] / 256 * (Amount + 1)); + end; + end; + end; +end; + +procedure MakeImageGrayscale(Image: TPngImage; Amount: Byte = 255); + + procedure GrayscaleRGB(var R, G, B: Byte); + var + X: Byte; + begin + X := Round(R * 0.30 + G * 0.59 + B * 0.11); + R := Round(R / 256 * (256 - Amount - 1)) + Round(X / 256 * (Amount + 1)); + G := Round(G / 256 * (256 - Amount - 1)) + Round(X / 256 * (Amount + 1)); + B := Round(B / 256 * (256 - Amount - 1)) + Round(X / 256 * (Amount + 1)); + end; + +var + X, Y, PalCount: Integer; + Line: PRGBLine; + PaletteHandle: HPalette; + Palette: array[Byte] of TPaletteEntry; +begin + //Don't do anything if the image is already a grayscaled one + if not (Image.Header.ColorType in [COLOR_GRAYSCALE, COLOR_GRAYSCALEALPHA]) then begin + if Image.Header.ColorType = COLOR_PALETTE then begin + //Grayscale every palette entry + PaletteHandle := Image.Palette; + PalCount := GetPaletteEntries(PaletteHandle, 0, 256, Palette); + for X := 0 to PalCount - 1 do + GrayscaleRGB(Palette[X].peRed, Palette[X].peGreen, Palette[X].peBlue); + SetPaletteEntries(PaletteHandle, 0, PalCount, Palette); + Image.Palette := PaletteHandle; + end + else begin + //Grayscale every pixel + for Y := 0 to Image.Height - 1 do begin + Line := Image.Scanline[Y]; + for X := 0 to Image.Width - 1 do + GrayscaleRGB(Line[X].rgbtRed, Line[X].rgbtGreen, Line[X].rgbtBlue); + end; + end; + end; +end; + +procedure DrawPNG(Png: TPngImage; Canvas: TCanvas; const ARect: TRect; const Options: TPngOptions); +var + PngCopy: TPngImage; +begin + if Options <> [] then begin + PngCopy := TPngImage.Create; + try + PngCopy.Assign(Png); + if pngBlendOnDisabled in Options then + MakeImageBlended(PngCopy); + if pngGrayscaleOnDisabled in Options then + MakeImageGrayscale(PngCopy); + PngCopy.Draw(Canvas, ARect); + finally + PngCopy.Free; + end; + end + else begin + Png.Draw(Canvas, ARect); + end; +end; + +procedure ConvertToPNG(Source: TGraphic; out Dest: TPngImage); +var + MaskLines: array of pngimage.PByteArray; + + function CompareColors(const Color1: TRGBTriple; const Color2: TColor): Boolean; + begin + Result := (Color1.rgbtBlue = Color2 shr 16 and $FF) and + (Color1.rgbtGreen = Color2 shr 8 and $FF) and + (Color1.rgbtRed = Color2 and $FF); + end; + + function ColorToTriple(const Color: TColor): TRGBTriple; + begin + Result.rgbtBlue := Color shr 16 and $FF; + Result.rgbtGreen := Color shr 8 and $FF; + Result.rgbtRed := Color and $FF; + end; + + procedure GetAlphaMask(SourceColor: TBitmap); + type + TBitmapInfo = packed record + bmiHeader: TBitmapV4Header; + //Otherwise I may not get per-pixel alpha values. + bmiColors: array[0..0] of TRGBQuad; + end; + var + Bits: PRGBALine; + BitmapInfo: TBitmapInfo; + I, X, Y: Integer; + HasAlpha: Boolean; + BitsSize: Integer; + begin + BitsSize := 4 * SourceColor.Width * SourceColor.Height; + Bits := AllocMem(BitsSize); + try + ZeroMemory(Bits, BitsSize); + ZeroMemory(@BitmapInfo, SizeOf(BitmapInfo)); + BitmapInfo.bmiHeader.bV4Size := SizeOf(BitmapInfo.bmiHeader); + BitmapInfo.bmiHeader.bV4Width := SourceColor.Width; + BitmapInfo.bmiHeader.bV4Height := -SourceColor.Height; + //Otherwise the image is upside down. + BitmapInfo.bmiHeader.bV4Planes := 1; + BitmapInfo.bmiHeader.bV4BitCount := 32; + BitmapInfo.bmiHeader.bV4V4Compression := BI_BITFIELDS; + BitmapInfo.bmiHeader.bV4SizeImage := BitsSize; + + if GetDIBits(SourceColor.Canvas.Handle, SourceColor.Handle, 0, + SourceColor.Height, Bits, Windows.PBitmapInfo(@BitmapInfo)^, + DIB_RGB_COLORS) > 0 then begin + //Because Win32 API is a piece of crap when it comes to icons, I have to check + //whether an has an alpha-channel the hard way. + HasAlpha := False; + for I := 0 to (SourceColor.Height * SourceColor.Width) - 1 do begin + if Bits[I].rgbReserved <> 0 then begin + HasAlpha := True; + Break; + end; + end; + if HasAlpha then begin + //OK, so not all alpha-values are 0, which indicates the existence of an + //alpha-channel. + I := 0; + for Y := 0 to SourceColor.Height - 1 do + for X := 0 to SourceColor.Width - 1 do begin + MaskLines[Y][X] := Bits[I].rgbReserved; + Inc(I); + end; + end; + end; + finally + FreeMem(Bits, BitsSize); + end; + end; + + function WinXPOrHigher: Boolean; + var + Info: TOSVersionInfo; + begin + Info.dwOSVersionInfoSize := SizeOf(Info); + GetVersionEx(Info); + Result := (Info.dwPlatformId = VER_PLATFORM_WIN32_NT) and + ((Info.dwMajorVersion > 5) or + ((Info.dwMajorVersion = 5) and (Info.dwMinorVersion >= 1))); + end; + +var + Temp, SourceColor, SourceMask: TBitmap; + X, Y: Integer; + Line: PRGBLine; + MaskLine, AlphaLine: pngimage.PByteArray; + TransparentColor, CurrentColor: TColor; + IconInfo: TIconInfo; + AlphaNeeded: Boolean; +begin + //A PNG does not have to be converted + if Source is TPngImage then begin + Dest := TPngImage.Create; + Dest.Assign(Source); + Exit; + end; + + AlphaNeeded := False; + Temp := TBitmap.Create; + SetLength(MaskLines, Source.Height); + for Y := 0 to Source.Height - 1 do begin + MaskLines[Y] := AllocMem(Source.Width); + FillMemory(MaskLines[Y], Source.Width, 255); + end; + try + //Initialize intermediate color bitmap + Temp.Width := Source.Width; + Temp.Height := Source.Height; + Temp.PixelFormat := pf24bit; + + //Now figure out the transparency + if Source is TBitmap then begin + if Source.Transparent then begin + //TBitmap is just about comparing the drawn colors against the TransparentColor + if TBitmap(Source).TransparentMode = tmFixed then + TransparentColor := TBitmap(Source).TransparentColor + else + TransparentColor := TBitmap(Source).Canvas.Pixels[0, Source.Height - 1]; + + for Y := 0 to Temp.Height - 1 do begin + Line := Temp.ScanLine[Y]; + MaskLine := MaskLines[Y]; + for X := 0 to Temp.Width - 1 do begin + CurrentColor := GetPixel(TBitmap(Source).Canvas.Handle, X, Y); + if CurrentColor = TransparentColor then begin + MaskLine^[X] := 0; + AlphaNeeded := True; + end; + Line[X] := ColorToTriple(CurrentColor); + end; + end; + end + else begin + Temp.Canvas.Draw(0, 0, Source); + end; + end + else if Source is TIcon then begin + //TIcon is more complicated, because there are bitmasked (classic) icons and + //alphablended (modern) icons. Not to forget about the "inverse" color. + GetIconInfo(TIcon(Source).Handle, IconInfo); + SourceColor := TBitmap.Create; + SourceMask := TBitmap.Create; + try + SourceColor.Handle := IconInfo.hbmColor; + SourceMask.Handle := IconInfo.hbmMask; + Temp.Canvas.Draw(0, 0, SourceColor); + for Y := 0 to Temp.Height - 1 do begin + MaskLine := MaskLines[Y]; + for X := 0 to Temp.Width - 1 do begin + if GetPixel(SourceMask.Canvas.Handle, X, Y) <> 0 then begin + MaskLine^[X] := 0; + AlphaNeeded := True; + end; + end; + end; + if (GetDeviceCaps(SourceColor.Canvas.Handle, BITSPIXEL) = 32) and WinXPOrHigher then begin + //This doesn't neccesarily mean we actually have 32bpp in the icon, because the + //bpp of an icon is always the same as the display settings, regardless of the + //actual color depth of the icon :( + AlphaNeeded := True; + GetAlphaMask(SourceColor); + end; + //This still doesn't work for alphablended icons... + finally + SourceColor.Free; + SourceMask.Free + end; + end; + + //And finally, create the destination PNG image + Dest := TPngImage.Create; + Dest.Assign(Temp); + if AlphaNeeded then begin + Dest.CreateAlpha; + for Y := 0 to Dest.Height - 1 do begin + AlphaLine := Dest.AlphaScanline[Y]; + CopyMemory(AlphaLine, MaskLines[Y], Temp.Width); + end; + end; + + finally + for Y := 0 to Source.Height - 1 do + FreeMem(MaskLines[Y], Source.Width); + Temp.Free; + end; +end; + +procedure CreatePNG(Color, Mask: TBitmap; out Dest: TPngImage; InverseMask: Boolean = False); +var + Temp: TBitmap; + Line: pngimage.PByteArray; + X, Y: Integer; +begin + //Create a PNG from two separate color and mask bitmaps. InverseMask should be + //True if white means transparent, and black means opaque. + Dest := TPngImage.Create; + if not (Color.PixelFormat in [pf24bit, pf32bit]) then begin + Temp := TBitmap.Create; + try + Temp.Assign(Color); + Temp.PixelFormat := pf24bit; + Dest.Assign(Temp); + finally + Temp.Free; + end; + end + else begin + Dest.Assign(Color); + end; + + //Copy the alpha channel. + Dest.CreateAlpha; + for Y := 0 to Dest.Height - 1 do begin + Line := Dest.AlphaScanline[Y]; + for X := 0 to Dest.Width - 1 do begin + if InverseMask then + Line[X] := 255 - (GetPixel(Mask.Canvas.Handle, X, Y) and $FF) + else + Line[X] := GetPixel(Mask.Canvas.Handle, X, Y) and $FF; + end; + end; +end; + +procedure CreatePNGMasked(Bitmap: TBitmap; Mask: TColor; out Dest: TPngImage); +var + Temp: TBitmap; + Line: pngimage.PByteArray; + X, Y: Integer; +begin + //Create a PNG from two separate color and mask bitmaps. InverseMask should be + //True if white means transparent, and black means opaque. + Dest := TPngImage.Create; + if not (Bitmap.PixelFormat in [pf24bit, pf32bit]) then begin + Temp := TBitmap.Create; + try + Temp.Assign(Bitmap); + Temp.PixelFormat := pf24bit; + Dest.Assign(Temp); + finally + Temp.Free; + end; + end + else begin + Dest.Assign(Bitmap); + end; + + //Copy the alpha channel. + Dest.CreateAlpha; + for Y := 0 to Dest.Height - 1 do begin + Line := Dest.AlphaScanline[Y]; + for X := 0 to Dest.Width - 1 do + Line[X] := Integer(TColor(GetPixel(Bitmap.Canvas.Handle, X, Y)) <> Mask) * $FF; + 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; + +procedure SlicePNG(JoinedPNG: TPngImage; Columns, Rows: Integer; out SlicedPNGs: TObjectList); +var + X, Y, ImageX, ImageY, OffsetX, OffsetY: Integer; + Width, Height: Integer; + Bitmap: TBitmap; + BitmapLine: PRGBLine; + AlphaLineA, AlphaLineB: pngimage.PByteArray; + PNG: TPngImage; +begin + //This function slices a large PNG file (e.g. an image with all images for a + //toolbar) into smaller, equally-sized pictures. + SlicedPNGs := TObjectList.Create(False); + Width := JoinedPNG.Width div Columns; + Height := JoinedPNG.Height div Rows; + + //Loop through the columns and rows to create each individual image + for ImageY := 0 to Rows - 1 do begin + for ImageX := 0 to Columns - 1 do begin + OffsetX := ImageX * Width; + OffsetY := ImageY * Height; + Bitmap := TBitmap.Create; + try + Bitmap.Width := Width; + Bitmap.Height := Height; + Bitmap.PixelFormat := pf24bit; + + //Copy the color information into a temporary bitmap. We can't use TPngImage.Draw + //here, because that would combine the color and alpha values. + for Y := 0 to Bitmap.Height - 1 do begin + BitmapLine := Bitmap.Scanline[Y]; + for X := 0 to Bitmap.Width - 1 do + BitmapLine[X] := ColorToTriple(JoinedPNG.Pixels[X + OffsetX, Y + OffsetY]); + end; + + PNG := TPngImage.Create; + PNG.Assign(Bitmap); + + if JoinedPNG.Header.ColorType in [COLOR_GRAYSCALEALPHA, COLOR_RGBALPHA] then begin + //Copy the alpha channel + PNG.CreateAlpha; + for Y := 0 to PNG.Height - 1 do begin + AlphaLineA := JoinedPNG.AlphaScanline[Y + OffsetY]; + AlphaLineB := JoinedPNG.AlphaScanline[Y]; + for X := 0 to PNG.Width - 1 do + AlphaLineB[X] := AlphaLineA[X + OffsetX]; + end; + end; + + SlicedPNGs.Add(PNG); + finally + Bitmap.Free; + end; + end; + end; +end; + +{$IF RTLVersion >= 20.0 } +type + TPNGObject = class(TPngImage); +begin + TPicture.RegisterFileFormat('', '', TPNGObject); +{$IFEND} +end. + diff --git a/internal/1.2.0/1/Source/PngImageList.pas b/internal/1.2.0/1/Source/PngImageList.pas new file mode 100644 index 0000000..3ea3d0b --- /dev/null +++ b/internal/1.2.0/1/Source/PngImageList.pas @@ -0,0 +1,1252 @@ +unit PngImageList; + +{$IF RTLVersion < 15.0 } +This unit only compiles with Delphi 7 and higher! +{$IFEND} + +interface + +uses + Windows, Classes, SysUtils, Controls, Graphics, ImgList, PngImage, + PngFunctions; + +type + TPngImageCollection = class; + TPngImageCollectionItem = class; + TPngImageCollectionItems = class; + + TPngImageList = class(TImageList) + private + FEnabledImages: Boolean; + FLocked: Integer; + FPngImages: TPngImageCollectionItems; + FPngOptions: TPngOptions; + function GetHeight: Integer; + 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; + 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 AddImage(Value: TCustomImageList; Index: Integer): Integer; virtual; + procedure AddImages(Value: TCustomImageList); virtual; + function AddMasked(Image: TBitmap; MaskColor: TColor): Integer; virtual; + procedure BeginUpdate; + procedure Clear; virtual; + procedure Delete(Index: Integer); virtual; + procedure EndUpdate(Update: Boolean = True); + procedure Insert(Index: Integer; Image, Mask: TBitmap); virtual; + procedure InsertIcon(Index: Integer; Image: TIcon); virtual; + procedure InsertMasked(Index: Integer; Image: TBitmap; MaskColor: TColor); virtual; + procedure InsertPng(Index: Integer; const Png: TPngImage; Background: TColor = clNone); + procedure Move(CurIndex, NewIndex: Integer); virtual; + procedure Replace(Index: Integer; Image, Mask: TBitmap); virtual; + procedure ReplaceIcon(Index: Integer; Image: TIcon); virtual; + procedure ReplaceMasked(Index: Integer; NewImage: TBitmap; MaskColor: TColor); virtual; + published + property EnabledImages: Boolean read FEnabledImages write SetEnabledImages default True; + property Height read GetHeight write SetHeight default 16; + 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; + +implementation + +uses + Math, Contnrs, CommCtrl, ComCtrls; + +var + ImageListCount: Integer = 0; + MethodPatches: TObjectList = nil; + +type + TMethodPatch = class + private + Name: string; + OldBody: array[0..5] of Byte; + OldPointer, 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; + +function PatchPtr(OldPtr, NewPtr: Pointer; const Name: string; Patch: TMethodPatch): Boolean; +var + Access: Cardinal; +begin + Result := False; + Patch.Name := Name; + if OldPtr <> NewPtr then begin + Patch.OldPointer := OldPtr; + Patch.NewPointer := NewPtr; + Move(PByte(OldPtr)^, Patch.OldBody[0], SizeOf(Patch.OldBody)); + if VirtualProtect(OldPtr, 16, PAGE_EXECUTE_READWRITE, @Access) then begin + PByte(OldPtr)^ := $E9; // Near jump + PCardinal(Cardinal(OldPtr) + 1)^ := Cardinal(NewPtr) - Cardinal(OldPtr) - 5; + VirtualProtect(OldPtr, 16, Access, @Access); + Result := True; + end; + end; + if not Result then + Patch.OldPointer := nil; +end; + +procedure ApplyMethodPatches; +type + TPointerCombo = record + OldPtr, NewPtr: Pointer; + Name: string; + end; + + function Combo(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 + SetLength(Pointers, 14); + 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'); + + 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 + MethodPatches.Add(Patch) + else + Patch.Free; + end; + end; + end; +end; + +procedure RevertPatchedMethods; +begin + if ImageListCount = 0 then + FreeAndNil(MethodPatches); +end; + +{ TMethodPatch } + +constructor TMethodPatch.Create; +begin + inherited Create; + OldPointer := nil; +end; + +destructor TMethodPatch.Destroy; +begin + if OldPointer <> nil then + PatchBack; + 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); +begin + inherited Create(AOwner); + 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 + Item: TPngImageCollectionItem; + Patch: TMethodPatch; + Icon: HICON; +begin + if TObject(Self) is TPngImageList then + if Image = nil then + Result := -1 + else begin + BeginUpdate; + try + Item := FPngImages.Add(True); + CreatePNG(Image, Mask, Item.FPngImage); + Result := Item.Index; + Icon := PngToIcon(Item.PngImage, Item.Background); + ImageList_AddIcon(Handle, Icon); + DestroyIcon(Icon); + Change; + finally + EndUpdate; + 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 + Item: TPngImageCollectionItem; + Patch: TMethodPatch; + Icon: HICON; +begin + if TObject(Self) is TPngImageList then + if Image = nil then + Result := -1 + else begin + BeginUpdate; + try + Item := FPngImages.Add(True); + ConvertToPNG(Image, Item.FPngImage); + Result := Item.Index; + Icon := PngToIcon(Item.PngImage, Item.Background); + ImageList_AddIcon(Handle, Icon); + DestroyIcon(Icon); + Change; + finally + EndUpdate; + 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.AddImage(Value: TCustomImageList; Index: Integer): Integer; +var + Item: TPngImageCollectionItem; + Patch: TMethodPatch; + Icon: HICON; +begin + if TObject(Self) is TPngImageList then begin + //Add a new PNG based on the image from another imagelist. If this happens to be + //a PngImageList, the PNG object is simply copied. + BeginUpdate; + try + Item := FPngImages.Add(False); + CopyImageFromImageList(Item.FPngImage, Value, Index); + Icon := PngToIcon(Item.PngImage, Item.Background); + ImageList_AddIcon(Handle, Icon); + DestroyIcon(Icon); + Result := Item.Index; + Change; + finally + EndUpdate; + 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 + Item: TPngImageCollectionItem; + Patch: TMethodPatch; + I: Integer; + Icon: HICON; +begin + if TObject(Self) is TPngImageList then begin + BeginUpdate; + try + //Copy every image from Value into this imagelist. + for I := 0 to Value.Count - 1 do begin + Item := FPngImages.Add(False); + CopyImageFromImageList(Item.FPngImage, Value, I); + Icon := PngToIcon(Item.PngImage, Item.Background); + ImageList_AddIcon(Handle, Icon); + DestroyIcon(Icon); + end; + Change; + 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; + +function TPngImageList.AddMasked(Image: TBitmap; MaskColor: TColor): Integer; +var + Item: TPngImageCollectionItem; + Patch: TMethodPatch; + Icon: HICON; +begin + if TObject(Self) is TPngImageList then + if Image = nil then + Result := -1 + else begin + BeginUpdate; + try + //Add a new PNG based on the image and a colored mask. + Item := FPngImages.Add(True); + CreatePNGMasked(Image, MaskColor, Item.FPngImage); + Result := Item.Index; + Icon := PngToIcon(Item.PngImage, Item.Background); + ImageList_AddIcon(Handle, Icon); + DestroyIcon(Icon); + Change; + finally + EndUpdate; + 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; + +{ TPngImageList } + +procedure TPngImageList.AssignTo(Dest: TPersistent); +begin + inherited; + if Dest is TPngImageList then begin + TPngImageList(Dest).PngImages := FPngImages; + TPngImageList(Dest).EnabledImages := FEnabledImages; + 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; +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); + + if not FEnabledImages and (FPngOptions <> []) then + Png := TPngImage.Create + else + Png := nil; //<- To prevent a compiler warning + try + for I := 0 to FPngImages.Count - 1 do begin + if TPngImageCollectionItem(FPngImages.Items[I]).PngImage = nil then + Continue; + if FEnabledImages or (FPngOptions = []) then + Icon := PngToIcon(FPngImages.Items[I].PngImage, + FPngImages.Items[I].Background) + else begin + //Basically the same as in the DrawPNG function + Png.Assign(TPngImageCollectionItem(FPngImages.Items[I]).PngImage); + if pngBlendOnDisabled in FPngOptions then + MakeImageBlended(Png); + if pngGrayscaleOnDisabled in FPngOptions then + MakeImageGrayscale(Png); + Icon := PngToIcon(Png); + end; + ImageList_AddIcon(Handle, Icon); + DestroyIcon(Icon); + end; + finally + if not FEnabledImages and (FPngOptions <> []) then + 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; + 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 := TPngImageCollectionItem(FPngImages.Items[Index]); + if Png <> nil then + DrawPNG(Png.PngImage, Canvas, PaintRect, Options); +end; + +procedure TPngImageList.EndUpdate(Update: Boolean); +begin + Dec(FLocked); + if Update and (FLocked = 0) then + CopyPngs; +end; + +function TPngImageList.GetHeight: Integer; +begin + Result := inherited Height; +end; + +function TPngImageList.GetWidth: Integer; +begin + Result := inherited Width; +end; + +procedure TPngImageList.Insert(Index: Integer; Image, Mask: TBitmap); +var + Item: TPngImageCollectionItem; + Patch: TMethodPatch; +begin + if TObject(Self) is TPngImageList then begin + //Insert a new PNG based on the image and its mask. + if Image <> nil then begin + BeginUpdate; + try + Item := FPngImages.Insert(Index, True); + CreatePNG(Image, Mask, Item.FPngImage); + InsertPng(Index, Item.PngImage, Item.Background); + Change; + finally + EndUpdate(False); + 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 + Item: TPngImageCollectionItem; + Patch: TMethodPatch; +begin + if TObject(Self) is TPngImageList then begin + //Insert a new PNG based on the image. + if Image <> nil then begin + BeginUpdate; + try + Item := FPngImages.Insert(Index, True); + ConvertToPNG(Image, Item.FPngImage); + InsertPng(Index, Item.PngImage, Item.Background); + Change; + finally + EndUpdate(False); + 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.InsertMasked(Index: Integer; Image: TBitmap; MaskColor: TColor); +var + Item: TPngImageCollectionItem; + Patch: TMethodPatch; +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 + BeginUpdate; + try + Item := FPngImages.Insert(Index, True); + CreatePNGMasked(Image, MaskColor, Item.FPngImage); + InsertPng(Index, Item.PngImage, Item.Background); + Change; + finally + EndUpdate(False); + 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.InsertPng(Index: Integer; const Png: TPngImage; Background: TColor); +var + I: Integer; + Icon: HICON; + TempList: TCustomImageList; +begin + TempList := TCustomImageList.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.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); + InsertPng(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.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 + //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]; + Item.FPngImage.Free; + CreatePNG(Image, Mask, Item.FPngImage); + 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]; + Item.FPngImage.Free; + ConvertToPNG(Image, Item.FPngImage); + 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]; + Item.FPngImage.Free; + CreatePNGMasked(NewImage, MaskColor, Item.FPngImage); + 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 + //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 + FPngImage.Assign(Value); + Changed(False); +end; + +initialization + +finalization + MethodPatches.Free; + +end. + diff --git a/internal/1.2.0/1/Source/PngSpeedButton.pas b/internal/1.2.0/1/Source/PngSpeedButton.pas new file mode 100644 index 0000000..3846d97 --- /dev/null +++ b/internal/1.2.0/1/Source/PngSpeedButton.pas @@ -0,0 +1,147 @@ +unit PngSpeedButton; + +interface + +uses + Windows, Classes, Buttons, pngimage, PngFunctions; + +type + TPngSpeedButton = class(TSpeedButton) + private + FPngImage: TPngImage; + FPngOptions: TPngOptions; + FImageFromAction: Boolean; + function PngImageStored: Boolean; + procedure SetPngImage(const Value: TPngImage); + procedure SetPngOptions(const Value: TPngOptions); + procedure CreatePngGlyph; + protected + procedure ActionChange(Sender: TObject; CheckDefaults: Boolean); override; + procedure Paint; override; + procedure Loaded; override; + public + constructor Create(AOwner: TComponent); override; + destructor Destroy; override; + published + property PngImage: TPngImage read FPngImage write SetPngImage stored PngImageStored; + property PngOptions: TPngOptions read FPngOptions write SetPngOptions default [pngBlendOnDisabled]; + property Glyph stored False; + property NumGlyphs stored False; + end; + +implementation + +uses + Graphics, ActnList, PngButtonFunctions; + +{ TPngSpeedButton } + +constructor TPngSpeedButton.Create(AOwner: TComponent); +begin + inherited Create(AOwner); + FPngImage := TPngImage.Create; + FPngOptions := [pngBlendOnDisabled]; + FImageFromAction := False; +end; + +destructor TPngSpeedButton.Destroy; +begin + FPngImage.Free; + inherited Destroy; +end; + +procedure TPngSpeedButton.ActionChange(Sender: TObject; CheckDefaults: Boolean); +begin + inherited ActionChange(Sender, CheckDefaults); + if Sender is TCustomAction then + with TCustomAction(Sender) do begin + //Copy image from action's imagelist + if (PngImage.Empty or FImageFromAction) and (ActionList <> nil) and + (ActionList.Images <> nil) and (ImageIndex >= 0) and (ImageIndex < + ActionList.Images.Count) then begin + CopyImageFromImageList(FPngImage, ActionList.Images, ImageIndex); + CreatePngGlyph; + FImageFromAction := True; + end; + end; +end; + +procedure TPngSpeedButton.Paint; +var + PaintRect: TRect; + GlyphPos, TextPos: TPoint; +begin + inherited Paint; + + if FPngImage <> nil then begin + //Calculate the position of the PNG glyph + CalcButtonLayout(Canvas, FPngImage, ClientRect, FState = bsDown, Down, + Caption, Layout, Margin, Spacing, GlyphPos, TextPos, DrawTextBiDiModeFlags(0)); + PaintRect := Bounds(GlyphPos.X, GlyphPos.Y, FPngImage.Width, FPngImage.Height); + + if Enabled then + DrawPNG(FPngImage, Canvas, PaintRect, []) + else + DrawPNG(FPngImage, Canvas, PaintRect, FPngOptions); + end; +end; + +procedure TPngSpeedButton.Loaded; +begin + inherited Loaded; + CreatePngGlyph; +end; + +function TPngSpeedButton.PngImageStored: Boolean; +begin + Result := not FImageFromAction; +end; + +procedure TPngSpeedButton.SetPngImage(const Value: TPngImage); +begin + //This is all neccesary, because you can't assign a nil to a TPngImage + if Value = nil then begin + FPngImage.Free; + FPngImage := TPngImage.Create; + end + else + FPngImage.Assign(Value); + + //To work around the gamma-problem + with FPngImage do + if Header.ColorType in [COLOR_RGB, COLOR_RGBALPHA, COLOR_PALETTE] then + Chunks.RemoveChunk(Chunks.ItemFromClass(TChunkgAMA)); + + FImageFromAction := False; + CreatePngGlyph; + Repaint; +end; + +procedure TPngSpeedButton.SetPngOptions(const Value: TPngOptions); +begin + if FPngOptions <> Value then begin + FPngOptions := Value; + CreatePngGlyph; + Repaint; + end; +end; + +procedure TPngSpeedButton.CreatePngGlyph; +var + Bmp: TBitmap; +begin + //Create an empty glyph, just to align the text correctly + Bmp := TBitmap.Create; + try + Bmp.Width := FPngImage.Width; + Bmp.Height := FPngImage.Height; + Bmp.Canvas.Brush.Color := clBtnFace; + Bmp.Canvas.FillRect(Rect(0, 0, Bmp.Width, Bmp.Height)); + Glyph.Assign(Bmp); + NumGlyphs := 1; + finally + Bmp.Free; + end; +end; + +end.