Looking for a custom image grid

10,586

Solution 1

For the fun of it, I wrote an ImageGrid component for you.

ImageGrid example

It has only a vertical scroll bar; resizing the width of the control adjusts the column count and row count. The images are cached as resized bitmaps in an internal list, along with their file names.

Because loading and resampling these images may take some time, depending on image count, resolution and whether you want to use the Graphics32 library for better resample quality, the component delegates the loading process to a separate thread, which (re)runs on setting the column width or the row height, and on changing the file names or the folder path in which the component tries to find all images of types to be supplied in the FileFormats property.

Features:

  • Creates and resizes image thumbs in a background thread, from file names with the GDI+ library or from manually added images with the Graphics 32 library
  • Automatically recognizes all registered image file formats
  • Animated scrolling
  • Touchscreen support for scrolling by dragging the grid
  • Keyboard support for selecting thumbs
  • OwnerDraw support, e.g. for adding captions to the thumbs
  • Virtual support for bypassing the automatic creation of thumbs

Properties and events:

  • ColCount: number of columns, readonly
  • Count: number of images, readonly
  • Images: list of all manually added images where the thumbs are internally created from
  • Items: list of all filename-thumbnail or image-thumbnail combinations
  • RowCount: number of rows, readonly
  • Thumbs: list of all internally created thumbs
  • AutoHideScrollBar: hides the scroll bar when all rows are visible
  • BorderStyle: shows or hides themed border
  • BorderWidth: margin of the component, outside of the scroll bar
  • CellAlignment: alignes thumbs at the left, center or right of the cell
  • CellHeight: height of cell
  • CellLayout: alignes thumbs at the top, middle or bottom of the cell
  • CellSpacing: spacing between the cells
  • CellWidth: width of cell
  • Color: background color of border and cell spacing
  • ColWidth: width of column (equals width of cell plus cell spacing)
  • DefaultDrawing: draws all thumbs by default
  • DesignPreview: shows thumbs in the designer
  • DragScroll: supports scrolling the grid by draging the grid
  • FileFormats: image file name extensions by which the file names are filtered
  • FileNames: list holding all file names
  • Folder: the directory in which the component tries to find all images files
  • ItemIndex: selected cell index
  • MarkerColor: color of temporarily thumb marker during loading process
  • MarkerStyle: style of temporarily thumb marker during loading process
  • OnClickCell: fires when a cell is clicked
  • OnDrawCell: fires when a cell is drawn
  • OnMeasureThumb: fires when the size of a thumb is to be calculated
  • OnProgress: fires when an image is resized to thumb format
  • OnUnresolved: fires when a thumb cannot be created, e.g. when file name is not found
  • RetainUnresolvedItems: keeps empty thumbs in the list
  • RowHeight: the row height (equals cell height plus cell spacing)
  • ParentBackground: draws the (themed) background of the parent in the border and between the cells
  • Proportional: resizes images proportionally
  • Sorted: file names are sorted
  • Stretch: stretches small images up to the cell size
  • VirtualMode: prevents of automatically creating the thumbs
  • WheelScrollLines: number of rows to be scrolled with mouse wheel

With thanks to:

The code is too long to post here, but the OpenSource project is downloadable from the GitHub server here. This is the interface section:

unit AwImageGrid;

interface

{$DEFINE USE_GR32}

uses
  Windows, Classes, SysUtils, Messages, Controls, Graphics, Forms, StdCtrls,
  Grids, GDIPAPI, GDIPOBJ, RTLConsts, Math, Themes
  {$IFDEF USE_GR32}, GR32, GR32_Resamplers {$ENDIF};

const
  DefCellSpacing = 5;
  DefCellWidth = 96;
  DefCellHeight = 60;
  DefColWidth = DefCellWidth + DefCellSpacing;
  DefRowHeight = DefCellHeight + DefCellSpacing;
  MinThumbSize = 4;
  MinCellSize = 8;

type
  PImageGridItem = ^TImageGridItem;
  TImageGridItem = record
    FFileName: TFileName;
    FObject: TObject;
    FImage: TGraphic;
    FThumb: TBitmap;
  end;

  PImageGridItemList = ^TImageGridItemList;
  TImageGridItemList = array[0..MaxListSize div 2] of TImageGridItem;

