You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1981 lines
55 KiB
Plaintext
1981 lines
55 KiB
Plaintext
unit AwImageGrid;
|
|
|
|
interface
|
|
|
|
uses
|
|
Windows, Classes, SysUtils, Messages, Controls, Graphics, Forms, StdCtrls,
|
|
Grids, RTLConsts, Math, Vcl.Imaging.PNGImage, RnQGraphics32;
|
|
|
|
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: TPNGImage;
|
|
end;
|
|
|
|
PImageGridItemList = ^TImageGridItemList;
|
|
TImageGridItemList = array[0..MaxInt div 64] 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: NativeInt);
|
|
function GetImage(Index: Integer): TGraphic;
|
|
function GetThumb(Index: Integer): TPNGImage;
|
|
procedure Grow;
|
|
procedure InsertItem(Index: Integer; const S: String; AObject: TObject;
|
|
AImage: TGraphic; AThumb: TPNGImage);
|
|
procedure PutImage(Index: Integer; AImage: TGraphic);
|
|
procedure PutThumb(Index: Integer; AThumb: TPNGImage);
|
|
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: TPNGImage); 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: TPNGImage): Integer; virtual;
|
|
function AddObject(const S: String; AObject: TObject): Integer; override;
|
|
function AddThumb(const S: String; AThumb: TPNGImage): 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]: TPNGImage 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 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;
|
|
FResample: 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): TPNGImage;
|
|
function IsFileNamesStored: Boolean;
|
|
procedure ItemsChanged(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 SetResample(Value: Boolean);
|
|
procedure SetThumb(Index: Integer; Value: TPNGImage);
|
|
// procedure ThumbsUpdated(Sender: TObject);
|
|
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;
|
|
procedure CMMouseLeave(var msg: TMessage); message CM_MOUSELEAVE;
|
|
protected
|
|
procedure DoProgress(Index: Integer); virtual;
|
|
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 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 MouseMove(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 Resample: Boolean read FResample write SetResample default False;
|
|
property Thumbs[Index: Integer]: TPNGImage read GetThumb write SetThumb;
|
|
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 Resample;
|
|
property TabOrder;
|
|
property TabStop;
|
|
property Visible;
|
|
property WheelScrollLines;
|
|
end;
|
|
|
|
implementation
|
|
|
|
function StrCmpLogicalW(const sz1, sz2: WideString): Integer; stdcall;
|
|
external 'Shlwapi.dll';
|
|
|
|
procedure GetImageExtensions(List: TStrings);
|
|
var
|
|
Temp: TStringList;
|
|
S: String;
|
|
// Count: Cardinal;
|
|
// Size: Cardinal;
|
|
// Decoders: array of TImageCodecInfo;
|
|
// I: Integer;
|
|
begin
|
|
Temp := TStringList.Create;
|
|
try
|
|
Temp.Duplicates := dupIgnore;
|
|
Temp.Sorted := True;
|
|
{ S := GraphicFileMask(TGraphic);
|
|
if GetImageDecodersSize(Count, Size) = Ok then
|
|
begin
|
|
SetLength(Decoders, Size div SizeOf(TImageCodecInfo));
|
|
if GetImageDecoders(Count, Size, @Decoders[0]) = Ok then
|
|
for I := 0 to Count - 1 do
|
|
S := S + ';' + LowerCase(Decoders[I].FilenameExtension);
|
|
end;}
|
|
ExtractStrings([';'], ['*', '.'], PChar(S), Temp);
|
|
List.AddStrings(Temp);
|
|
finally
|
|
Temp.Free;
|
|
end;
|
|
end;
|
|
|
|
{ TImageGridItems }
|
|
|
|
function TImageGridItems.Add(const S: String): Integer;
|
|
begin
|
|
Result := AddItem(S, nil, nil, nil);
|
|
end;
|
|
|
|
function TImageGridItems.AddImage(const S: String; AImage: TGraphic): Integer;
|
|
begin
|
|
Result := AddItem(S, nil, AImage, nil);
|
|
end;
|
|
|
|
function TImageGridItems.AddItem(const S: String; AObject: TObject;
|
|
AImage: TGraphic; AThumb: TPNGImage): Integer;
|
|
begin
|
|
if FSorted then
|
|
Find(S, Result)
|
|
else
|
|
Result := FCount;
|
|
InsertItem(Result, S, AObject, AImage, AThumb);
|
|
end;
|
|
|
|
function TImageGridItems.AddObject(const S: String; AObject: TObject): Integer;
|
|
begin
|
|
Result := AddItem(S, AObject, nil, nil);
|
|
end;
|
|
|
|
procedure TImageGridItems.AddStrings(Strings: TStrings);
|
|
var
|
|
I: Integer;
|
|
Item: TImageGridItem;
|
|
begin
|
|
if Strings is TImageGridItems then
|
|
begin
|
|
BeginUpdate;
|
|
try
|
|
for I := 0 to Strings.Count - 1 do
|
|
begin
|
|
Item := TImageGridItems(Strings).FList^[I];
|
|
AddItem(Item.FFileName, Item.FObject, Item.FImage, Item.FThumb);
|
|
end;
|
|
finally
|
|
EndUpdate;
|
|
end;
|
|
end
|
|
else
|
|
inherited AddStrings(Strings);
|
|
end;
|
|
|
|
function TImageGridItems.AddThumb(const S: String; AThumb: TPNGImage): Integer;
|
|
begin
|
|
Result := AddItem(S, nil, nil, AThumb);
|
|
end;
|
|
|
|
procedure TImageGridItems.Assign(Source: TPersistent);
|
|
begin
|
|
if Source is TImageGridItems then
|
|
begin
|
|
BeginUpdate;
|
|
try
|
|
FSorted := TImageGridItems(Source).FSorted;
|
|
FOnChanged := TImageGridItems(Source).FOnChanged;
|
|
inherited Assign(Source);
|
|
Changed;
|
|
finally
|
|
EndUpdate;
|
|
end;
|
|
end
|
|
else
|
|
inherited Assign(Source);
|
|
end;
|
|
|
|
procedure TImageGridItems.Changed;
|
|
begin
|
|
FChanged := True;
|
|
if (UpdateCount = 0) and Assigned(FOnChanged) then
|
|
begin
|
|
FOnChanged(Self);
|
|
FChanged := False;
|
|
end;
|
|
end;
|
|
|
|
procedure TImageGridItems.Changing;
|
|
begin
|
|
if (UpdateCount = 0) and Assigned(FOnChanging) then
|
|
FOnChanging(Self);
|
|
end;
|
|
|
|
procedure TImageGridItems.Clear;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
if FCount <> 0 then
|
|
begin
|
|
Changing;
|
|
for I := 0 to FCount - 1 do
|
|
FList^[I].FThumb.Free;
|
|
if FOwnsObjects then
|
|
for I := 0 to FCount - 1 do
|
|
FList^[I].FObject.Free;
|
|
Finalize(FList^[0], FCount);
|
|
FCount := 0;
|
|
SetCapacity(0);
|
|
Changed;
|
|
end;
|
|
end;
|
|
|
|
procedure TImageGridItems.ClearThumbs;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
BeginUpdate;
|
|
for I := 0 to FCount - 1 do
|
|
FreeAndNil(FList^[I].FThumb);
|
|
EndUpdate;
|
|
end;
|
|
|
|
function TImageGridItems.CompareStrings(const S1, S2: String): Integer;
|
|
begin
|
|
Result := StrCmpLogicalW(S1, S2);
|
|
end;
|
|
|
|
procedure TImageGridItems.Delete(Index: Integer);
|
|
begin
|
|
if (Index < 0) or (Index >= FCount) then
|
|
Error(@SListIndexError, Index);
|
|
Changing;
|
|
FList^[Index].FThumb.Free;
|
|
if FOwnsObjects then
|
|
FList^[Index].FObject.Free;
|
|
Finalize(FList^[Index]);
|
|
Dec(FCount);
|
|
if Index < FCount then
|
|
System.Move(FList^[Index + 1], FList^[Index],
|
|
(FCount - Index) * SizeOf(TImageGridItem));
|
|
Changed;
|
|
end;
|
|
|
|
destructor TImageGridItems.Destroy;
|
|
begin
|
|
FOnChanged := nil;
|
|
FOnChanging := nil;
|
|
Clear;
|
|
inherited Destroy;
|
|
end;
|
|
|
|
procedure TImageGridItems.Exchange(Index1, Index2: Integer);
|
|
begin
|
|
if (Index1 < 0) or (Index1 >= FCount) then
|
|
Error(@SListIndexError, Index1);
|
|
if (Index2 < 0) or (Index2 >= FCount) then
|
|
Error(@SListIndexError, Index2);
|
|
Changing;
|
|
ExchangeItems(Index1, Index2);
|
|
Changed;
|
|
end;
|
|
|
|
procedure TImageGridItems.ExchangeItems(Index1, Index2: NativeInt);
|
|
var
|
|
Temp: NativeInt;
|
|
Item1: PImageGridItem;
|
|
Item2: PImageGridItem;
|
|
begin
|
|
Item1 := @FList^[Index1];
|
|
Item2 := @FList^[Index2];
|
|
Temp := NativeInt(Item1^.FFileName);
|
|
NativeInt(Item1^.FFileName) := NativeInt(Item2^.FFileName);
|
|
NativeInt(Item2^.FFileName) := Temp;
|
|
Temp := Integer(Item1^.FObject);
|
|
NativeInt(Item1^.FObject) := NativeInt(Item2^.FObject);
|
|
NativeInt(Item2^.FObject) := Temp;
|
|
Temp := NativeInt(Item1^.FThumb);
|
|
NativeInt(Item1^.FThumb) := NativeInt(Item2^.FThumb);
|
|
NativeInt(Item2^.FThumb) := Temp;
|
|
end;
|
|
|
|
function TImageGridItems.Find(const S: String; var Index: Integer): Boolean;
|
|
var
|
|
L: Integer;
|
|
H: Integer;
|
|
I: Integer;
|
|
C: Integer;
|
|
begin
|
|
Result := False;
|
|
L := 0;
|
|
H := FCount - 1;
|
|
while L <= H do
|
|
begin
|
|
I := (L + H) shr 1;
|
|
C := CompareStrings(FList^[I].FFileName, S);
|
|
if C < 0 then
|
|
L := I + 1
|
|
else
|
|
begin
|
|
H := I - 1;
|
|
if C = 0 then
|
|
Result := True;
|
|
end;
|
|
end;
|
|
Index := L;
|
|
end;
|
|
|
|
function TImageGridItems.Get(Index: Integer): String;
|
|
begin
|
|
if (Index < 0) or (Index >= FCount) then
|
|
Result := '' // Error(@SListgeIndexError, Index);
|
|
else
|
|
Result := FList^[Index].FFileName;
|
|
end;
|
|
|
|
function TImageGridItems.GetCapacity: Integer;
|
|
begin
|
|
Result := FCapacity;
|
|
end;
|
|
|
|
function TImageGridItems.GetCount: Integer;
|
|
begin
|
|
Result := FCount;
|
|
end;
|
|
|
|
function TImageGridItems.GetImage(Index: Integer): TGraphic;
|
|
begin
|
|
if (Index < 0) or (Index >= FCount) then
|
|
Error(@SListIndexError, Index);
|
|
Result := FList^[Index].FImage;
|
|
end;
|
|
|
|
function TImageGridItems.GetObject(Index: Integer): TObject;
|
|
begin
|
|
if (Index < 0) or (Index >= FCount) then
|
|
Error(@SListIndexError, Index);
|
|
Result := FList^[Index].FObject;
|
|
end;
|
|
|
|
function TImageGridItems.GetThumb(Index: Integer): TPNGImage;
|
|
begin
|
|
if (Index < 0) or (Index >= FCount) then
|
|
Error(@SListIndexError, Index);
|
|
Result := FList^[Index].FThumb;
|
|
end;
|
|
|
|
procedure TImageGridItems.Grow;
|
|
var
|
|
Delta: Integer;
|
|
begin
|
|
if FCapacity > 64 then
|
|
Delta := FCapacity div 4
|
|
else if FCapacity > 8 then
|
|
Delta := 16
|
|
else
|
|
Delta := 4;
|
|
SetCapacity(FCapacity + Delta);
|
|
end;
|
|
|
|
function TImageGridItems.IndexOf(const S: String): Integer;
|
|
begin
|
|
if not FSorted then
|
|
Result := inherited IndexOf(S)
|
|
else
|
|
if not Find(S, Result) then
|
|
Result := -1;
|
|
end;
|
|
|
|
procedure TImageGridItems.Insert(Index: Integer; const S: String);
|
|
begin
|
|
InsertObject(Index, S, nil);
|
|
end;
|
|
|
|
procedure TImageGridItems.InsertItem(Index: Integer; const S: String;
|
|
AObject: TObject; AImage: TGraphic; AThumb: TPNGImage);
|
|
begin
|
|
Changing;
|
|
if FCount = FCapacity then
|
|
Grow;
|
|
if Index < FCount then
|
|
System.Move(FList^[Index], FList^[Index + 1],
|
|
(FCount - Index) * SizeOf(TImageGridItem));
|
|
Pointer(FList^[Index].FFileName) := nil;
|
|
FList^[Index].FFileName := S;
|
|
FList^[Index].FObject := AObject;
|
|
FList^[Index].FImage := AImage;
|
|
FList^[Index].FThumb := AThumb;
|
|
Inc(FCount);
|
|
Changed;
|
|
end;
|
|
|
|
procedure TImageGridItems.InsertObject(Index: Integer; const S: String;
|
|
AObject: TObject);
|
|
begin
|
|
if FSorted then
|
|
Error(@SSortedListError, 0);
|
|
if (Index < 0) or (Index > FCount) then
|
|
Error(@SListIndexError, Index);
|
|
InsertItem(Index, S, AObject, nil, nil);
|
|
end;
|
|
|
|
procedure TImageGridItems.Put(Index: Integer; const S: String);
|
|
begin
|
|
if FSorted then
|
|
Error(@SSortedListError, 0);
|
|
if (Index < 0) or (Index >= FCount) then
|
|
Error(@SListIndexError, Index);
|
|
if FList^[Index].FFileName <> S then
|
|
begin
|
|
Changing;
|
|
if FList^[Index].FImage = nil then
|
|
FreeAndNil(FList^[Index].FThumb);
|
|
FList^[Index].FFileName := S;
|
|
Changed;
|
|
end;
|
|
end;
|
|
|
|
procedure TImageGridItems.PutImage(Index: Integer; AImage: TGraphic);
|
|
begin
|
|
if (Index < 0) or (Index >= FCount) then
|
|
Error(@SListIndexError, Index);
|
|
if Flist^[Index].FImage <> AImage then
|
|
begin
|
|
Changing;
|
|
FList^[Index].FImage := AImage;
|
|
FreeAndNil(FList^[Index].FThumb);
|
|
Changed;
|
|
end;
|
|
end;
|
|
|
|
procedure TImageGridItems.PutObject(Index: Integer; AObject: TObject);
|
|
begin
|
|
if (Index < 0) or (Index >= FCount) then
|
|
Error(@SListIndexError, Index);
|
|
if FList^[Index].FObject <> AObject then
|
|
begin
|
|
Changing;
|
|
FList^[Index].FObject := AObject;
|
|
Changed;
|
|
end;
|
|
end;
|
|
|
|
procedure TImageGridItems.PutThumb(Index: Integer; AThumb: TPNGImage);
|
|
begin
|
|
if (Index < 0) or (Index >= FCount) then
|
|
Error(@SListIndexError, Index);
|
|
if FList^[Index].FThumb <> AThumb then
|
|
begin
|
|
Changing;
|
|
FList^[Index].FThumb := AThumb;
|
|
Changed;
|
|
end;
|
|
end;
|
|
|
|
procedure TImageGridItems.PutThumbSilently(Index: Integer; AThumb: TPNGImage);
|
|
begin
|
|
if (Index >= 0) and (Index < FCount) then
|
|
FList^[Index].FThumb := AThumb;
|
|
end;
|
|
|
|
procedure TImageGridItems.QuickSort(L, R: Integer);
|
|
var
|
|
I: Integer;
|
|
J: Integer;
|
|
P: Integer;
|
|
begin
|
|
repeat
|
|
I := L;
|
|
J := R;
|
|
P := (L + R) shr 1;
|
|
repeat
|
|
while CompareStrings(FList^[I].FFileName, FList^[P].FFileName) < 0 do
|
|
Inc(I);
|
|
while CompareStrings(FList^[J].FFileName, FList^[P].FFileName) > 0 do
|
|
Dec(J);
|
|
if I <= J then
|
|
begin
|
|
ExchangeItems(I, J);
|
|
if P = I then
|
|
P := J
|
|
else if P = J then
|
|
P := I;
|
|
Inc(I);
|
|
Dec(J);
|
|
end;
|
|
until I > J;
|
|
if L < J then
|
|
QuickSort(L, J);
|
|
L := I;
|
|
until I >= R;
|
|
end;
|
|
|
|
procedure TImageGridItems.SetCapacity(Value: Integer);
|
|
begin
|
|
if FCapacity <> Value then
|
|
begin
|
|
ReallocMem(FList, Value * SizeOf(TImageGridItem));
|
|
FCapacity := Value;
|
|
end;
|
|
end;
|
|
|
|
procedure TImageGridItems.SetSorted(Value: Boolean);
|
|
begin
|
|
if FSorted <> Value then
|
|
begin
|
|
if Value then
|
|
Sort;
|
|
FSorted := Value;
|
|
end;
|
|
end;
|
|
|
|
procedure TImageGridItems.SetUpdateState(Updating: Boolean);
|
|
begin
|
|
if Updating then
|
|
Changing
|
|
else if FChanged then
|
|
Changed;
|
|
end;
|
|
|
|
procedure TImageGridItems.Sort;
|
|
begin
|
|
if not FSorted and (FCount > 1) then
|
|
begin
|
|
Changing;
|
|
QuickSort(0, FCount - 1);
|
|
Changed;
|
|
end;
|
|
end;
|
|
|
|
{ TBorderControl }
|
|
|
|
procedure TBorderControl.CMCtl3DChanged(var Message: TMessage);
|
|
begin
|
|
if NewStyleControls and (FBorderStyle = bsSingle) then
|
|
RecreateWnd;
|
|
inherited;
|
|
end;
|
|
|
|
constructor TBorderControl.Create(AOwner: TComponent);
|
|
begin
|
|
inherited Create(AOwner);
|
|
if NewStyleControls then
|
|
ControlStyle := [csNeedsBorderPaint]
|
|
else
|
|
ControlStyle := [csNeedsBorderPaint, csFramed];
|
|
FBorderStyle := bsSingle;
|
|
end;
|
|
|
|
procedure TBorderControl.CreateParams(var Params: TCreateParams);
|
|
const
|
|
BorderStyles: array[TBorderStyle] of DWORD = (0, WS_BORDER);
|
|
begin
|
|
inherited CreateParams(Params);
|
|
Params.WindowClass.style :=
|
|
Params.WindowClass.style and not (CS_HREDRAW or CS_VREDRAW);
|
|
if NewStyleControls and Ctl3D and (FBorderStyle = bsSingle) then
|
|
begin
|
|
Params.Style := Params.Style and not WS_BORDER;
|
|
Params.ExStyle := Params.ExStyle or WS_EX_CLIENTEDGE;
|
|
end
|
|
else
|
|
Params.Style := Params.Style or BorderStyles[FBorderStyle];
|
|
end;
|
|
|
|
procedure TBorderControl.SetBorderStyle(Value: TBorderStyle);
|
|
begin
|
|
if Value <> FBorderStyle then
|
|
begin
|
|
FBorderStyle := Value;
|
|
if FBorderStyle = bsSingle then
|
|
ControlStyle := ControlStyle + [csNeedsBorderPaint]
|
|
else
|
|
ControlStyle := ControlStyle - [csNeedsBorderPaint];
|
|
RecreateWnd;
|
|
end;
|
|
end;
|
|
|
|
function TBorderControl.TotalBorderWidth: Integer;
|
|
begin
|
|
if GetWindowLong(Handle, GWL_STYLE) and WS_VSCROLL <> 0 then
|
|
Result := (Width - ClientWidth - GetSystemMetrics(SM_CXVSCROLL)) div 2
|
|
else
|
|
Result := (Width - ClientWidth) div 2;
|
|
end;
|
|
|
|
procedure TBorderControl.WMNCPaint(var Message: TWMNCPaint);
|
|
{$IF CompilerVersion < 18.5} {D2007}
|
|
var
|
|
DC: HDC;
|
|
TotalBorderWidth: Integer;
|
|
{$IFEND}
|
|
begin
|
|
{$IF CompilerVersion < 18.5}
|
|
DC := GetWindowDC(Handle);
|
|
try
|
|
TotalBorderWidth := Self.TotalBorderWidth;
|
|
if GetWindowLong(Handle, GWL_STYLE) and WS_HSCROLL <> 0 then
|
|
FillRect(DC, Rect(0, Height - TotalBorderWidth, Width, Height),
|
|
Brush.Handle);
|
|
if GetWindowLong(Handle, GWL_STYLE) and WS_VSCROLL <> 0 then
|
|
FillRect(DC, Rect(Width - TotalBorderWidth, 0, Width, Height),
|
|
Brush.Handle);
|
|
finally
|
|
ReleaseDC(Handle, DC);
|
|
end;
|
|
{$IFEND}
|
|
inherited;
|
|
end;
|
|
|
|
{ TAnimRowScroller }
|
|
|
|
const
|
|
ScrollTimerId = 123;
|
|
DragTimerId = 234;
|
|
ScrollTimerInterval = 15;
|
|
DragTimerInterval = 15;
|
|
|
|
constructor TAnimRowScroller.Create(AOwner: TComponent);
|
|
begin
|
|
inherited Create(AOwner);
|
|
FAutoHideScrollbar := True;
|
|
FRow := -1;
|
|
FRowHeight := DefRowHeight;
|
|
FDragScroll := True;
|
|
FWheelScrollLines := Mouse.WheelScrollLines;
|
|
end;
|
|
|
|
procedure TAnimRowScroller.CreateWnd;
|
|
begin
|
|
inherited CreateWnd;
|
|
UpdateScrollBar;
|
|
end;
|
|
|
|
function TAnimRowScroller.DoMouseWheel(Shift: TShiftState; WheelDelta: Integer;
|
|
MousePos: TPoint): Boolean;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
Result := inherited DoMouseWheel(Shift, WheelDelta, MousePos);
|
|
if not Result then
|
|
begin
|
|
for I := 0 to FWheelScrollLines - 1 do
|
|
if WheelDelta < 0 then
|
|
Perform(WM_VSCROLL, MakeLong(SB_LINEDOWN, 0), 0)
|
|
else
|
|
Perform(WM_VSCROLL, MakeLong(SB_LINEUP, 0), 0);
|
|
Result := True;
|
|
end;
|
|
end;
|
|
|
|
procedure TAnimRowScroller.Drag;
|
|
var
|
|
Delay: Cardinal;
|
|
begin
|
|
Delay := GetTickCount - FPrevTick;
|
|
if FDragScrolling then
|
|
begin
|
|
if Delay = 0 then
|
|
Delay := 1;
|
|
FDragSpeed := (FScrollingPos - FPrevScrollPos) / Delay;
|
|
end
|
|
else
|
|
begin
|
|
if Abs(FDragSpeed) < 0.005 then
|
|
KillTimer(Handle, DragTimerId)
|
|
else
|
|
begin
|
|
SetScrollPos(FPrevScrollPos + Round(Delay * FDragSpeed), False, False);
|
|
FDragSpeed := 0.83 * FDragSpeed;
|
|
end;
|
|
end;
|
|
FPrevScrollPos := FScrollingPos;
|
|
FPrevTick := GetTickCount;
|
|
end;
|
|
|
|
function TAnimRowScroller.IsWheelScrollLinesStored: Boolean;
|
|
begin
|
|
Result := FWheelScrollLines <> Mouse.WheelScrollLines;
|
|
end;
|
|
|
|
procedure TAnimRowScroller.MouseDown(Button: TMouseButton; Shift: TShiftState;
|
|
X, Y: Integer);
|
|
begin
|
|
if FDragScroll then
|
|
FDragStartPos := Y + FScrollingPos;
|
|
inherited MouseDown(Button, Shift, X, Y);
|
|
end;
|
|
|
|
procedure TAnimRowScroller.MouseMove(Shift: TShiftState; X, Y: Integer);
|
|
begin
|
|
if FDragScroll and (not FDragScrolling) and (ssLeft in Shift) and
|
|
(Abs(Y - FDragStartPos) > Mouse.DragThreshold) then
|
|
begin
|
|
FPrevScrollPos := FScrollingPos;
|
|
FDragScrolling := True;
|
|
SetTimer(Handle, DragTimerId, DragTimerInterval, nil);
|
|
end;
|
|
|
|
if FDragScrolling then
|
|
SetScrollPos(FDragStartPos - Y, False, False);
|
|
|
|
if not (Scrolling) then Invalidate;
|
|
inherited MouseMove(Shift, X, Y);
|
|
end;
|
|
|
|
procedure TAnimRowScroller.MouseUp(Button: TMouseButton; Shift: TShiftState;
|
|
X, Y: Integer);
|
|
begin
|
|
FDragScrolling := False;
|
|
inherited MouseUp(Button, Shift, X, Y);
|
|
end;
|
|
|
|
procedure TAnimRowScroller.MouseWheelHandler(var Message: TMessage);
|
|
var
|
|
Form: TCustomForm;
|
|
begin
|
|
Message.Result := Perform(CM_MOUSEWHEEL, Message.WParam, Message.LParam);
|
|
if Message.Result = 0 then
|
|
begin
|
|
Form := GetParentForm(Self);
|
|
if Form <> nil then
|
|
Form.MouseWheelHandler(Message);
|
|
end;
|
|
end;
|
|
|
|
procedure TAnimRowScroller.Resize;
|
|
begin
|
|
UpdateScrollBar;
|
|
inherited Resize;
|
|
end;
|
|
|
|
procedure TAnimRowScroller.Scroll;
|
|
var
|
|
Diff: Integer;
|
|
Delta: Integer;
|
|
begin
|
|
Diff := FScrollingPos - FScrollPos;
|
|
if Diff <> 0 then
|
|
begin
|
|
if Abs(Diff) > 3 then
|
|
Delta := Diff div 4
|
|
else if Abs(Diff) > 1 then
|
|
Delta := Diff div 2
|
|
else
|
|
Delta := Diff;
|
|
ScrollWindow(Handle, 0, Delta, nil, nil);
|
|
Dec(FScrollingPos, Delta);
|
|
end
|
|
else
|
|
KillTimer(Handle, ScrollTimerId);
|
|
end;
|
|
|
|
function TAnimRowScroller.Scrolling: Boolean;
|
|
begin
|
|
Result := (FScrollingPos <> FScrollPos) or FDragScrolling;
|
|
end;
|
|
|
|
procedure TAnimRowScroller.SetAutoHideScrollBar(Value: Boolean);
|
|
begin
|
|
if FAutoHideScrollBar <> Value then
|
|
begin
|
|
FAutoHideScrollBar := Value;
|
|
UpdateScrollBar;
|
|
end;
|
|
end;
|
|
|
|
procedure TAnimRowScroller.SetRow(Value: Integer);
|
|
begin
|
|
if FRow <> Value then
|
|
begin
|
|
FRow := Max(-1, Min(Value, FRowCount - 1));
|
|
UpdateScrollBar;
|
|
Invalidate;
|
|
end;
|
|
end;
|
|
|
|
procedure TAnimRowScroller.SetRowCount(Value: Integer);
|
|
begin
|
|
if FRowCount <> Value then
|
|
begin
|
|
FRowCount := Max(0, Value);
|
|
UpdateScrollBar;
|
|
Invalidate;
|
|
end;
|
|
end;
|
|
|
|
procedure TAnimRowScroller.SetRowHeight(Value: Integer);
|
|
begin
|
|
if FRowHeight <> Value then
|
|
begin
|
|
FRowHeight := Max(MinCellSize, Value);
|
|
UpdateScrollBar;
|
|
Invalidate;
|
|
end;
|
|
end;
|
|
|
|
procedure TAnimRowScroller.SetScrollPos(Value: Integer; Animate,
|
|
Snap: Boolean);
|
|
var
|
|
PageHeight: Integer;
|
|
AlreadyScrolling: Boolean;
|
|
begin
|
|
if FScrollPos <> Value then
|
|
begin
|
|
PageHeight := (ClientHeight div FRowHeight) * FRowHeight;
|
|
Value := Max(0, Min(Value, FRowCount * FRowHeight - PageHeight));
|
|
if Snap then
|
|
Value := (Value div FRowHeight) * FRowHeight;
|
|
Windows.SetScrollPos(Handle, SB_VERT, Value, True);
|
|
if Animate then
|
|
begin
|
|
AlreadyScrolling := Scrolling;
|
|
FScrollPos := Value;
|
|
if not AlreadyScrolling then
|
|
SetTimer(Handle, ScrollTimerId, ScrollTimerInterval, nil);
|
|
end
|
|
else
|
|
begin
|
|
ScrollWindow(Handle, 0, FScrollPos - Value, nil, nil);
|
|
FScrollPos := Value;
|
|
FScrollingPos := FScrollPos;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure TAnimRowScroller.UpdateScrollBar;
|
|
var
|
|
PageHeight: Integer;
|
|
Info: TScrollInfo;
|
|
RowPos: Integer;
|
|
begin
|
|
if HandleAllocated then
|
|
begin
|
|
PageHeight := (ClientHeight div FRowHeight) * FRowHeight;
|
|
Info.cbSize := SizeOf(TScrollInfo);
|
|
Info.fMask := SIF_ALL;
|
|
Info.nMin := 0;
|
|
Info.nMax := FRowCount * FRowHeight;
|
|
Info.nPage := PageHeight;
|
|
Info.nPos := Max(0, Min(FScrollPos, Info.nMax - PageHeight));
|
|
if FRow >= 0 then
|
|
begin
|
|
RowPos := FRow * FRowHeight;
|
|
if RowPos < Info.nPos then
|
|
Info.nPos := RowPos
|
|
else if RowPos > (Info.nPos + PageHeight - FRowHeight) then
|
|
Info.nPos := RowPos - PageHeight + FRowHeight;
|
|
end;
|
|
|
|
if Info.nMax <= PageHeight then
|
|
begin
|
|
FScrollPos := 0;
|
|
FScrollingPos := 0;
|
|
if FAutoHideScrollBar then
|
|
ShowScrollBar(Handle, SB_VERT, False)
|
|
else
|
|
begin
|
|
ShowScrollBar(Handle, SB_VERT, True);
|
|
EnableScrollBar(Handle, SB_VERT, ESB_DISABLE_BOTH);
|
|
end;
|
|
end
|
|
else
|
|
begin
|
|
FScrollPos := Info.nPos;
|
|
FScrollingPos := Info.nPos;
|
|
ShowScrollBar(Handle, SB_VERT, True);
|
|
if Enabled then
|
|
begin
|
|
EnableScrollBar(Handle, SB_VERT, ESB_ENABLE_BOTH);
|
|
SetScrollInfo(Handle, SB_VERT, Info, True);
|
|
end
|
|
else
|
|
EnableScrollBar(Handle, SB_VERT, ESB_DISABLE_BOTH);
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure TAnimRowScroller.WMVScroll(var Message: TWMVScroll);
|
|
|
|
function RealScrollPos: Integer;
|
|
var
|
|
Info: TScrollInfo;
|
|
begin
|
|
Info.cbSize := SizeOf(TScrollInfo);
|
|
Info.fMask := SIF_TRACKPOS;
|
|
Result := Message.Pos;
|
|
if GetScrollInfo(Handle, SB_VERT, Info) then
|
|
Result := Info.nTrackPos;
|
|
end;
|
|
|
|
var
|
|
PageHeight: Integer;
|
|
begin
|
|
PageHeight := (ClientHeight div FRowHeight) * FRowHeight;
|
|
case Message.ScrollCode of
|
|
SB_LINEUP:
|
|
SetScrollPos(FScrollPos - FRowHeight, True, True);
|
|
SB_LINEDOWN:
|
|
SetScrollPos(FScrollPos + FRowHeight, True, True);
|
|
SB_PAGEUP:
|
|
SetScrollPos(FScrollPos - PageHeight, True, True);
|
|
SB_PAGEDOWN:
|
|
SetScrollPos(FScrollPos + PageHeight, True, True);
|
|
SB_THUMBPOSITION:
|
|
SetScrollPos(RealScrollPos, True, False);
|
|
SB_THUMBTRACK:
|
|
SetScrollPos(RealScrollPos, False, False);
|
|
SB_TOP:
|
|
SetScrollPos(0, False, True);
|
|
SB_BOTTOM:
|
|
SetScrollPos(FRowCount * FRowHeight, False, False);
|
|
end;
|
|
inherited;
|
|
end;
|
|
|
|
procedure TAnimRowScroller.WndProc(var Message: TMessage);
|
|
begin
|
|
if (Message.Msg <> WM_TIMER) then
|
|
inherited WndProc(Message)
|
|
else if TWMTimer(Message).TimerID = ScrollTimerId then
|
|
Scroll
|
|
else if TWMTimer(Message).TimerID = DragTimerId then
|
|
Drag;
|
|
end;
|
|
|
|
{ TCustomImageGrid }
|
|
|
|
function TCustomImageGrid.CellRect(Index: Integer): TRect;
|
|
var
|
|
Coord: TGridCoord;
|
|
begin
|
|
Coord := CoordFromIndex(Index);
|
|
Result := Bounds(Coord.X * FColWidth, Coord.Y * RowHeight, CellWidth,
|
|
CellHeight);
|
|
Dec(Result.Top, ScrollingPos);
|
|
Dec(Result.Bottom, ScrollingPos);
|
|
end;
|
|
|
|
procedure TCustomImageGrid.ChangeScale(M, D: Integer);
|
|
begin
|
|
inherited ChangeScale(M, D);
|
|
BorderWidth := MulDiv(BorderWidth, M, D);
|
|
FCellSpacing := MulDiv(FCellSpacing, M, D);
|
|
SetCoordSize(MulDiv(FColWidth, M, D), MulDiv(RowHeight, M, D));
|
|
end;
|
|
|
|
procedure TCustomImageGrid.Clear;
|
|
begin
|
|
FItems.Clear;
|
|
end;
|
|
|
|
procedure TCustomImageGrid.CMEnter(var Message: TCMEnter);
|
|
begin
|
|
inherited;
|
|
end;
|
|
|
|
procedure TCustomImageGrid.CMExit(var Message: TCMExit);
|
|
begin
|
|
inherited;
|
|
end;
|
|
|
|
procedure TCustomImageGrid.CMMouseLeave(var msg: TMessage);
|
|
begin
|
|
Invalidate;
|
|
end;
|
|
|
|
function TCustomImageGrid.CoordFromIndex(Index: Integer): TGridCoord;
|
|
begin
|
|
Result.X := Index mod FColCount;
|
|
Result.Y := Index div FColCount;
|
|
end;
|
|
|
|
constructor TCustomImageGrid.Create(AOwner: TComponent);
|
|
begin
|
|
inherited Create(AOwner);
|
|
ControlStyle := ControlStyle + [csCaptureMouse, csClickEvents, csOpaque,
|
|
csDoubleClicks];
|
|
Width := 218;
|
|
Height := 134;
|
|
TabStop := True;
|
|
FCellAlignment := taCenter;
|
|
FCellLayout := tlCenter;
|
|
FCellSpacing := DefCellSpacing;
|
|
FColCount := 1;
|
|
FColWidth := DefColWidth;
|
|
FDefaultDrawing := True;
|
|
FItemIndex := -1;
|
|
FMarkerColor := clGray;
|
|
FMarkerStyle := psDash;
|
|
FProportional := True;
|
|
FFileFormats := TStringList.Create;
|
|
if csDesigning in ComponentState then
|
|
GetImageExtensions(FFileFormats);
|
|
TStringList(FFileFormats).OnChange := FileFormatsChanged;
|
|
FItems := TImageGridItems.Create;
|
|
FItems.OnChanged := ItemsChanged;
|
|
end;
|
|
|
|
procedure TCustomImageGrid.DeleteUnresolvedItems;
|
|
var
|
|
I: Integer;
|
|
PrevCount: Integer;
|
|
begin
|
|
PrevCount := Count;
|
|
FItems.BeginUpdate;
|
|
try
|
|
for I := Count - 1 downto 0 do
|
|
if FItems.Thumbs[I] = nil then
|
|
FItems.Delete(I);
|
|
finally
|
|
FItems.EndUpdate;
|
|
end;
|
|
if Count <> PrevCount then
|
|
Rearrange;
|
|
end;
|
|
|
|
destructor TCustomImageGrid.Destroy;
|
|
begin
|
|
FItems.OnChanged := nil;
|
|
FItems.OnChanging := nil;
|
|
TStringList(FFileFormats).OnChange := nil;
|
|
FItems.Free;
|
|
FFileFormats.Free;
|
|
inherited Destroy;
|
|
end;
|
|
|
|
procedure TCustomImageGrid.DoClickCell(Index: Integer);
|
|
begin
|
|
ItemIndex := Index;
|
|
if Assigned(FOnClickCell) then
|
|
FOnClickCell(Self, Index);
|
|
end;
|
|
|
|
procedure TCustomImageGrid.DoDrawCell(Index, ACol, ARow: Integer;
|
|
R: TRect);
|
|
begin
|
|
if Assigned(FOnDrawCell) then
|
|
FOnDrawCell(Self, Index, ACol, ARow, R);
|
|
end;
|
|
|
|
procedure TCustomImageGrid.DoMeasureThumb(Index: Integer; var AThumbWidth,
|
|
AThumbHeight: Integer);
|
|
begin
|
|
AThumbWidth := CellWidth;
|
|
AThumbHeight := CellHeight;
|
|
if Assigned(FOnMeasureThumb) then
|
|
begin
|
|
FOnMeasureThumb(Self, Index, AThumbWidth, AThumbHeight);
|
|
AThumbWidth := Max(MinThumbSize, Min(AThumbWidth, CellWidth));
|
|
AThumbHeight := Max(MinThumbSize, Min(AThumbHeight, CellHeight));
|
|
end;
|
|
end;
|
|
|
|
procedure TCustomImageGrid.DoProgress(Index: Integer);
|
|
begin
|
|
InvalidateItem(Index);
|
|
if FItems.Thumbs[Index] = nil then
|
|
if Assigned(FOnUnresolved) then
|
|
FOnUnresolved(Self, Index);
|
|
if Assigned(FOnProgress) then
|
|
FOnProgress(Self, Index);
|
|
end;
|
|
|
|
procedure TCustomImageGrid.FileFormatsChanged(Sender: TObject);
|
|
var
|
|
SaveFolder: TPath;
|
|
I: Integer;
|
|
Ext: String;
|
|
begin
|
|
SaveFolder := FFolder;
|
|
FItems.BeginUpdate;
|
|
try
|
|
for I := Count - 1 downto 0 do
|
|
begin
|
|
Ext := ExtractFileExt(FItems.FileNames[I]);
|
|
Delete(Ext, 1, 1);
|
|
if FFileFormats.IndexOf(Ext) = -1 then
|
|
FItems.Delete(I);
|
|
end;
|
|
finally
|
|
FItems.EndUpdate;
|
|
FFolder := SaveFolder;
|
|
end;
|
|
end;
|
|
|
|
function TCustomImageGrid.GetCellHeight: Integer;
|
|
begin
|
|
Result := RowHeight - FCellSpacing;
|
|
end;
|
|
|
|
function TCustomImageGrid.GetCellWidth: Integer;
|
|
begin
|
|
Result := FColWidth - FCellSpacing;
|
|
end;
|
|
|
|
function TCustomImageGrid.GetCount: Integer;
|
|
begin
|
|
Result := FItems.Count;
|
|
end;
|
|
|
|
function TCustomImageGrid.GetFileNames: TStrings;
|
|
begin
|
|
Result := FItems;
|
|
end;
|
|
|
|
function TCustomImageGrid.GetImage(Index: Integer): TGraphic;
|
|
begin
|
|
Result := FItems.Images[Index];
|
|
end;
|
|
|
|
function TCustomImageGrid.GetRowCount: Integer;
|
|
begin
|
|
Result := inherited RowCount;
|
|
end;
|
|
|
|
function TCustomImageGrid.GetSorted: Boolean;
|
|
begin
|
|
Result := FItems.Sorted;
|
|
end;
|
|
|
|
function TCustomImageGrid.GetThumb(Index: Integer): TPNGImage;
|
|
begin
|
|
Result := FItems.Thumbs[Index];
|
|
end;
|
|
|
|
procedure TCustomImageGrid.InvalidateItem(Index: Integer);
|
|
var
|
|
Coord: TGridCoord;
|
|
R: TRect;
|
|
begin
|
|
Coord := CoordFromIndex(Index);
|
|
R := Bounds(Coord.X * FColWidth, Coord.Y * RowHeight - ScrollingPos,
|
|
FColWidth, RowHeight);
|
|
InvalidateRect(Handle, @R, False);
|
|
end;
|
|
|
|
function TCustomImageGrid.IsFileNamesStored: Boolean;
|
|
begin
|
|
Result := FFolder = '';
|
|
end;
|
|
|
|
procedure TCustomImageGrid.ItemsChanged(Sender: TObject);
|
|
begin
|
|
if (FItemIndex = -1) and (Count > 0) then
|
|
FItemIndex := 0;
|
|
FFolder := '';
|
|
Rearrange;
|
|
end;
|
|
|
|
procedure TCustomImageGrid.KeyDown(var Key: Word; Shift: TShiftState);
|
|
begin
|
|
case Key of
|
|
VK_UP:
|
|
ItemIndex := FItemIndex - FColCount;
|
|
VK_DOWN:
|
|
ItemIndex := FItemIndex + FColCount;
|
|
VK_LEFT:
|
|
ItemIndex := FItemIndex - 1;
|
|
VK_RIGHT:
|
|
ItemIndex := FItemIndex + 1;
|
|
VK_PRIOR:
|
|
ItemIndex := FItemIndex - (FColCount * (ClientHeight div FRowHeight));
|
|
VK_NEXT:
|
|
ItemIndex := FItemIndex + (FColCount * (ClientHeight div FRowHeight));
|
|
VK_HOME:
|
|
ItemIndex := 0;
|
|
VK_END:
|
|
ItemIndex := FItems.Count - 1;
|
|
end;
|
|
inherited KeyDown(Key, Shift);
|
|
end;
|
|
|
|
procedure TCustomImageGrid.Loaded;
|
|
begin
|
|
inherited Loaded;
|
|
Rearrange;
|
|
end;
|
|
|
|
procedure TCustomImageGrid.MouseDown(Button: TMouseButton; Shift: TShiftState;
|
|
X, Y: Integer);
|
|
begin
|
|
if not (csDesigning in ComponentState) and CanFocus then
|
|
SetFocus;
|
|
inherited MouseDown(Button, Shift, X, Y);
|
|
end;
|
|
|
|
function TCustomImageGrid.MouseToIndex(X, Y: Integer): Integer;
|
|
var
|
|
Col: Integer;
|
|
Row: Integer;
|
|
begin
|
|
if PtInRect(ClientRect, Point(X, Y)) then
|
|
begin
|
|
Inc(Y, ScrollingPos);
|
|
Col := X div FColWidth;
|
|
Row := Y div RowHeight;
|
|
if (X < Col * FColWidth + CellWidth) and
|
|
(Y < Row * RowHeight + CellHeight) and
|
|
(Row * FColCount + Col < Count) then
|
|
Result := Row * FColCount + Col
|
|
else
|
|
Result := -1;
|
|
end
|
|
else
|
|
Result := -1;
|
|
end;
|
|
|
|
procedure TCustomImageGrid.MouseUp(Button: TMouseButton; Shift: TShiftState;
|
|
X, Y: Integer);
|
|
begin
|
|
if (not DragScrolling) and (Button = mbLeft) then
|
|
DoClickCell(MouseToIndex(X, Y));
|
|
inherited MouseUp(Button, Shift, X, Y);
|
|
end;
|
|
|
|
procedure TCustomImageGrid.MouseMove(Shift: TShiftState; X, Y: Integer);
|
|
var
|
|
Index, Col, Row, Y2: Integer;
|
|
begin
|
|
if PtInRect(ClientRect, Point(X, Y)) then
|
|
begin
|
|
Y2 := Y + ScrollingPos;
|
|
Col := X div FColWidth;
|
|
if Col > FColCount - 1 then
|
|
Index := -1
|
|
else
|
|
begin
|
|
Row := Y2 div RowHeight;
|
|
if (X < Col * FColWidth + CellWidth) and
|
|
(Y2 < Row * RowHeight + CellHeight) and
|
|
(Row * FColCount + Col < Count) then
|
|
Index := Row * FColCount + Col
|
|
else
|
|
Index := -1;
|
|
end;
|
|
end
|
|
else
|
|
Index := -1;
|
|
|
|
if (index >= 0) then
|
|
FItemIndex := index;
|
|
|
|
inherited MouseMove(Shift, X, Y);
|
|
end;
|
|
|
|
procedure TCustomImageGrid.Paint;
|
|
var
|
|
// DrawParentBackGround: Boolean;
|
|
// MouseOverThumb: Boolean;
|
|
// MouseOverStickers: Boolean;
|
|
UpdateCoords: TGridRect;
|
|
Offset: TPoint;
|
|
R: TRect;
|
|
Col: Integer;
|
|
Row: Integer;
|
|
Index: Integer;
|
|
TempThumb: TRnQBitmap;
|
|
Thumb: TPNGImage;
|
|
ThumbWidth: Integer;
|
|
ThumbHeight: Integer;
|
|
begin
|
|
// DrawParentBackGround := ParentBackground and (Parent <> nil) and StyleServices.Enabled;;
|
|
|
|
Canvas.Brush.Color := Color;
|
|
Canvas.Brush.Style := bsSolid;
|
|
if FMarkerStyle = psClear then
|
|
begin
|
|
Canvas.Pen.Color := Color;
|
|
Canvas.Pen.Style := psSolid;
|
|
end
|
|
else
|
|
begin
|
|
Canvas.Pen.Color := FMarkerColor;
|
|
Canvas.Pen.Style := FMarkerStyle;
|
|
end;
|
|
|
|
Canvas.FillRect(Canvas.ClipRect);
|
|
|
|
UpdateCoords.Left := Canvas.ClipRect.Left div FColWidth;
|
|
UpdateCoords.Top := (ScrollingPos + Canvas.ClipRect.Top) div RowHeight;
|
|
UpdateCoords.Right := Min(Canvas.ClipRect.Right div FColWidth, FColCount - 1);
|
|
UpdateCoords.Bottom := Min((ScrollingPos + Canvas.ClipRect.Bottom) div RowHeight, RowCount - 1);
|
|
Offset := Point(0, 0);
|
|
R.Left := UpdateCoords.Left * FColWidth;
|
|
R.Right := R.Left + FColWidth - FCellSpacing;
|
|
for Col := UpdateCoords.Left to UpdateCoords.Right do
|
|
begin
|
|
R.Top := UpdateCoords.Top * RowHeight - ScrollingPos;
|
|
R.Bottom := R.Top + RowHeight - FCellSpacing;
|
|
for Row := UpdateCoords.Top to UpdateCoords.Bottom do
|
|
begin
|
|
Index := Row * FColCount + Col;
|
|
if Index >= Count then
|
|
Break;
|
|
if FDefaultDrawing then
|
|
begin
|
|
Thumb := Thumbs[Index];
|
|
if Thumb = nil then
|
|
Canvas.Rectangle(R)
|
|
else
|
|
begin
|
|
ThumbWidth := Min(Thumb.Width, CellWidth);
|
|
ThumbHeight := Min(Thumb.Height, CellHeight);
|
|
|
|
TempThumb := TRnQBitmap.Create;
|
|
TempThumb.f32Alpha := True;
|
|
TempThumb.fFormat := PA_FORMAT_PNG;
|
|
TempThumb.fBmp := TBitmap.Create;
|
|
TempThumb.fBmp.Assign(Thumb);
|
|
TempThumb.fBmp.AlphaFormat := afPremultiplied;
|
|
TempThumb.fBmp.PixelFormat := pf32bit;
|
|
if Resample then
|
|
ResampleSticker(TempThumb.fBmp, round(ThumbHeight * 0.875), round(ThumbWidth * 0.875));
|
|
TempThumb.fHeight := TempThumb.fBmp.Height;
|
|
TempThumb.fWidth := TempThumb.fBmp.Width;
|
|
|
|
case FCellAlignment of
|
|
taCenter:
|
|
Offset.X := (R.Right - R.Left - TempThumb.fBmp.Width) div 2;
|
|
taRightJustify:
|
|
Offset.X := R.Right - R.Left - TempThumb.fBmp.Width;
|
|
end;
|
|
|
|
case FCellLayout of
|
|
tlCenter:
|
|
Offset.Y := (R.Bottom - R.Top - TempThumb.fBmp.Height) div 2;
|
|
tlBottom:
|
|
Offset.Y := R.Bottom - R.Top - TempThumb.fBmp.Height;
|
|
end;
|
|
|
|
//MouseOverThumb := Types.PtInRect(R, ScreenToClient(Mouse.CursorPos));
|
|
if Focused and (not Scrolling) and (FItemIndex = Index) then
|
|
begin
|
|
if (GetAsyncKeyState(VK_LBUTTON) <> 0) then
|
|
Canvas.Brush.Color := $00DEDEDE
|
|
else
|
|
Canvas.Brush.Color := $00E3E3E3;
|
|
|
|
Canvas.Brush.Style := bsSolid;
|
|
Canvas.RoundRect(R.Left + 2, R.Top + 2, R.Right - 2, R.Bottom - 2, 10, 10);
|
|
Canvas.Brush.Color := Color;
|
|
end;
|
|
|
|
SetStretchBltMode(Canvas.Handle, HALFTONE);
|
|
DrawRbmp(Canvas.Handle, TempThumb, R.Left + Offset.X, R.Top + Offset.Y);
|
|
TempThumb.Free;
|
|
end;
|
|
end
|
|
else if csDesigning in ComponentState then
|
|
Canvas.FillRect(R);
|
|
DoDrawCell(Index, Col, Row, R);
|
|
Inc(R.Top, RowHeight);
|
|
Inc(R.Bottom, RowHeight);
|
|
end;
|
|
Inc(R.Left, FColWidth);
|
|
Inc(R.Right, FColWidth);
|
|
end;
|
|
end;
|
|
|
|
procedure TCustomImageGrid.Rearrange;
|
|
var
|
|
NewClientWidth: Integer;
|
|
NewRowCount: Integer;
|
|
begin
|
|
if HandleAllocated then
|
|
begin
|
|
NewClientWidth := Width - 2 * TotalBorderWidth;
|
|
if not AutoHideScrollBar then
|
|
Dec(NewClientWidth, GetSystemMetrics(SM_CXVSCROLL));
|
|
FColCount := Max(1, (NewClientWidth + FCellSpacing) div FColWidth);
|
|
NewRowCount := Ceil(Count / FColCount);
|
|
if AutoHideScrollBar and
|
|
(NewRowCount * RowHeight > Height - 2 * TotalBorderWidth) then
|
|
begin
|
|
Dec(NewClientWidth, GetSystemMetrics(SM_CXVSCROLL));
|
|
FColCount := Max(1, (NewClientWidth + FCellSpacing) div FColWidth);
|
|
NewRowCount := Ceil(Count / FColCount);
|
|
end;
|
|
inherited RowCount := NewRowCount;
|
|
Invalidate;
|
|
end;
|
|
end;
|
|
|
|
procedure TCustomImageGrid.Resize;
|
|
begin
|
|
Rearrange;
|
|
inherited Resize;
|
|
end;
|
|
|
|
procedure TCustomImageGrid.ScrollInView(Index: Integer);
|
|
begin
|
|
Row := CoordFromIndex(Index).Y;
|
|
end;
|
|
|
|
procedure TCustomImageGrid.SetCellAlignment(Value: TAlignment);
|
|
begin
|
|
if FCellAlignment <> Value then
|
|
begin
|
|
FCellAlignment := Value;
|
|
Invalidate;
|
|
end;
|
|
end;
|
|
|
|
procedure TCustomImageGrid.SetCellHeight(Value: Integer);
|
|
begin
|
|
SetCellSize(CellWidth, Value);
|
|
end;
|
|
|
|
procedure TCustomImageGrid.SetCellLayout(Value: TTextLayout);
|
|
begin
|
|
if FCellLayout <> Value then
|
|
begin
|
|
FCellLayout := Value;
|
|
Invalidate;
|
|
end;
|
|
end;
|
|
|
|
procedure TCustomImageGrid.SetCellSize(ACellWidth, ACellHeight: Integer);
|
|
begin
|
|
if (CellWidth <> ACellWidth) or (CellHeight <> ACellHeight) then
|
|
SetCoordSize(ACellWidth + FCellSpacing, ACellHeight + FCellSpacing);
|
|
end;
|
|
|
|
procedure TCustomImageGrid.SetCellSpacing(Value: Integer);
|
|
var
|
|
Diff: Integer;
|
|
begin
|
|
Value := Max(0, Value);
|
|
if FCellSpacing <> Value then
|
|
begin
|
|
Diff := Value - FCellSpacing;
|
|
FCellSpacing := Value;
|
|
SetCoordSize(FColWidth + Diff, RowHeight + Diff);
|
|
end;
|
|
end;
|
|
|
|
procedure TCustomImageGrid.SetCellWidth(Value: Integer);
|
|
begin
|
|
SetCellSize(Value, CellHeight);
|
|
end;
|
|
|
|
procedure TCustomImageGrid.SetColWidth(Value: Integer);
|
|
begin
|
|
SetCoordSize(Value, RowHeight);
|
|
end;
|
|
|
|
procedure TCustomImageGrid.SetCoordSize(AColWidth, ARowHeight: Integer);
|
|
begin
|
|
if (FColWidth <> AColWidth) or (RowHeight <> ARowHeight) then
|
|
begin
|
|
FColWidth := Max(MinCellSize + FCellSpacing, AColWidth);
|
|
ARowHeight := Max(MinCellSize + FCellSpacing, ARowHeight);
|
|
inherited SetRowHeight(ARowHeight);
|
|
Rearrange;
|
|
end;
|
|
end;
|
|
|
|
procedure TCustomImageGrid.SetDefaultDrawing(Value: Boolean);
|
|
begin
|
|
if FDefaultDrawing <> Value then
|
|
begin
|
|
FDefaultDrawing := Value;
|
|
Invalidate;
|
|
end;
|
|
end;
|
|
|
|
procedure TCustomImageGrid.SetDesignPreview(Value: Boolean);
|
|
begin
|
|
if FDesignPreview <> Value then
|
|
begin
|
|
FDesignPreview := Value;
|
|
if csDesigning in ComponentState then
|
|
if not FDesignPreview then
|
|
begin
|
|
FItems.ClearThumbs;
|
|
Invalidate;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure TCustomImageGrid.SetFileFormats(Value: TStrings);
|
|
begin
|
|
FFileFormats.Assign(Value);
|
|
end;
|
|
|
|
procedure TCustomImageGrid.SetFileNames(Value: TStrings);
|
|
begin
|
|
FItems.Assign(Value);
|
|
end;
|
|
|
|
procedure TCustomImageGrid.SetFolder(Value: TPath);
|
|
const
|
|
FileAttributes = FILE_ATTRIBUTE_NORMAL or FILE_ATTRIBUTE_ARCHIVE or
|
|
FILE_ATTRIBUTE_READONLY;
|
|
var
|
|
SearchRec: TSearchRec;
|
|
I: Integer;
|
|
Path: TPath;
|
|
begin
|
|
if Value <> '' then
|
|
Value := IncludeTrailingPathDelimiter(Value);
|
|
if FFolder <> Value then
|
|
begin
|
|
FItems.BeginUpdate;
|
|
try
|
|
Clear;
|
|
for I := 0 to FFileFormats.Count - 1 do
|
|
begin
|
|
Path := Value + '*.' + FFileFormats[I];
|
|
if FindFirst(Path, FileAttributes, SearchRec) = 0 then
|
|
try
|
|
repeat
|
|
FItems.Add(Value + SearchRec.Name);
|
|
until FindNext(SearchRec) <> 0;
|
|
finally
|
|
FindClose(SearchRec);
|
|
end;
|
|
end;
|
|
finally
|
|
FItems.EndUpdate;
|
|
FFolder := Value;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure TCustomImageGrid.SetImage(Index: Integer; Value: TGraphic);
|
|
begin
|
|
FItems.Images[Index] := Value;
|
|
end;
|
|
|
|
procedure TCustomImageGrid.SetItemIndex(Value: Integer);
|
|
begin
|
|
if Count = 0 then
|
|
Value := -1
|
|
else
|
|
Value := Max(0, Min(Value, Count - 1));
|
|
if FItemIndex <> Value then
|
|
begin
|
|
FItemIndex := Value;
|
|
ScrollInView(FItemIndex);
|
|
Invalidate;
|
|
end;
|
|
end;
|
|
|
|
procedure TCustomImageGrid.SetItems(Value: TImageGridItems);
|
|
begin
|
|
FItems.Assign(Value);
|
|
end;
|
|
|
|
procedure TCustomImageGrid.SetMarkerColor(Value: TColor);
|
|
begin
|
|
if FMarkerColor <> Value then
|
|
begin
|
|
FMarkerColor := Value;
|
|
Invalidate;
|
|
end;
|
|
end;
|
|
|
|
procedure TCustomImageGrid.SetMarkerStyle(Value: TPenStyle);
|
|
begin
|
|
if FMarkerStyle <> Value then
|
|
begin
|
|
FMarkerStyle := Value;
|
|
Invalidate;
|
|
end;
|
|
end;
|
|
|
|
procedure TCustomImageGrid.SetProportional(Value: Boolean);
|
|
begin
|
|
if FProportional <> Value then
|
|
begin
|
|
FProportional := Value;
|
|
if FProportional then
|
|
FItems.ClearThumbs;
|
|
end;
|
|
end;
|
|
|
|
procedure TCustomImageGrid.SetRetainUnresolvedItems(Value: Boolean);
|
|
begin
|
|
if FRetainUnresolvedItems <> Value then
|
|
begin
|
|
FRetainUnresolvedItems := Value;
|
|
if not FRetainUnresolvedItems then
|
|
DeleteUnresolvedItems;
|
|
end;
|
|
end;
|
|
|
|
procedure TCustomImageGrid.SetRowHeight(Value: Integer);
|
|
begin
|
|
SetCoordSize(FColWidth, Value);
|
|
end;
|
|
|
|
procedure TCustomImageGrid.SetSorted(Value: Boolean);
|
|
begin
|
|
FItems.Sorted := Value;
|
|
end;
|
|
|
|
procedure TCustomImageGrid.SetResample(Value: Boolean);
|
|
begin
|
|
if FResample <> Value then
|
|
FResample := Value;
|
|
end;
|
|
|
|
procedure TCustomImageGrid.SetThumb(Index: Integer; Value: TPNGImage);
|
|
begin
|
|
FItems.Thumbs[Index] := Value;
|
|
end;
|
|
{
|
|
procedure TCustomImageGrid.ThumbsUpdated(Sender: TObject);
|
|
begin
|
|
if not FRetainUnresolvedItems then
|
|
DeleteUnresolvedItems;
|
|
end;
|
|
}
|
|
procedure TCustomImageGrid.WMEraseBkgnd(var Message: TWMEraseBkgnd);
|
|
begin
|
|
Message.Result := 1;
|
|
end;
|
|
|
|
procedure TCustomImageGrid.WMGetDlgCode(var Message: TWMGetDlgCode);
|
|
begin
|
|
inherited;
|
|
Message.Result := Message.Result or DLGC_WANTARROWS;
|
|
end;
|
|
|
|
end.
|
|
|