^ What's the point?
^ Usage
^ Functions

Download :: Topics on this subject on the Forum :: Top
Skeez

Skeez is an animated list view component for Delphi (Win32, Win64) based on Graphics32.
The package includes derived components: filesystem browser, picture list viewer and audio file list viewer.

Features:
  • Animated list view (add, refresh, delete, move)
  • Support for multi-line text with expandable height
  • Hot track, hint, scroll to/select item on keypress, edit item's caption
  • Re-draw existing item (partially) with optional animation
  • Multi-column mode
  • Custom sort the list
  • Built-in animations: XY, Zoom, FadeIn, or implement custom animation with an event
  • Filesystem browser with full support for virtual objects (PIDLs) and shell change notifications
  • Picture (thumbnail) list viewer class, uses FreeImage.dll for loading many formats of picture files and displays their EXIF information if available
  • Audio (tag) list viewer class with support for all the current audio tag standards
  • Fully customizable display with support for variable item height within the same list
  • The derived classes support browsing the file system or items can be added manually
  • Multi threaded derived classes

The audio list view component uses Tags Library, the used Delphi tagging libraries are also available separatelly:

ID3v1 and ID3v2 tagging unit: ID3v2 Library
MP4 tagging unit: MP4 Tag Library
APEv2 tagging unit: APEv2 Library
Ogg Vorbis and Opus tagging unit: Ogg Vorbis and Opus Tag Library
Flac tagging unit: Flac Tag Library
WMA tagging unit: WMA Tag Library
WAV tagging unit: WAV Tag Library

If you have any question, please write to: 3delite@3delite.hu



Skeez in shareware and commercial software?

The component is free for use in free software. If you like it and use it in a shareware or commercial (or any other money making - advertising, in app. selling, etc.) product you need one of the licenses.


Requirements

Delphi 2009 and above with Graphics32 installed.


Installation

If Graphics32 is not already installed, it's recommended to install it - although it's not needed to install it for Skeez to compile, it's enough to have the Graphics32 units on the search path. But Graphics32 is a great component you might want to decide to use it.

Extract the .zip archives ('bass24.zip', 'graphics32-code-2197-trunk.zip' and 'KleverComponents.zip') from where you installed/extracted Skeez files to a folder.