{ TImageGridItems
  The managing object for holding filename-thumbnail or image-thumbnail
  combinations in an array of TImageGridItem elements. When an item's image
  changes, the item's thumb is freed. When an item's filename changes, then
  the item's thumb is freed only if the item's image is unassigned. }

  TImageGridItems = class(TStrings)
  private
    FCapacity: Integer;
    FChanged: Boolean;
    FCount: Integer;
    FList: PImageGridItemList;
    FOnChanged: TNotifyEvent;
    FOnChanging: TNotifyEvent;
    FOwnsObjects: Boolean;
    FSorted: Boolean;
    procedure ExchangeItems(Index1, Index2: Integer);
    function GetImage(Index: Integer): TGraphic;
    function GetThumb(Index: Integer): TBitmap;
    procedure Grow;
    procedure InsertItem(Index: Integer; const S: String; AObject: TObject;
      AImage: TGraphic; AThumb: TBitmap);
    procedure PutImage(Index: Integer; AImage: TGraphic);
    procedure PutThumb(Index: Integer; AThumb: TBitmap);
    procedure QuickSort(L, R: Integer);
    procedure SetSorted(Value: Boolean);
  protected
    function CompareStrings(const S1, S2: String): Integer; override;
    procedure Changed; virtual;
    procedure Changing; virtual;
    function Get(Index: Integer): String; override;
    function GetCapacity: Integer; override;
    function GetCount: Integer; override;
    function GetObject(Index: Integer): TObject; override;
    procedure Put(Index: Integer; const S: String); override;
    procedure PutObject(Index: Integer; AObject: TObject); override;
    procedure PutThumbSilently(Index: Integer; AThumb: TBitmap); virtual;
    procedure SetCapacity(Value: Integer); override;
    procedure SetUpdateState(Updating: Boolean); override;
  public
    function Add(const S: String): Integer; override;
    function AddImage(const S: String; AImage: TGraphic): Integer; virtual;
    function AddItem(const S: String; AObject: TObject; AImage: TGraphic;
      AThumb: TBitmap): Integer; virtual;
    function AddObject(const S: String; AObject: TObject): Integer; override;
    function AddThumb(const S: String; AThumb: TBitmap): Integer; virtual;
    procedure AddStrings(Strings: TStrings); override;
    procedure Assign(Source: TPersistent); override;
    procedure Clear; override;
    procedure ClearThumbs; virtual;
    procedure Delete(Index: Integer); override;
    destructor Destroy; override;
    procedure Exchange(Index1, Index2: Integer); override;
    function IndexOf(const S: String): Integer; override;
    procedure Insert(Index: Integer; const S: String); override;
    procedure InsertObject(Index: Integer; const S: String;
      AObject: TObject); override;
    function Find(const S: String; var Index: Integer): Boolean;
    procedure Sort; virtual;
    property FileNames[Index: Integer]: String read Get write Put;
    property Images[Index: Integer]: TGraphic read GetImage write PutImage;
    property OnChanged: TNotifyEvent read FOnChanged write FOnChanged;
    property OnChanging: TNotifyEvent read FOnChanging write FOnChanging;
    property OwnsObjects: Boolean read FOwnsObjects write FOwnsObjects;
    property Sorted: Boolean read FSorted write SetSorted;
    property Thumbs[Index: Integer]: TBitmap read GetThumb write PutThumb;
  end;

{ TBorderControl
  A control with a system drawn border following the current theme, and an
  additional margin as implemented by TWinControl.BorderWidth. }

  TBorderControl = class(TCustomControl)
  private
    FBorderStyle: TBorderStyle;
    procedure SetBorderStyle(Value: TBorderStyle);
    procedure WMNCPaint(var Message: TWMNCPaint); message WM_NCPAINT;
    procedure CMCtl3DChanged(var Message: TMessage); message CM_CTL3DCHANGED;
  protected
    procedure CreateParams(var Params: TCreateParams); override;
    function TotalBorderWidth: Integer; virtual;
  public
    constructor Create(AOwner: TComponent); override;
    property BorderStyle: TBorderStyle read FBorderStyle write SetBorderStyle
      default bsSingle;
    property BorderWidth;
  end;

