diff options
Diffstat (limited to 'apps/X11/VCL/TCustomImageList.cpp')
-rw-r--r-- | apps/X11/VCL/TCustomImageList.cpp | 1142 |
1 files changed, 1142 insertions, 0 deletions
diff --git a/apps/X11/VCL/TCustomImageList.cpp b/apps/X11/VCL/TCustomImageList.cpp new file mode 100644 index 0000000..6a63a24 --- /dev/null +++ b/apps/X11/VCL/TCustomImageList.cpp @@ -0,0 +1,1142 @@ + +#include <TCustomImageList.h> + +TCustomImageList::TCustomImageList(TComponent *AOwner) : + TComponent(AOwner) { +} + +TCustomImageList::TCustomImageList(int AWidth, int AHeight) : + TComponent(0) { +} + +TCustomImageList::~TCustomImageList() { +} + +/* +function TCustomImageList.Add(Image, Mask: TBitmap): Integer; +var + ImageDDB, MaskDDB: TBitmap; +begin + ImageDDB := TBitmap.Create; + try + MaskDDB := TBitmap.Create; + try + HandleNeeded; + Result := ImageList_Add(FHandle, GetImageHandle(Image, ImageDDB), + GetImageHandle(Mask, MaskDDB)); + finally + MaskDDB.Free; + end; + finally + ImageDDB.Free; + end; + Change; +end; +*/ + +int TCustomImageList::Add(gchar **xpm_data, GtkWidget *canvas) { + + /* GtkWidget is the storage type for widgets */ + GtkWidget *pixmapwid; + GdkPixmap *pixmap; + GdkBitmap *mask; + GdkWindow *window = 0; + GtkStyle *style; + + while ((!window) && (canvas->parent)) { + window = gtk_widget_get_parent_window(GTK_WIDGET(canvas)); + canvas = canvas->parent; + } + style = gtk_widget_get_style( GTK_WIDGET(canvas) ); + pixmap = gdk_pixmap_create_from_xpm_d( window, &mask, + &style->bg[GTK_STATE_NORMAL], + (gchar **)xpm_data); + + pixmapwid = gtk_pixmap_new( pixmap, mask ); + images.push_back(GTK_PIXMAP(pixmapwid)); + return images.size(); +} + + +/* +procedure TCustomImageList.GetBitmap(Index: Integer; Image: TBitmap); +begin + if (Image <> nil) and HandleAllocated then + with Image do + begin + Height := FHeight; + Width := FWidth; + Draw(Canvas, 0, 0, Index); + end; +end; +*/ +GtkPixmap *TCustomImageList::GetPixmap(int index) { + if ((unsigned int)index < images.size()) + return images[index]; + else return 0; +} + + +/* +{ TCustomImageList } + +function GetRGBColor(Value: TColor): DWORD; +begin + Result := ColorToRGB(Value); + case Result of + clNone: Result := CLR_NONE; + clDefault: Result := CLR_DEFAULT; + end; +end; + +function GetColor(Value: DWORD): TColor; +begin + case Value of + CLR_NONE: Result := clNone; + CLR_DEFAULT: Result := clDefault; + else + Result := TColor(Value); + end; +end; + +constructor TCustomImageList.Create(AOwner: TComponent); +begin + inherited Create(AOwner); + FWidth := 16; + FHeight := 16; + Initialize; +end; + +constructor TCustomImageList.CreateSize(AWidth, AHeight: Integer); +begin + inherited Create(nil); + FWidth := AWidth; + FHeight := AHeight; + Initialize; +end; + +destructor TCustomImageList.Destroy; +begin + while FClients.Count > 0 do + UnRegisterChanges(TChangeLink(FClients.Last)); + FBitmap.Free; + FreeHandle; + FClients.Free; + FClients := nil; + if FMonoBitmap <> nil then FMonoBitmap.Free; + inherited Destroy; +end; + +procedure TCustomImageList.Initialize; +const + MaxSize = 32768; +begin + FClients := TList.Create; + if (Height < 1) or (Height > MaxSize) or (Width < 1) then + raise EInvalidOperation.Create(SInvalidImageSize); + AllocBy := 4; + Masked := True; + DrawingStyle := dsNormal; + ImageType := itImage; + FBkColor := clNone; + FBlendColor := clNone; + FBitmap := TBitmap.Create; + InitBitmap; +end; + +function TCustomImageList.HandleAllocated: Boolean; +begin + Result := FHandle <> 0; +end; + +procedure TCustomImageList.HandleNeeded; +begin + if FHandle = 0 then CreateImageList; +end; + +procedure TCustomImageList.InitBitmap; +var + ScreenDC: HDC; +begin + ScreenDC := GetDC(0); + try + with FBitmap do + begin + Handle := CreateCompatibleBitmap(ScreenDC, Self.Width, Self.Height); + Canvas.Brush.Color := clBlack; + Canvas.FillRect(Rect(0, 0, Width, Height)); + end; + finally + ReleaseDC(0, ScreenDC); + end; + if FMonoBitmap <> nil then + begin + FMonoBitmap.Free; + FMonoBitmap := nil; + end; +end; + +procedure TCustomImageList.SetNewDimensions(Value: HImageList); +var + AHeight, AWidth: Integer; +begin + AWidth := Width; + AHeight := Height; + ImageList_GetIconSize(Value, AWidth, AHeight); + FWidth := AWidth; + FHeight := AHeight; + InitBitmap; +end; + +procedure TCustomImageList.SetWidth(Value: Integer); +begin + if Value <> Width then + begin + FWidth := Value; + if HandleAllocated then ImageList_SetIconSize(FHandle, Width, Height); + Clear; + InitBitmap; + Change; + end; +end; + +procedure TCustomImageList.SetHeight(Value: Integer); +begin + if Value <> Height then + begin + FHeight := Value; + if HandleAllocated then ImageList_SetIconSize(FHandle, Width, Height); + Clear; + InitBitmap; + Change; + end; +end; + +procedure TCustomImageList.SetHandle(Value: HImageList); +begin + FreeHandle; + if Value <> 0 then + begin + SetNewDimensions(Value); + FHandle := Value; + Change; + end; +end; + +function TCustomImageList.GetBitmapHandle(Bitmap: HBITMAP): HBITMAP; +begin + if Bitmap <> 0 then + Result := Bitmap else + Result := FBitmap.Handle; +end; + +function TCustomImageList.GetHandle: HImageList; +begin + HandleNeeded; + Result := FHandle; +end; + +function TCustomImageList.GetImageHandle(Image, ImageDDB: TBitmap): HBITMAP; +begin + CheckImage(Image); + if Image <> nil then + if Image.HandleType = bmDDB then + Result := Image.Handle + else + begin + ImageDDB.Assign(Image); + ImageDDB.HandleType := bmDDB; + Result := ImageDDB.Handle; + end + else Result := FBitmap.Handle; +end; + +procedure TCustomImageList.FreeHandle; +begin + if HandleAllocated and not ShareImages then + ImageList_Destroy(Handle); + FHandle := 0; + Change; +end; + +procedure TCustomImageList.CreateImageList; +const + Mask: array[Boolean] of Longint = (0, ILC_MASK); +begin + FHandle := ImageList_Create(Width, Height, ILC_COLOR or Mask[Masked], + AllocBy, AllocBy); + if FHandle = 0 then raise EInvalidOperation.Create(SInvalidImageList); + if FBkColor <> clNone then BkColor := FBkColor; +end; + +function TCustomImageList.GetImageBitmap: HBITMAP; +var + Info: TImageInfo; +begin + if (Count > 0) and ImageList_GetImageInfo(Handle, 0, Info) then + begin + Result := Info.hbmImage; + DeleteObject(Info.hbmMask); + end + else Result := 0; +end; + +function TCustomImageList.GetMaskBitmap: HBITMAP; +var + Info: TImageInfo; +begin + if (Count > 0) and ImageList_GetImageInfo(Handle, 0, Info) then + begin + Result := Info.hbmMask; + DeleteObject(Info.hbmImage); + end + else Result := 0; +end; + +function TCustomImageList.AddMasked(Image: TBitmap; MaskColor: TColor): Integer; +var + ImageDDB: TBitmap; +begin + ImageDDB := TBitmap.Create; + try + if Masked and (MaskColor <> -1) then + begin + with TBitmap.Create do + try + Assign(Image); + TransparentColor := MaskColor; + Self.HandleNeeded; + Result := ImageList_Add(Self.FHandle, GetImageHandle(Image, ImageDDB), + GetBitmapHandle(MaskHandle)); + finally + Free; + end; + end + else Result := ImageList_Add(Handle, GetImageHandle(Image, ImageDDB), 0); + finally + ImageDDB.Free; + end; + Change; +end; + +function TCustomImageList.AddIcon(Image: TIcon): Integer; +begin + if Image = nil then + Result := Add(nil, nil) + else + begin + CheckImage(Image); + Result := ImageList_AddIcon(Handle, Image.Handle); + end; + Change; +end; + +procedure TCustomImageList.GetIcon(Index: Integer; Image: TIcon); +const + DrawingStyles: array[TDrawingStyle] of Longint = (ILD_FOCUS, + ILD_SELECTED, ILD_NORMAL, ILD_TRANSPARENT); + Images: array[TImageType] of Longint = (0, ILD_MASK); +begin + if (Image <> nil) and HandleAllocated then + Image.Handle := ImageList_GetIcon(Handle, Index, + DrawingStyles[DrawingStyle] or Images[ImageType]); +end; + +function TCustomImageList.GetCount: Integer; +begin + if HandleAllocated then Result := ImageList_GetImageCount(Handle) + else Result := 0; +end; + +procedure TCustomImageList.Replace(Index: Integer; Image, Mask: TBitmap); +var + ImageDDB, MaskDDB: TBitmap; +begin + ImageDDB := TBitmap.Create; + try + MaskDDB := TBitmap.Create; + try + if HandleAllocated and not ImageList_Replace(Handle, Index, + GetImageHandle(Image, ImageDDB), GetImageHandle(Mask, MaskDDB)) then + raise EInvalidOperation.Create(SReplaceImage); + finally + MaskDDB.Free; + end; + finally + ImageDDB.Free; + end; + Change; +end; + +procedure TCustomImageList.ReplaceMasked(Index: Integer; NewImage: TBitmap; MaskColor: TColor); +var + TempIndex: Integer; + Image, Mask: TBitmap; +begin + if HandleAllocated then + begin + CheckImage(NewImage); + TempIndex := AddMasked(NewImage, MaskColor); + if TempIndex <> -1 then + try + Image := TBitmap.Create; + try + with Image do + begin + Height := FHeight; + Width := FWidth; + end; + Mask := TBitmap.Create; + try + with Mask do + begin + Monochrome := True; + Height := FHeight; + Width := FWidth; + end; + ImageList_Draw(Handle, TempIndex, Image.Canvas.Handle, 0, 0, ILD_NORMAL); + ImageList_Draw(Handle, TempIndex, Mask.Canvas.Handle, 0, 0, ILD_MASK); + if not ImageList_Replace(Handle, Index, Image.Handle, Mask.Handle) then + raise EInvalidOperation.Create(SReplaceImage); + finally + Mask.Free; + end; + finally + Image.Free; + end; + finally + Delete(TempIndex); + end + else raise EInvalidOperation.Create(SReplaceImage); + end; + Change; +end; + +procedure TCustomImageList.ReplaceIcon(Index: Integer; Image: TIcon); +begin + if HandleAllocated then + if Image = nil then Replace(Index, nil, nil) + else begin + CheckImage(Image); + if ImageList_ReplaceIcon(Handle, Index, Image.Handle) = -1 then + raise EInvalidOperation.Create(SReplaceImage); + end; + Change; +end; + +procedure TCustomImageList.Delete(Index: Integer); +begin + if Index >= Count then raise EInvalidOperation.Create(SImageIndexError); + if HandleAllocated then ImageList_Remove(Handle, Index); + Change; +end; + +procedure TCustomImageList.Clear; +begin + Delete(-1); +end; + +procedure TCustomImageList.SetBkColor(Value: TColor); +begin + if HandleAllocated then ImageList_SetBkColor(FHandle, GetRGBColor(Value)) + else FBkColor := Value; + Change; +end; + +function TCustomImageList.GetBkColor: TColor; +begin + if HandleAllocated then Result := GetColor(ImageList_GetBkColor(Handle)) + else Result := FBkColor; +end; + +procedure TCustomImageList.DoDraw(Index: Integer; Canvas: TCanvas; X, Y: Integer; + Style: Cardinal; Enabled: Boolean); +const + ROP_DSPDxax = $00E20746; +var + R: TRect; + DestDC, SrcDC: HDC; +begin + if HandleAllocated then + begin + if Enabled then + ImageList_DrawEx(Handle, Index, Canvas.Handle, X, Y, 0, 0, + GetRGBColor(BkColor), GetRGBColor(BlendColor), Style) + else + begin + if FMonoBitmap = nil then + begin + FMonoBitmap := TBitmap.Create; + with FMonoBitmap do + begin + Monochrome := True; + Width := Self.Width; + Height := Self.Height; + end; + end; + { Store masked version of image temporarily in FBitmap } + FMonoBitmap.Canvas.Brush.Color := clWhite; + FMonoBitmap.Canvas.FillRect(Rect(0, 0, Self.Width, Self.Height)); + ImageList_DrawEx(Handle, Index, FMonoBitmap.Canvas.Handle, 0,0,0,0, + CLR_DEFAULT, 0, ILD_NORMAL); + R := Rect(X, Y, X+Width, Y+Height); + SrcDC := FMonoBitmap.Canvas.Handle; + { Convert Black to clBtnHighlight } + Canvas.Brush.Color := clBtnHighlight; + DestDC := Canvas.Handle; + Windows.SetTextColor(DestDC, clWhite); + Windows.SetBkColor(DestDC, clBlack); + BitBlt(DestDC, X+1, Y+1, Width, Height, SrcDC, 0, 0, ROP_DSPDxax); + { Convert Black to clBtnShadow } + Canvas.Brush.Color := clBtnShadow; + DestDC := Canvas.Handle; + Windows.SetTextColor(DestDC, clWhite); + Windows.SetBkColor(DestDC, clBlack); + BitBlt(DestDC, X, Y, Width, Height, SrcDC, 0, 0, ROP_DSPDxax); + end; + end; +end; + +procedure TCustomImageList.Draw(Canvas: TCanvas; X, Y, Index: Integer; + Enabled: Boolean); +const + DrawingStyles: array[TDrawingStyle] of Longint = (ILD_FOCUS, ILD_SELECTED, + ILD_NORMAL, ILD_TRANSPARENT); + Images: array[TImageType] of Longint = (0, ILD_MASK); +begin + if HandleAllocated then + DoDraw(Index, Canvas, X, Y, DrawingStyles[DrawingStyle] or + Images[ImageType], Enabled); +end; + +procedure TCustomImageList.DrawOverlay(Canvas: TCanvas; X, Y: Integer; + ImageIndex: Integer; Overlay: TOverlay; Enabled: Boolean); +const + Images: array[TImageType] of Longint = (0, ILD_MASK); +var + Index: Integer; +begin + if HandleAllocated then + begin + Index := IndexToOverlayMask(Overlay + 1); + DoDraw(ImageIndex, Canvas, X, Y, Images[ImageType] or ILD_OVERLAYMASK and + Index, Enabled); + end; +end; + +function TCustomImageList.Overlay(ImageIndex: Integer; Overlay: TOverlay): Boolean; +begin + if HandleAllocated then + Result := ImageList_SetOverlayImage(Handle, ImageIndex, Overlay + 1) + else Result := False; +end; + +procedure TCustomImageList.CopyImages(Value: HImageList); +var + I: Integer; + Image, Mask: TBitmap; + ARect: TRect; +begin + ARect := Rect(0, 0, Width, Height); + BeginUpdate; + try + Image := TBitmap.Create; + try + with Image do + begin + Height := FHeight; + Width := FWidth; + end; + Mask := TBitmap.Create; + try + with Mask do + begin + Monochrome := True; + Height := FHeight; + Width := FWidth; + end; + for I := 0 to ImageList_GetImageCount(Value) - 1 do + begin + with Image.Canvas do + begin + FillRect(ARect); + ImageList_Draw(Value, I, Handle, 0, 0, ILD_NORMAL); + end; + with Mask.Canvas do + begin + FillRect(ARect); + ImageList_Draw(Value, I, Handle, 0, 0, ILD_MASK); + end; + Add(Image, Mask); + end; + finally + Mask.Free; + end; + finally + Image.Free; + end; + finally + EndUpdate; + end; +end; + +procedure TCustomImageList.GetImages(Index: Integer; Image, Mask: TBitmap); +var + R: TRect; +begin + R := Rect(0, 0, Width, Height); + with Image.Canvas do + begin + Brush.Color := clWhite; + FillRect(R); + ImageList_Draw(Self.Handle, Index, Handle, 0, 0, ILD_NORMAL); + end; + with Mask.Canvas do + begin + Brush.Color := clWhite; + FillRect(R); + ImageList_Draw(Self.Handle, Index, Handle, 0, 0, ILD_MASK); + end; +end; + +procedure TCustomImageList.InsertImage(Index: Integer; Image, Mask: TBitmap; + MaskColor: TColor); +var + I: Integer; + OldImage, OldMask: TBitmap; + TempList: TCustomImageList; +begin + BeginUpdate; + try + OldImage := TBitmap.Create; + try + with OldImage do + begin + Height := FHeight; + Width := FWidth; + end; + OldMask := TBitmap.Create; + try + with OldMask do + begin + Monochrome := True; + Height := FHeight; + Width := FWidth; + end; + TempList := TCustomImageList.CreateSize(5, 5); + try + TempList.Assign(Self); + Clear; + if Index > TempList.Count then + raise EInvalidOperation.Create(SImageIndexError); + for I := 0 to Index - 1 do + begin + TempList.GetImages(I, OldImage, OldMask); + Add(OldImage, OldMask); + end; + if MaskColor <> -1 then + AddMasked(Image, MaskColor) else + Add(Image, Mask); + for I := Index to TempList.Count - 1 do + begin + TempList.GetImages(I, OldImage, OldMask); + Add(OldImage, OldMask); + end; + finally + TempList.Free; + end; + finally + OldMask.Free; + end; + finally + OldImage.Free; + end; + finally + EndUpdate; + end; +end; + +procedure TCustomImageList.Insert(Index: Integer; Image, Mask: TBitmap); +begin + InsertImage(Index, Image, Mask, -1); +end; + +procedure TCustomImageList.InsertMasked(Index: Integer; Image: TBitmap; + MaskColor: TColor); +begin + InsertImage(Index, Image, nil, MaskColor); +end; + +procedure TCustomImageList.InsertIcon(Index: Integer; Image: TIcon); +var + I: Integer; + TempList: TCustomImageList; + Icon: TIcon; +begin + Icon := TIcon.Create; + TempList := TCustomImageList.CreateSize(5, 5); + TempList.Assign(Self); + Clear; + if Index > TempList.Count then raise EInvalidOperation.Create(SImageIndexError); + BeginUpdate; + try + for I := 0 to Index - 1 do + begin + TempList.GetIcon(I, Icon); + AddIcon(Icon); + end; + AddIcon(Image); + for I := Index to TempList.Count - 1 do + begin + TempList.GetIcon(I, Icon); + AddIcon(Icon); + end; + finally + TempList.Free; + EndUpdate; + end; +end; + +procedure TCustomImageList.Move(CurIndex, NewIndex: Integer); +var + Image, Mask: TBitmap; +begin + if CurIndex <> NewIndex then + begin + Image := TBitmap.Create; + try + with Image do + begin + Height := FHeight; + Width := FWidth; + end; + Mask := TBitmap.Create; + try + with Mask do + begin + Height := FHeight; + Width := FWidth; + end; + GetImages(CurIndex, Image, Mask); + Delete(CurIndex); + Insert(NewIndex, Image, Mask); + finally + Mask.Free; + end; + finally + Image.Free; + end; + end; +end; + +procedure TCustomImageList.AddImages(Value: TCustomImageList); +begin + if Value <> nil then CopyImages(Value.Handle); +end; + +procedure TCustomImageList.Assign(Source: TPersistent); +var + ImageList: TCustomImageList; +begin + if Source = nil then FreeHandle + else if Source is TCustomImageList then + begin + Clear; + ImageList := TCustomImageList(Source); + Masked := ImageList.Masked; + ImageType := ImageList.ImageType; + DrawingStyle := ImageList.DrawingStyle; + ShareImages := ImageList.ShareImages; + SetNewDimensions(ImageList.Handle); + if not HandleAllocated then HandleNeeded + else ImageList_SetIconSize(Handle, Width, Height); + BkColor := GetColor(ImageList_GetBkColor(ImageList.Handle)); + BlendColor := ImageList.BlendColor; + AddImages(ImageList); + end + else inherited Assign(Source); +end; + +procedure TCustomImageList.AssignTo(Dest: TPersistent); +var + ImageList: TCustomImageList; +begin + if Dest is TCustomImageList then + begin + ImageList := TCustomImageList(Dest); + ImageList.Masked := Masked; + ImageList.ImageType := ImageType; + ImageList.DrawingStyle := DrawingStyle; + ImageList.ShareImages := ShareImages; + ImageList.BlendColor := BlendColor; + with ImageList do + begin + Clear; + SetNewDimensions(Self.Handle); + if not HandleAllocated then HandleNeeded + else ImageList_SetIconSize(Handle, Width, Height); + BkColor := GetColor(ImageList_GetBkColor(Self.Handle)); + AddImages(Self); + end; + end + else inherited AssignTo(Dest); +end; + +procedure TCustomImageList.CheckImage(Image: TGraphic); +begin + if Image = nil then Exit; + with Image do + if (Height < FHeight) or (Width < FWidth) then + raise EInvalidOperation.Create(SInvalidImageSize); +end; + +procedure TCustomImageList.SetDrawingStyle(Value: TDrawingStyle); +begin + if Value <> DrawingStyle then + begin + FDrawingStyle := Value; + Change; + end; +end; + +function TCustomImageList.GetHotSpot: TPoint; +begin + Result := Point(0, 0); +end; + +function TCustomImageList.GetInstRes(Instance: THandle; ResType: TResType; + Name: string; Width: Integer; LoadFlags: TLoadResources; MaskColor: TColor): + Boolean; +const + ResMap: array [TResType] of Integer = (IMAGE_BITMAP, IMAGE_CURSOR, IMAGE_ICON); +var + hImage: HImageList; + Flags: Integer; +begin + Flags := 0; + if lrDefaultColor in LoadFlags then Flags := Flags or LR_DEFAULTCOLOR; + if lrDefaultSize in LoadFlags then Flags := Flags or LR_DEFAULTSIZE; + if lrFromFile in LoadFlags then Flags := Flags or LR_LOADFROMFILE; + if lrMap3DColors in LoadFlags then Flags := Flags or LR_LOADMAP3DCOLORS; + if lrTransparent in LoadFlags then Flags := Flags or LR_LOADTRANSPARENT; + if lrMonoChrome in LoadFlags then Flags := Flags or LR_MONOCHROME; + hImage := ImageList_LoadImage(Instance, PChar(Name), Width, AllocBy, + MaskColor, ResMap[ResType], Flags); + if hImage <> 0 then + begin + CopyImages(hImage); + ImageList_Destroy(hImage); + Result := True; + end + else Result := False; +end; + +function TCustomImageList.GetResource(ResType: TResType; Name: string; + Width: Integer; LoadFlags: TLoadResources; MaskColor: TColor): Boolean; +begin + Result := GetInstRes(MainInstance, ResType, Name, Width, LoadFlags, MaskColor); +end; + +function TCustomImageList.ResInstLoad(Instance: THandle; ResType: TResType; + Name: string; MaskColor: TColor): Boolean; +begin + Result := GetInstRes(Instance, ResType, Name, Width, [], MaskColor); +end; + +function TCustomImageList.ResourceLoad(ResType: TResType; Name: string; + MaskColor: TColor): Boolean; +var + LibModule: PLibModule; +begin + Result := False; + if HInstance = MainInstance then + Result := GetInstRes(MainInstance, ResType, Name, Width, [], MaskColor) + else + begin + LibModule := LibModuleList; + while LibModule <> nil do + with LibModule^ do + begin + Result := GetInstRes(ResInstance, ResType, Name, Width, [], MaskColor); + if not Result and (Instance <> ResInstance) then + Result := GetInstRes(Instance, ResType, Name, Width, [], MaskColor); + if Result then Exit; + LibModule := LibModule.Next; + end; + end; +end; + +function TCustomImageList.FileLoad(ResType: TResType; Name: string; + MaskColor: TColor): Boolean; +begin + Result := GetResource(ResType, Name, Width, [lrFromFile], MaskColor); +end; + +procedure TCustomImageList.Change; +var + I: Integer; +begin + FChanged := True; + if FUpdateCount > 0 then Exit; + if FClients <> nil then + for I := 0 to FClients.Count - 1 do + TChangeLink(FClients[I]).Change; + if Assigned(FOnChange) then FOnChange(Self); +end; + +procedure TCustomImageList.UnRegisterChanges(Value: TChangeLink); +var + I: Integer; +begin + if FClients <> nil then + for I := 0 to FClients.Count - 1 do + if FClients[I] = Value then + begin + Value.Sender := nil; + FClients.Delete(I); + Break; + end; +end; + +procedure TCustomImageList.RegisterChanges(Value: TChangeLink); +begin + Value.Sender := Self; + if FClients <> nil then FClients.Add(Value); +end; + +function TCustomImageList.Equal(IL: TCustomImageList): Boolean; + + function StreamsEqual(S1, S2: TMemoryStream): Boolean; + begin + Result := (S1.Size = S2.Size) and CompareMem(S1.Memory, S2.Memory, S1.Size); + end; + +var + MyImage, OtherImage: TMemoryStream; +begin + if (IL = nil) or (Count <> IL.Count) then + begin + Result := False; + Exit; + end; + if (Count = 0) and (IL.Count = 0) then + begin + Result := True; + Exit; + end; + MyImage := TMemoryStream.Create; + try + WriteData(MyImage); + OtherImage := TMemoryStream.Create; + try + IL.WriteData(OtherImage); + Result := StreamsEqual(MyImage, OtherImage); + finally + OtherImage.Free; + end; + finally + MyImage.Free; + end; +end; + +procedure TCustomImageList.DefineProperties(Filer: TFiler); + + function DoWrite: Boolean; + begin + if Filer.Ancestor <> nil then + Result := not (Filer.Ancestor is TCustomImageList) or + not Equal(TCustomImageList(Filer.Ancestor)) + else + Result := Count > 0; + end; + +begin + inherited DefineProperties(Filer); + Filer.DefineBinaryProperty('Bitmap', ReadData, WriteData, DoWrite); +end; + +procedure TCustomImageList.ReadD2Stream(Stream: TStream); +var + FullImage, Image, FullMask, Mask: TBitmap; + I, J, Size, Pos, Count: Integer; + SrcRect: TRect; +begin + Stream.ReadBuffer(Size, SizeOf(Size)); + Stream.ReadBuffer(Count, SizeOf(Count)); + FullImage := TBitmap.Create; + try + Pos := Stream.Position; + FullImage.LoadFromStream(Stream); + Stream.Position := Pos + Size; + FullMask := TBitmap.Create; + try + FullMask.LoadFromStream(Stream); + Image := TBitmap.Create; + Image.Width := Width; + Image.Height := Height; + Mask := TBitmap.Create; + Mask.Monochrome := True; + Mask.Width := Width; + Mask.Height := Height; + SrcRect := Rect(0, 0, Width, Height); + BeginUpdate; + try + for J := 0 to (FullImage.Height div Height) - 1 do + begin + if Count = 0 then Break; + for I := 0 to (FullImage.Width div Width) - 1 do + begin + if Count = 0 then Break; + Image.Canvas.CopyRect(SrcRect, FullImage.Canvas, + Bounds(I * Width, J * Height, Width, Height)); + Mask.Canvas.CopyRect(SrcRect, FullMask.Canvas, + Bounds(I * Width, J * Height, Width, Height)); + Add(Image, Mask); + Dec(Count); + end; + end; + finally + Image.Free; + Mask.Free; + EndUpdate; + end; + finally + FullMask.Free; + end; + finally + FullImage.Free; + end; +end; + +procedure TCustomImageList.ReadD3Stream(Stream: TStream); +var + SA: TStreamAdapter; +begin + SA := TStreamAdapter.Create(Stream); + try + Handle := ImageList_Read(SA); + if Handle = 0 then + raise EReadError.Create(SImageReadFail); + finally + SA.Free; + end; +end; + +procedure TCustomImageList.ReadData(Stream: TStream); +var + CheckInt1, CheckInt2: Integer; + CheckByte1, CheckByte2: Byte; + StreamPos: Integer; +begin + FreeHandle; + StreamPos := Stream.Position; // check stream signature to + Stream.Read(CheckInt1, SizeOf(CheckInt1)); // determine a Delphi 2 or Delphi + Stream.Read(CheckInt2, SizeOf(CheckInt2)); // 3 imagelist stream. Delphi 2 + CheckByte1 := Lo(LoWord(CheckInt1)); // streams can be read, but only + CheckByte2 := Hi(LoWord(CheckInt1)); // Delphi 3 streams will be written + Stream.Position := StreamPos; + if (CheckInt1 <> CheckInt2) and (CheckByte1 = $49) and (CheckByte2 = $4C) then + ReadD3Stream(Stream) + else + ReadD2Stream(Stream); +end; + +procedure TCustomImageList.WriteData(Stream: TStream); +var + SA: TStreamAdapter; +begin + SA := TStreamAdapter.Create(Stream); + try + if not ImageList_Write(Handle, SA) then + raise EWriteError.Create(SImageWriteFail); + finally + SA.Free; + end; +end; +(* +var + I: Integer; + DIB1, DIB2: TBitmap; + DC: HDC; + S: TMemoryStream; + + procedure WriteDIB(BM: HBitmap); + { The ImageList leaves its bitmap handle selected into a DC somewhere, + so we can't select it into our own DC to copy from it. The only safe + operation is GetDIB (GetDIBits), which extracts the pixel bits without + selecting the BM into a DC. This code builds our own bitmap from + those bits, then crops it to the minimum size before writing it out.} + var + BitsSize: DWORD; + Header, Bits: PChar; + DIBBits: Pointer; + R: TRect; + HeaderSize: DWORD; + GlyphsPerRow, Rows: Integer; + begin + if BM = 0 then Exit; + GetDIBSizes(BM, HeaderSize, BitsSize); + GetMem(Header, HeaderSize + BitsSize); + try + Bits := Header + HeaderSize; + GetDIB(BM, 0, Header^, Bits^); + DIB1.Handle := CreateDIBSection(DC, PBitmapInfo(Header)^, DIB_RGB_COLORS, DIBBits, 0, 0); + System.Move(Bits^, DIBBits^, BitsSize); + with PBitmapInfo(Header)^.bmiHeader do + begin + GlyphsPerRow := biWidth div Width; + if GlyphsPerRow = 0 then Inc(GlyphsPerRow); + if GlyphsPerRow > Count then GlyphsPerRow := Count; + biWidth := GlyphsPerRow * Width; + Rows := Count div GlyphsPerRow; + if Count > Rows * GlyphsPerRow then Inc(Rows); + biHeight := Rows * Height; + R := Rect(0, 0, biWidth, biHeight); + end; + DIB2.Handle := CreateDIBSection(DC, PBitmapInfo(Header)^, DIB_RGB_COLORS, DIBBits, 0, 0); + DIB2.Canvas.CopyRect(R, DIB1.Canvas, R); + DIB2.SaveToStream(S); + finally + FreeMem(Header); + end; + end; + +begin + DIB1 := nil; + DIB2 := nil; + DC := 0; + S := TMemoryStream.Create; + try + DIB1 := TBitmap.Create; + DIB2 := TBitmap.Create; + DC := GetDC(0); + WriteDIB(GetImageBitmap); + I := S.Size; + WriteDIB(GetMaskBitmap); + Stream.WriteBuffer(I, sizeof(I)); + I := Count; + Stream.WriteBuffer(I, sizeof(I)); + Stream.WriteBuffer(S.Memory^, S.Size); + finally + ReleaseDC(0, DC); + DIB1.Free; + DIB2.Free; + S.Free; + end; +end; +*) +procedure TCustomImageList.BeginUpdate; +begin + Inc(FUpdateCount); +end; + +procedure TCustomImageList.EndUpdate; +begin + if FUpdateCount > 0 then Dec(FUpdateCount); + if FChanged then + begin + FChanged := False; + Change; + end; +end; +*/ |