Create a new package, menu: File/New/Package - Delphi, save it with a new name, menu: File/Save Project As.... for example 'PackageSkeez.bpl'. On the upper-right corner of the Delphi window right mouse click on the package name you saved as, and click on 'Add' from the pop-up menu and add 'Skeez.pas', 'SkeezFilesystem.pas', 'SkeezPictures.pas' and optionally 'SkeezAudios.pas' and 'MultiThread2.pas' and 'Skeez.dcr' for the icon.
Add the directories to the tagging libraries ('..\Delphi\Tagging Libraries\APEv2 Library\' etc.) and all required .pas files to the search path too - Menu: Project/Options, select 'Delphi compiler', in the upper part of the window select 'All configuration', below click on 'Search path' and add the paths where you installed/extracted Skeez.
Right mouse click again on the package name and select 'Build', if successfull, again right mouse click and select 'Install'.

Note: If you get a package build error, comment out '{$DEFINE COMDRAGDROP}' in SkeezFilesystem.pas when building the package. If the build is successfull save the package and enable this compiler directive again - it should work for a real build.

If everything went smooth the components will show up on the '3delite' tab.

To be able to build the tutorials create a new package, as described above, and this time add 'rkShellPath.pas' and 'rkPathViewer.pas' to the package and use a different package name for example 'Packagerk.bpl'.
Build and install it too.

If everything went smooth the components will show up on the 'rmklever' tab.


Properties and methods
  • TSkeez.Items: List containing the TSkeezItem items. When changing this list by code after finished call 'ReIndexItems' and to update the display 'UpdateDisplay(True)'.

  • TSkeez.Selected: The currently selected item. When multiple items are selected, this is the last, recently, selected item.

  • TSkeez.MultiColumnCount: If 'MultiColumn' is True, items are drawn side-by-side if the display width is large enough for multiple columns. For example for 2 multi columns the needed space is HorizontalMargin * 2 + Item's total width for all the columns. Multi columns and item columns are 2 separate things. Columns specify an item's text and picture positions, while multi column specify to allow to draw the items horizontally side-by-side if enough space is available.

  • TSkeez.CurrentListingID: This number is incremented on every 'IncrementListingID' call. It us used to identify a listing, needed when for example navigating folders and icons are extracted in another thread, if the user navigates to another folder Skeez will not add the icons arriving after the navigation because the 'CurrentListingID' is not valid for the icon arriving.

  • TSkeez.ImageList: Array containing images that are meant to be re-used for multiple items. Add TBitmap32 pictures to this list and to use these images in the SkeezItem.AddPicture() calls' 'ImageListIndex' variable:
                with SkeezItem.AddPicture(nil) do begin
                    Position.X := 0;
                    Position.Y := 0;
                    ImageListIndex := 1;
                end;
    

  • TSkeez.ParseInQueue: It's essential to call this procedure periodically. Internally Skeez will parse the added 'TSkeezItem's with 'InQueue.Add(SkeezItem)'. 'InQueue.Add()' is a thread safe function (so it's fine to call it in threads), and in the main thread where this function is called will process (parse) the items added with 'InQueue.Add(SkeezItem)'. 'ItemParseMode' specifies how many items to parse for a single 'ParseInQueue' call. 'sipmOne' means one item on every call, which results linear animation, the items will move one by one with a delay how frequently 'ParseInQueue' is called. 'sipmAll' will process all items in the incomming queue, results faster displaying of the items but items will move together in parallel.

  • TSkeez.UpdateDisplay: Update all the items (advance one frame). You need to call this function to update the display (animate) at at least 33ms intervals (FPS = 1000 / interval). If an item is not changed it will not be updated, to force re-drawing all the items call this function with 'UpdateDisplay(True)' - for example if you change the order of items in the 'TSkeez.Items' list.

  • TSkeez.ItemAtPos: Use this function to get the 'TSkeezItem' at the specified position. You can use this function for example in OnMouseMove() event to track the currently hovered item.

  • TSkeez.Sort: Sort the items with the specified 'OnItemCompare' event. Use the 'Item.Data' class to perform the comparison. This object will be for example 'TSkeezAudioData(Item.Data).FileName' for the audio lister class, 'TSkeezFileData(Item.Data).FileName' for the file system browser component, or the one you added to 'SkeezItem.Data' when adding the skeez items. You should inherit from these types when using the picture and audio component and add your fields to it - this way Skeez will still be able to use these objects like identifying whether it's a folder or a file.

  • TSkeez.ReIndexItems: If you modify the 'TSkeez.Items' list, call this function to re-index the items, then call 'UpdateDisplay(True)'.