{ TAnimRowScroller
  A scroll box with a vertical scroll bar and vertically stacked items with a
  fixed row height. Scrolling with the scroll bar is animated alike Windows'
  own default list box control. Scrolling is also possible by dragging the
  content with the left mouse button. }

  TAnimRowScroller = class(TBorderControl)
  private
    FAutoHideScrollBar: Boolean;
    FDragScroll: Boolean;
    FDragScrolling: Boolean;
    FDragSpeed: Single;
    FDragStartPos: Integer;
    FPrevScrollPos: Integer;
    FPrevTick: Cardinal;
    FRow: Integer;
    FRowCount: Integer;
    FRowHeight: Integer;
    FScrollingPos: Integer;
    FScrollPos: Integer;
    FWheelScrollLines: Integer;
    procedure Drag;
    function IsWheelScrollLinesStored: Boolean;
    procedure Scroll;
    procedure SetAutoHideScrollBar(Value: Boolean);
    procedure SetRow(Value: Integer);
    procedure SetRowCount(Value: Integer);
    procedure SetScrollPos(Value: Integer; Animate, Snap: Boolean);
    procedure UpdateScrollBar;
    procedure WMVScroll(var Message: TWMVScroll); message WM_VSCROLL;
  protected
    procedure CreateWnd; override;
    function DoMouseWheel(Shift: TShiftState; WheelDelta: Integer;
      MousePos: TPoint): Boolean; override;
    procedure DrawFocusRect; virtual;
    procedure MouseDown(Button: TMouseButton; Shift: TShiftState; X,
      Y: Integer); override;
    procedure MouseMove(Shift: TShiftState; X, Y: Integer); override;
    procedure MouseUp(Button: TMouseButton; Shift: TShiftState; X,
      Y: Integer); override;
    procedure Resize; override;
    procedure SetRowHeight(Value: Integer); virtual;
    procedure WndProc(var Message: TMessage); override;
    property AutoHideScrollBar: Boolean read FAutoHideScrollBar
      write SetAutoHideScrollBar default True;
    property Row: Integer read FRow write SetRow default -1;
    property RowCount: Integer read FRowCount write SetRowCount;
    property RowHeight: Integer read FRowHeight write SetRowHeight
      default DefRowHeight;
    property DragScroll: Boolean read FDragScroll write FDragScroll
      default True;
    property DragScrolling: Boolean read FDragScrolling;
    property ScrollingPos: Integer read FScrollingPos;
    property WheelScrollLines: Integer read FWheelScrollLines
      write FWheelScrollLines stored IsWheelScrollLinesStored;
  public
    constructor Create(AOwner: TComponent); override;
    procedure MouseWheelHandler(var Message: TMessage); override;
    function Scrolling: Boolean;
  end;

{ TCustomImageGrid
  The base class of an image grid. It shows images from left to right, then
  from top to bottom. The number of columns is determined by the width of the
  control, possibly resulting in a vertical scroll bar. The coord size is set
  by ColWidth and RowHeight, being the sum of CellWidth resp. CellHeight plus
  CellSpacing. Each cell shows a thumb of the corresponding image. The control
  automatically starts a thumbs generating background thread when an image's
  graphic, filename or its cell size is changed. Before every such change, any
  previously created thread is terminated. Combine multiple changes by calling
  Items.BeginUpdate/Items.EndUpdate to prevent the thread from being recreated
  repeatedly. }

  TCustomImageGrid = class;

  TPath = type String;

  TDrawCellEvent = procedure(Sender: TCustomImageGrid; Index, ACol,
    ARow: Integer; R: TRect) of object;

  TImageEvent = procedure(Sender: TCustomImageGrid; Index: Integer) of object;

  TMeasureThumbEvent = procedure(Sender: TCustomImageGrid; Index: Integer;
    var AThumbWidth, AThumbHeight: Integer) of object;

  TCustomImageGrid = class(TAnimRowScroller)
  private
    FCellAlignment: TAlignment;
    FCellLayout: TTextLayout;
    FCellSpacing: Integer;
    FColCount: Integer;
    FColWidth: Integer;
    FDefaultDrawing: Boolean;
    FDesignPreview: Boolean;
    FFileFormats: TStrings;
    FFolder: TPath;
    FItemIndex: Integer;
    FItems: TImageGridItems;
    FMarkerColor: TColor;
    FMarkerStyle: TPenStyle;
    FOnClickCell: TImageEvent;
    FOnDrawCell: TDrawCellEvent;
    FOnMeasureThumb: TMeasureThumbEvent;
    FOnProgress: TImageEvent;
    FOnUnresolved: TImageEvent;
    FProportional: Boolean;
    FRetainUnresolvedItems: Boolean;
    FStretch: Boolean;
    FThumbsGenerator: TThread;
    FVirtualMode: Boolean;
    procedure DeleteUnresolvedItems;
    procedure FileFormatsChanged(Sender: TObject);
    function GetCellHeight: Integer;
    function GetCellWidth: Integer;
    function GetCount: Integer;
    function GetFileNames: TStrings;
    function GetImage(Index: Integer): TGraphic;
    function GetRowCount: Integer;
    function GetSorted: Boolean;
    function GetThumb(Index: Integer): TBitmap;
    function IsFileNamesStored: Boolean;
    procedure ItemsChanged(Sender: TObject);
    procedure ItemsChanging(Sender: TObject);
    procedure Rearrange;
    procedure SetCellAlignment(Value: TAlignment);
    procedure SetCellHeight(Value: Integer);
    procedure SetCellLayout(Value: TTextLayout);
    procedure SetCellSpacing(Value: Integer);
    procedure SetCellWidth(Value: Integer);
    procedure SetColWidth(Value: Integer);
    procedure SetDefaultDrawing(Value: Boolean);
    procedure SetDesignPreview(Value: Boolean);
    procedure SetFileFormats(Value: TStrings);
    procedure SetFileNames(Value: TStrings);
    procedure SetFolder(Value: TPath);
    procedure SetImage(Index: Integer; Value: TGraphic);
    procedure SetItemIndex(Value: Integer);
    procedure SetItems(Value: TImageGridItems);
    procedure SetMarkerColor(Value: TColor);
    procedure SetMarkerStyle(Value: TPenStyle);
    procedure SetProportional(Value: Boolean);
    procedure SetRetainUnresolvedItems(Value: Boolean);
    procedure SetSorted(Value: Boolean);
    procedure SetStretch(Value: Boolean);
    procedure SetThumb(Index: Integer; Value: TBitmap);
    procedure SetVirtualMode(Value: Boolean);
    procedure TerminateThumbsGenerator;
    procedure ThumbsUpdated(Sender: TObject);
    procedure UpdateThumbs;
    procedure WMEraseBkgnd(var Message: TWMEraseBkgnd); message WM_ERASEBKGND;
    procedure WMGetDlgCode(var Message: TWMGetDlgCode); message WM_GETDLGCODE;
    procedure CMEnter(var Message: TCMEnter); message CM_ENTER;
    procedure CMExit(var Message: TCMExit); message CM_EXIT;
  protected
    procedure ChangeScale(M, D: Integer); override;
    procedure DoClickCell(Index: Integer); virtual;
    procedure DoDrawCell(Index, ACol, ARow: Integer; R: TRect); virtual;
    procedure DoMeasureThumb(Index: Integer; var AThumbWidth,
      AThumbHeight: Integer); virtual;
    procedure DoProgress(Index: Integer); virtual;
    procedure DrawFocusRect; override;
    procedure InvalidateItem(Index: Integer); virtual;
    procedure KeyDown(var Key: Word; Shift: TShiftState); override;
    procedure Loaded; override;
    procedure MouseDown(Button: TMouseButton; Shift: TShiftState; X,
      Y: Integer); override;
    procedure MouseUp(Button: TMouseButton; Shift: TShiftState; X,
      Y: Integer); override;
    procedure Paint; override;
    procedure Resize; override;
    procedure SetRowHeight(Value: Integer); override;
    property CellAlignment: TAlignment read FCellAlignment
      write SetCellAlignment default taCenter;
    property CellHeight: Integer read GetCellHeight write SetCellHeight
      default DefCellHeight;
    property CellLayout: TTextLayout read FCellLayout write SetCellLayout
      default tlCenter;
    property CellSpacing: Integer read FCellSpacing write SetCellSpacing
      default DefCellSpacing;
    property CellWidth: Integer read GetCellWidth write SetCellWidth
      default DefCellWidth;
    property ColCount: Integer read FColCount;
    property ColWidth: Integer read FColWidth write SetColWidth
      default DefColWidth;
    property Count: Integer read GetCount;
    property DefaultDrawing: Boolean read FDefaultDrawing
      write SetDefaultDrawing default True;
    property DesignPreview: Boolean read FDesignPreview write SetDesignPreview
      default False;
    property FileFormats: TStrings read FFileFormats write SetFileFormats;
    property FileNames: TStrings read GetFileNames write SetFileNames
      stored IsFileNamesStored;
    property Folder: TPath read FFolder write SetFolder;
    property Images[Index: Integer]: TGraphic read GetImage write SetImage;
    property ItemIndex: Integer read FItemIndex write SetItemIndex default -1;
    property Items: TImageGridItems read FItems write SetItems;
    property MarkerColor: TColor read FMarkerColor write SetMarkerColor
      default clGray;
    property MarkerStyle: TPenStyle read FMarkerStyle write SetMarkerStyle
      default psDash;
    property OnClickCell: TImageEvent read FOnClickCell write FOnClickCell;
    property OnDrawCell: TDrawCellEvent read FOnDrawCell write FOnDrawCell;
    property OnMeasureThumb: TMeasureThumbEvent read FOnMeasureThumb
      write FOnMeasureThumb;
    property OnProgress: TImageEvent read FOnProgress write FOnProgress;
    property OnUnresolved: TImageEvent read FOnUnresolved write FOnUnresolved;
    property Proportional: Boolean read FProportional write SetProportional
      default True;
    property RetainUnresolvedItems: Boolean read FRetainUnresolvedItems
      write SetRetainUnresolvedItems default False;
    property RowCount: Integer read GetRowCount;
    property Sorted: Boolean read GetSorted write SetSorted default False;
    property Stretch: Boolean read FStretch write SetStretch default False;
    property Thumbs[Index: Integer]: TBitmap read GetThumb write SetThumb;
    property VirtualMode: Boolean read FVirtualMode write SetVirtualMode
      default False;
  public
    constructor Create(AOwner: TComponent); override;
    destructor Destroy; override;
    function CellRect(Index: Integer): TRect;
    function CoordFromIndex(Index: Integer): TGridCoord;
    procedure Clear; virtual;
    function MouseToIndex(X, Y: Integer): Integer;
    procedure ScrollInView(Index: Integer);
    procedure SetCellSize(ACellWidth, ACellHeight: Integer);
    procedure SetCoordSize(AColWidth, ARowHeight: Integer);
    property ParentBackground default False;
  public
    property TabStop default True;
  end;

  TAwImageGrid = class(TCustomImageGrid)
  public
    property ColCount;
    property Count;
    property Images;
    property Items;
    property RowCount;
    property Thumbs;
  published
    property Align;
    property Anchors;
    property AutoHideScrollBar;
    property BorderStyle;
    property BorderWidth;
    property CellAlignment;
    property CellHeight;
    property CellLayout;
    property CellSpacing;
    property CellWidth;
    property ClientHeight;
    property ClientWidth;
    property Color;
    property ColWidth;
    property Constraints;
    property Ctl3D;
    property DefaultDrawing;
    property DesignPreview;
    property DragCursor;
    property DragKind;
    property DragMode;
    property DragScroll;
    property Enabled;
    property FileFormats;
    property FileNames;
    property Folder;
    property ItemIndex;
    property MarkerColor;
    property MarkerStyle;
    property OnCanResize;
    property OnClick;
    property OnClickCell;
    property OnConstrainedResize;
    property OnContextPopup;
    property OnDblClick;
    property OnDockDrop;
    property OnDockOver;
    property OnDragDrop;
    property OnDragOver;
    property OnDrawCell;
    property OnEndDock;
    property OnEndDrag;
    property OnEnter;
    property OnExit;
    property OnGetSiteInfo;
    property OnKeyDown;
    property OnKeyPress;
    property OnKeyUp;
    property OnMeasureThumb;
    property OnMouseDown;
    property OnMouseMove;
    property OnMouseUp;
    property OnMouseWheel;
    property OnMouseWheelDown;
    property OnMouseWheelUp;
    property OnProgress;
    property OnResize;
    property OnStartDock;
    property OnStartDrag;
    property OnUnDock;
    property OnUnresolved;
    property ParentBackground;
    property RetainUnresolvedItems;
    property RowHeight;
    property ParentColor;
    property ParentCtl3D;
    property ParentShowHint;
    property PopupMenu;
    property Proportional;
    property ShowHint;
    property Sorted;
    property Stretch;
    property TabOrder;
    property TabStop;
    property VirtualMode;
    property Visible;
    property WheelScrollLines;
  end;