Published properties
  • AllowEdit: Enable possibility of editing the first text item of a Skeez item. Can be invoked from code with Skeez1.Edit(Index) or with middle mouse button clicking on an item. Notification of an edit is available with the OnItemEdit() event.

  • AllowHotTrack: Enable to mark the item below the mouse cursor. Use 'ItemHotTrackOptions' to specify the hot tracking colors and alpha value.

  • AllowKeySelect: If True and the Skeez control has focus, pressing a key on the keyboard scrolls to and selects the first item which matches the character (first text item's first character). If another key is pressed in 2 seconds, the first 2 characters are searched.

  • AllowMultiSelect: More than 1 item can be selected by holding down the Shift or Ctrl key and clicking with the left mouse button on items.

  • AllowSelect: Enable to select the item with the mouse cursor and keyboard cursor keys. Use 'ItemSelectionOptions' to specify the selection colors and alpha value.

  • AnimationExpandCollapseTime: Specify how long does an expand or collapse animation take when expanding multi-line texts.

  • AnimationPictureTime: Specify the picture moving time in milliseconds.

  • AnimationPictureX: Specify the pixel count from where the picture start to move.

  • AnimationTextTime: Specify the text moving time in milliseconds.

  • AnimationTextX: Specify the pixel count from where the text start to move.

  • BackgroundColor: Specify the display's background color.

  • HintHideTime: Specifies how long to display a hint. Implement OnItemHint() event to hide the hint.

  • HintShowTime: Specifies how long the mouse cursor needs hovered above an item to pop-up a hint. Implement OnItemHint() event to show the hint.

  • ItemAudioProperties / ItemFileProperties / ItemPictureProperties: Specify the properties of the items. 'ItemFileProperties' always specifies the file items' properties including when using the picture and audio lister. One of the important values is the 'ItemHeight' variable, which specifies the height of the items. Note that you can always specify a custom (item-by-item different) height when adding the TSkeezItems to the queue. File items and picture/audio items will have the same item width though. Use Icon/Picture/CoverArt to specify these pictures' dimensions on the display.

  • ItemHotTrackOptions: Specify the hot track colors and alpha value ('AllowHotTrack' needs to be 'True').

  • ItemSelectionOptions: Specify the selection colors and alpha value ('AllowSelection' needs to be 'True').

  • ItemParseMode: Specifies how many items to parse for a single 'ParseInQueue' call. 'sipmOne' means one item on every call, which results linear animation, the items will move one by one with a delay how frequently 'ParseInQueue' is called. 'sipmAll' will process all items in the incomming queue, results faster displaying of the items but items will move together in parallel.

  • MarginHorizontal: The padding (space) between the display's left side and the items. Also the margin on the right side of the display.

  • MarginVertical: The padding (space) between the display's top and the items. Also the margin at the bottom of the display below the last item.

  • MultiColumn: If 'MultiColumn' is True, items are drawn side-by-side if the display width is large enough for multiple columns. For example for 2 multi columns the needed space is HorizontalMargin * 2 + Item's total width for all the columns. Multi columns and item columns are 2 separate things. Columns specify an item's text and picture positions, while multi column specify to allow to draw the items horizontally side-by-side if enough space is available.

  • MultiThreaded: For the derived components, this value specifies to use multi threading for loading of the icon/picture/cover art pictures. If this is 'False' these pictures will be parsed in the main thread, which means if the CPU is not powerfull enough the animation will be jerky, but linear. It is recommended to always use multi-threading, for your implementation too.

  • OnlyFilesystem: When browsing folders display only file system items (folders and files).

Events
  • OnAddItem: Called when adding an item to the list, usefull for adding any custom text and pictures when using the file system/picture/audio components. You can add a column (about it later) and add custom informatiom. For example:
                with DisplayItem.AddText('My text') do begin
                    Position.X := 5;
                    Position.Y := 5;
                    ColumnIndex := 2;
                end;
    

  • OnCanAdd: Implement this event to filter what files are added to the list in case of the picture and audio component. Set 'Add' to False to not list the file.

  • OnFileSelect: If the user double-clicks an item which is not a folder this event is called.

  • OnFolderChange: Notification on going into a folder.

  • OnGetAudioAttributes: For the audio component implement this event to display the audio file's attributes like sample rate, channel count, etc.

  • OnItemCompare: When calling 'TSkeez.Sort' the items with the specified 'OnItemCompare' event will be sorted. Use the 'Item.Data' class to perform the comparison. This object will be for example 'TSkeezAudioData (Item.Data).FileName' for the audio lister class, 'TSkeezFileData(Item.Data).FileName' for the file system browser component, or the one you added to 'SkeezItem.Data' when adding the skeez items. You should inherit from these types when using the picture and audio component and add your fields to it - this way Skeez will still be able to use these objects like identifying whether it's a folder or a file.

  • OnItemEdit: If AllowEdit is True, after editing an item's first text item when user presses Enter this event is called. Set 'Allow' to False te reject the modification.

  • OnItemFree: Called when freeing an item. Implement clean-up of an item's 'Data' if needed.

  • OnItemHint: This event is called when a hint needs to show (Show = True) or needs to hide (Show = False).

  • OnItemHot: If 'AllowHotTrack' is True get notification when an item becomes hot.

  • OnItemSelect: Happens when the user selects an item with mouse clicking on it, or with the cursor keys (not double-click, that is OnFileSelect).

  • OnLayerDrawAfter / OnLayerDrawBefore: It's possible to draw on the TBitmap32 pictures that Skeez generates from TSkeezItems' text and picture lists with this event.

Tips
  • It is a good idea to prepare the item data in separate thread(s) with a lower priority then the main thread and use the main thread just for the UI.
    Load the data in a thread and with Skeez1.InQueue.Add(SkeezItem) send it to Skeez. The main UI thread will process this in the main thread when ParseInQueue is called which results smooth animations.
    One can easily implement multi threading with the included TMultiThread2 class (see the implementation in TSkeezFilesystem, TSkeezPictures or TSkeezAudios).

  • To add custom text or pictures to an item, use the OnAddItem() event, for example:
    with SkeezItem.AddText('My text') do begin
        Font.Size := 10;
        Position.X := 6;
        Position.Y := 6;
        ColumnIndex := 2;
    end;
    
    with SkeezItem.AddPicture(Bitmap32) do begin
        Position.X := 4;
        Position.Y := 6;
        //* This will use the 'Position' values, else the picture will be centered in it's column
        Align := paCustom;
    end;
    
  • By default 2 columns are created: first one for the icon/picture, second for the text. To add columns use:
    var
        Column: TSkeezColumn;
    begin
        //* Basic data
        Column := TSkeezColumn.Create;
        Column.Caption := 'Data';
        Column.Width := 350;
        Skeez1.Columns.Add(Column);
    end;
    
  • To update a text (or picture) of an existing item already in the list, send 'TSkeezItemText', 'TSkeezItemTextMultiLine' or 'TSkeezItemPicture' with 'InQueue.Add()'.
    There are 2 options: if you specify 'Index := - 1' then the object will be added, if you specify an existing object 'Index > - 1' (and exists) the text/picture will be replaced. Parent and ParentGUID are always needed to identify which item is to be updated. If you work in thread NEVER access the 'Work.ParentSkeezItem' fields, it could be freed in the mean time if the user navigated to another folder/list, just use it as identification (the pointer and the GUID) for the item to be updated. Extract from SkeezPictures.pas - PictureLoaderThreadWorkerCallback():
        //* Send the loaded picture to Skeez
        SkeezItemPicture := TSkeezItemPicture.Create;
        //* This needs to be a TSkeezItem which will be updated
        SkeezItemPicture.Parent := Work.ParentSkeezItem;
        //* This needs to be a TSkeezItem's GUID which will be updated
        SkeezItemPicture.ParentGUID := Work.ParentSkeezItemGUID;
        //* Use current ListingID, else this update will be
        //* discarded (list changed in the mean time)
        SkeezItemPicture.ListingID := Work.ListingID;
        SkeezItemPicture.Bitmap := Picture; //* The new picture
        Params.SkeezPictures.InQueue.Add(SkeezItemPicture);
    
        //* Send the original dimensions text to Skeez
        SkeezItemText := TSkeezItemText.Create;
        SkeezItemText.Parent := Work.ParentSkeezItem;
        SkeezItemText.ParentGUID := Work.ParentSkeezItemGUID;
        SkeezItemText.ListingID := Work.ListingID;
        //* The new text
        SkeezItemText.Text := IntToStr(OriginalWidth) + ' x ' + IntToStr(OriginalHeight);
        //* The 'TSkeezItemText' index in TSkeezItem.TextItems[Index] that you want to update
        SkeezItemText.Index := 2;
        //* This means the new text will be animated "in"
        SkeezItemText.AnimState := asStarting;
        Params.SkeezPictures.InQueue.Add(SkeezItemText);
    
  • When using Delphi's VCL styles use the following code to adjust the colors on style change (TSkeezFilesystem example):
    Uses
        GR32,
        Vcl.Themes,
        Vcl.Styles;
    
    procedure UpdateSkeezStyle(SkeezFilesystem: TSkeezFilesystem);
    var
        BackgroundColor: TColor;
        ListerFontColor: TColor;
        ColumnHeaderTopColor: TColor;
        ColumnHeaderBottomColor: TColor;
        ColumnHeaderFontColor: TColor;
        ColumnHeaderBrightColor: TColor;
        ColumnHeaderDarkColor: TColor;
        LStyle: TCustomStyleServices;
        Item: TSkeezItem;
        i, k: Integer;
    begin
        //* Style enabled?
        LStyle := StyleServices;
        if LStyle.Enabled
        AND (TStyleManager.ActiveStyle.Name <> 'Windows')
        then begin
            //* Get the current style's colors
            ColumnHeaderTopColor := LStyle.GetStyleColor(scGenericGradientBase);
            ColumnHeaderBottomColor := LStyle.GetStyleColor(scGenericGradientEnd);
            ColumnHeaderBrightColor := ColumnHeaderTopColor;
            ColumnHeaderDarkColor := ColumnHeaderBottomColor;
            ColumnHeaderFontColor := LStyle.GetStyleFontColor(sfHeaderSectionTextNormal);
            BackgroundColor := TStyleManager.ActiveStyle.GetStyleColor(scListView);
            ListerFontColor := TStyleManager.ActiveStyle.GetSystemColor(clWindowText);
        end else begin
            //* Set your default Windows style colors here (white theme used here)
            BackgroundColor := clWindow;
            ListerFontColor := clWindowText;
            ColumnHeaderTopColor := WinColor($FFFDFDFD);
            ColumnHeaderBottomColor := WinColor($FFBBBBBB);
            ColumnHeaderBrightColor := clWhite;
            ColumnHeaderDarkColor := WinColor($FFAAAAAA);
            ColumnHeaderFontColor := clWindowText;
        end;
        //* Set background color
        SkeezFilesystem.BackgroundColor := Color32(BackgroundColor);
        //* Set item text colors
        SkeezFilesystem.ItemFileProperties.FileName.Font.Color := ListerFontColor;
        SkeezFilesystem.ItemFileProperties.Size.Font.Color := ListerFontColor;
        SkeezFilesystem.ItemFileProperties.DateTime.Font.Color := ListerFontColor;
        SkeezFilesystem.ItemFileProperties.Description.Font.Color := ListerFontColor;
        //* Column header
        SkeezFilesystem.ColumnHeader.TopColor := Color32(ColumnHeaderTopColor);
        SkeezFilesystem.ColumnHeader.BottomColor := Color32(ColumnHeaderBottomColor);
        SkeezFilesystem.ColumnHeader.BrightColor := Color32(ColumnHeaderBrightColor);
        SkeezFilesystem.ColumnHeader.DarkColor := Color32(ColumnHeaderDarkColor);
        SkeezFilesystem.ColumnHeader.Font.Color := ColumnHeaderFontColor;
        SkeezFilesystem.DrawColumnHeaders;
        //* Redraw all items with new font color
        if SkeezFilesystem.Items.Count > 0 then begin
            for i := 0 to SkeezFilesystem.Items.Count - 1 do begin
                Item := SkeezFilesystem.Items[i];
                for k := 0 to Item.TextItems.Count - 1 do begin
                    Item.TextItems[k].Font.Color := ListerFontColor;
                end;
                for k := 0 to Item.TextMultiLineItems.Count - 1 do begin
                    Item.TextMultiLineItems[k].Font.Color := ListerFontColor;
                end;
                Item.ReDraw;
            end;
        end;
    end;
    
  • It's possible to modify the multi-line text expander/collapser icons by changing the SkeezIcons.res file. Using XN Resource Editor it's simple to edit the .res file, just use transparent PNG images and the same resource name for them. Or assign the pictures 'IconArrowDown', 'IconArrowUp', 'IconArrowDownHot' and 'IconArrowUpHot'.

Useful information


[Top]