Solution 2

I'm using the multi-image view from the ImageEn library. It does everything you asked for, and it's very fast. I'm happy with it. You can still get an older, free version from Torry that works with Delphi 7 (I haven't tried it on XE2).

The methods aren't exactly intuitive, but once you get the hang of it (nice help file included), it works great.

The latest version has some more features, and it's not expensive if you do decide to license it.

You can see a video of ImageEn multi-image view in action in my application.

They even have a Flow View control that looks like the slide show on a Mac.

Share:
10,586
Jerry Dodge
Author by

Jerry Dodge

I'm a Delphi developer. I work for a software company which does solutions for retail management, including inventory, POS, reporting, BI, Tags, and more. It's been in Delphi since Delphi's been around. I am actively in Stack Overflow monitoring the Delphi tag, and looking for those questions I can answer and also contributing my time to keep Stack Overflow in order. I'm not an expert in anything, a jack of all trades rather. But I love to help people when I'm able to. I've known Delphi since about 2007 now, and before that, I had learned VB6. I havn't gone back to VB since I learned Delphi. I also taught myself QBasic and HTML as a kid. It hasn't been until the past 5 years that I've been diving into programming. Since then I've also become vaguely familiar with ASP.NET with C#, as well as some C# windows apps. But I'm not too fond of the whole .NET idea. .NET is good for web platforms and such, but not for win apps. My latest work has been with Delphi 10 Seattle mobile development. I'm still very raw on the subject, but see a huge potential behind it. My strengths: Understanding the bigger picture of projects Writing Custom Classes, Components, and Controls Code organization (within unit or namespace) Writing purely independent classes (as opposed to cross-referencing units or namespaces) User Friendly UI's Developer Friendly Classes Encapsulating layers of business logic My weaknesses: Lower-level coding (such as Assembly) Platform-specific design (using Firemonkey) Web Design It's always nice to know you're able to do something, even if you never use it.

Updated on June 04, 2022

Comments

  • Jerry Dodge
    Jerry Dodge almost 2 years

    I'm trying to find a grid which is especially designed to show images. It needs to have good performance too, and preferably with some sort of thumbnail cache. The images need to be loaded from files, and it would be good if images can be assigned dynamically too. It shouldn't work on a list of col/row records like standard grids, but a single list of items, each item representing an image. There should be a property to define col width and row height for all cols and rows at once, not one at a time. The end goal is to list all images with user options to control how large to display the images. It will be used as a product display, so there needs to be some sort of custom drawing capability too, like an OnDrawItem event. This may display up to 50,000 images in this list, so TListView won't work, as it's very heavy for this.

    It needs to work with Delphi 2010, XE2, and preferably 7 too.

    Here's 3 examples of how to display 8 images below. I don't mean each image being a different size, but exactly the same size. No 2 columns can have different widths, and same with rows.

    enter image description here

  • Jerry Dodge
    Jerry Dodge over 12 years
    Wow, this is awesome. I have to thank you 1,000 times, that makes two or three entire things you're built from my questions (or more?).
  • NGLN
    NGLN over 12 years
    @Jerry Hmm, scroll bar appears here just fine with D7. But indeed, keyboard input isn't handled yet. I will add it, but you also may/can yourself. It's not thát difficult.
  • Jerry Dodge
    Jerry Dodge over 12 years
    Do doubt it probably isn't too difficult - except that's easier for you to say because I'm far from familiar with things like this. Original question was asking for reference where I can get one, and although greatly appreciated, I was hoping for something a little more complete.
  • NGLN
    NGLN over 12 years
    @Jerry I added keyboard sensitivity. What else are you missing? And: does it work on 2010/XE2?
  • Jerry Dodge
    Jerry Dodge over 12 years
    :D Thanks - It's working in XE2, haven't tried yet in 7 or 2010 - my 7 is broken since I installed XE2 and I don't have a 2010 license (need to test on colleague's PC).
  • Jerry Dodge
    Jerry Dodge over 12 years
    And that should do it btw, I love the image loading and has inspired me to actually re-build my caching system to use threads per picture. Tweaking to A) First show a "box" or "cell" for each image which is to be shown, and then B) Spawn new threads to load each image, and then C) When image is available, draw it in its place. It will automatically maintain a thumbnail cache in any specified directory :D
  • none
    none almost 11 years
    compiles on delphi 2009. when droping on form throws access violation: Access violation at address 19A66174 in module 'AwImageGrid_RS2009.bpl'. Write of address 00000030. changed the dpk name to 2009.
  • kobik
    kobik over 9 years
    @NGLN, Can you show a small example of how to use VirtualMode := True?
  • NGLN
    NGLN over 9 years
    @kobik VirtualMode := True just disables the background thread creating the thumbs; everything else works as normal. So every item may have a valid FileName, Object and/or Image member set. In contrast, the Item.Thumb will not be created automatically, so you have the choice: use it and create them all in advance or when needed/shown, or not use it at all, and decide for yourself what to paint on the grid's canvas. Possible usage: showing each font found in Folder in its own font (e.g. add .ttf to the FileFormats property).
  • kobik
    kobik over 9 years
    @NGLN, I see. But I think you do need to a have a e.g. OnData event indicating the index, and also exposing the background thread interface, with something like TThumbsGenerator.Create(AnIndex). does that make seance?
  • NGLN
    NGLN over 9 years
    @kobik There's an OnDraw event indicating the index. When would 'data' be needed other than when to draw? Why would you want to disable the ThumbsGenerator for all, but use its default behaviour on one? Look, say you want to morph or blur the images, then the default thumb generator is obsolete. Instead: create, resize and blur all images beforehand via the Thumbs property. Other interaction with the control is controlable with the OnClickCell and OnMouse* events.
  • NGLN
    NGLN over 9 years
    @kobik I think I understand you now: If you expect the thumb generator to be able to do some custom thumb generating in virtual mode, to prevent the need for a separate thread, then you have to wait for the next version. ;-) Would be a nice feature though! And should not be hard to implement.
  • kobik
    kobik over 9 years
    @NGLN, Yes that was excellently my meaning. :) Looking forward to the next version.
  • kobik
    kobik over 9 years
    @NGLN, What I was actually thinking about, is the ability to process multiple Thumbs in multiple threads simultaneously (But I guess you already figured that out). You use a single worker thread which processes the files synchronously. This works very slow. if I have a folder with 100 pictures (not to mention 1000) it takes forever to paint them in the grid, and If I scroll to the end while the generator thread is running I need to wait until it processes all files to actually see any Thumbs. So I guess virtual mode would be the best in this situation.
  • kobik
    kobik over 9 years
    I think a queue will be needed here so that we don't exceed some "max" worker threads. anyway, just thinking out loud :)
  • Jerry Dodge
    Jerry Dodge about 9 years
    I just tried using this with VCL Styles... it doesn't seem to be compatible. The background remained the original color and the scrollbar is the Windows style.
  • NGLN
    NGLN about 9 years
    Sorry, I have no experience with VCL styles. I assume one can add it.
  • NGLN
    NGLN about 9 years
    Setting ParentBackground to True solves the first part.
  • Steve F
    Steve F over 8 years
    @NGLN: I have a problem with the Image grid. It gives a memory leak error (when closing the program) if trying to delete an image, if there is only 1 (one) image in the grid. Can you help me to fix this?
  • Mang Ndie
    Mang Ndie over 4 years
    i got "Warning: Potential Security Risk Ahead" when trying to access link "Subversion server here", is there another way to get the code ?
  • hikari
    hikari over 3 years
    Is this still available somewhere?
  • Jerry Dodge
    Jerry Dodge over 3 years
    @NGLN If you haven't already, you should stick this up on GitHub :)
  • NGLN
    NGLN over 3 years
    @hikari Yes, see here.