(* ImageEn Build 7.0.0.06.2637 @ 7-4-17 14:58:42.679 *) (* Copyright (c) 1998-2017 by Carlotta Calandra. All rights reserved. Copyright (c) 2011-2017 by Xequte Software. This software comes without express or implied warranty. In no case shall the author be liable for any damage or unwanted behavior of any computer hardware and/or software. Author grants you the right to include the component in your application, whether COMMERCIAL, SHAREWARE, or FREEWARE. ImageEn, IEvolution and ImageEn ActiveX may not be included in any commercial, shareware or freeware libraries or components. www.ImageEn.com *) (* File version 1100 Doc revision 1004 *) unit iemview; {$R-} {$Q-} {$I ie.inc} {$IFDEF IEINCLUDEMULTIVIEW} interface uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, SyncObjs, {$ifdef IEHASTYPES} Types, {$endif} {$ifdef IEHASUITYPES} System.UITypes, {$endif} ExtCtrls, Clipbrd, stdctrls, iexBitmaps, hyiedefs, ImageEnView, ImageEnProc, ImageEnIO, ieview, iemio, iepresetim, ievect, ieanimation, iexTransitions, hyieutils; type {!! TIEImageAddEvent Declaration type TIEImageAddEvent = procedure(Sender : TObject; idx : integer; const sFilename : string; bFolder : boolean; bHiddenFile : boolean; iFileSizeBytes : Int64; CreateDate : TDateTime; EditDate : TDateTime; var bAllow : Boolean) of object; Description Occurs whenever an image is added to a or when using TImageEnMView.FillFromDirectory. Set bAllow to skip the addition of certain files. Value Description Sender The or idx The new position for this file sFilename The full path of the file or folder bFolder True for folders, false for files bHiddenFile True for files marked hidden in file properties iFileSizeBytes Size of the file in bytes CreateDate Date the file was created EditDate Date the file was last modified bAllow Defaults to false. Set to true to skip the addition of this file
Examples procedure TfMain.ImageEnMView1ImageAdd(Sender : TObject; idx : integer; const sFilename : string; bFolder : boolean; bHiddenFile : boolean; iFileSizeBytes : Int64; CreateDate : TDateTime; EditDate : TDateTime; var bAllow : Boolean); const ONE_MB = 1024 * 1024; begin // Don't add files larger than one MB if iFileSizeBytes > ONE_MB then bAllow := False; end; procedure TfMain.ImageEnMView1ImageAdd(Sender : TObject; idx : integer; const sFilename : string; bFolder : boolean; bHiddenFile : boolean; iFileSizeBytes : Int64; CreateDate : TDateTime; EditDate : TDateTime; var bAllow : Boolean); const ONE_YEAR = 365; begin // Don't add files more than a year old if EditDate < Now - ONE_YEAR then bAllow := False; end; !!} TIEImageAddEvent = procedure(Sender : TObject; idx : integer; const sFilename : string; bFolder : boolean; bHiddenFile : boolean; iFileSizeBytes : Int64; CreateDate : TDateTime; EditDate : TDateTime; var bAllow : Boolean) of object; {!! TIEImageSelectEvent Declaration type TIEImageSelectEvent = procedure(Sender: TObject; idx: integer) of object; Description Occurs whenever the user selects or deselects an image idx is the index of the selected image. !!} TIEImageSelectEvent = procedure(Sender: TObject; idx: integer) of object; {!! TIEMViewImageNotifyEvent Declaration type TIEMViewImageNotifyEvent = procedure(Sender: TObject; idx: integer) of object; Description Used by and . idx is the index of the relevant image. !!} TIEMViewImageNotifyEvent = procedure(Sender: TObject; idx: integer) of object; {!! TIESelectionChangingEvent Declaration type TIESelectionChangingEvent = procedure(Sender: TObject; var bAllow: Boolean) of object; Description Occurs prior to a change in the selected frame/thumbnail due to user action (i.e. mouse or keyboard). This can be used to prevent changing of a selection (e.g. due to the current selection not being saved). Example procedure TfMain.ImageEnMView1SelectionChanging(Sender: TObject; var bAllow: Boolean); begin // Don't allow changing of the selection if the user cancels saving of the selected image if fSelectedImageChanged and (PromptToSaveSelectedImageChanges = False) then bAllow := False; end; !!} TIESelectionChangingEvent = procedure(Sender: TObject; var bAllow: Boolean) of object; {!! TIECheckboxClickEvent Declaration type TIECheckboxClickEvent = procedure(Sender: TObject; idx: integer; var bChecked : Boolean) of object; Description Occurs whenever a user clicks a checkbox. idx is the index of the clicked image. bChecked specifies the new status of the image. You can override it, e.g. set it to false if the image cannot be checked Note: Don't read in this event which will not yet be valid. Use OnClick or OnMouseUp. Example procedure TfMain.ImageEnMView1CheckboxClick(Sender: TObject; idx: integer; var bChecked : Boolean); begin // Only allow JPEG images to be checked if bChecked and (IEFileIsOfFormat(ImageEnMView1.ImageFilename[idx], ioJPEG) = False) then begin MessageBeep(MB_ICONEXCLAMATION); bChecked := False; end; end; See Also - - !!} TIECheckboxClickEvent = procedure(Sender: TObject; idx: integer; var bChecked : Boolean) of object; {!! TIEImageIDRequestEvent Declaration type TIEImageIDRequestEvent = procedure(Sender: TObject; Index, ID: integer; var Bitmap: TBitmap) of object; Description Occurs when an image is required if you have specified a value for the property. Index is the index of the image being displayed (i.e. 0 for first image in the grid, 1 for second, etc.) ID is the value you have specified in property. Bitmap is the image to display. The bitmap is copied in , and then automatically freed. !!} TIEImageIDRequestEvent = procedure(Sender: TObject; Index, ID: integer; var Bitmap: TBitmap) of object; {!! TIEImageIDRequestExEvent Declaration type TIEImageIDRequestExEvent = procedure(Sender: TObject; Index, ID: integer; var Bitmap: ) of object; Description Occurs when an image is required if you have specified a value for the property. Index is the index of the image being displayed (i.e. 0 for first image in the grid, 1 for second, etc.) ID is the value you have specified in property Bitmap is the image to display. The bitmap is copied in , and then automatically freed. !!} TIEImageIDRequestExEvent = procedure(Sender: TObject; Index, ID: integer; var Bitmap: TIEBitmap) of object; {!! TIEMProgressEvent Declaration TIEMProgressEvent = procedure(Sender: TObject; per: integer; idx: integer) of object; Description Occurs during . per is the percentage of the progress (i.e. 100 indicates painting has finished). idx is the index of the image currently being drawn. !!} TIEMProgressEvent = procedure(Sender: TObject; per: integer; idx: integer) of object; {!! TIEWrongImageEvent Declaration TIEWrongImageEvent = procedure(Sender: TObject; OutBitmap: ; idx: integer; var Handled: boolean) of object; Description Used by whenever TImageEnMView cannot load the image specified in property, for instance when the file is corrupted or of an unrecognized format. idx specifies the image index. If you change the OutBitmap, also set Handled to True. If Handled is false, replaces the bitmap with a question mark image. !!} TIEWrongImageEvent = procedure(Sender: TObject; OutBitmap: TIEBitmap; idx: integer; var Handled: boolean) of object; {!! TIEImageDrawEvent Declaration TIEImageDrawEvent = procedure(Sender: TObject; idx: integer; Left, Top: integer; Canvas: TCanvas) of object; Description idx is the index of the image being painted Left is the X coordinate of the top-left corner of the thumbnail Top is the Y coordinate of the top-left corner of the thumbnail. Canvas is the canvas to draw to. !!} TIEImageDrawEvent = procedure(Sender: TObject; idx: integer; Left, Top: integer; Canvas: TCanvas) of object; {!! TIEImageDraw2Event Declaration TIEImageDraw2Event = procedure(Sender: TObject; idx: integer; Left, Top: integer; ImageRect: TRect; Canvas: TCanvas) of object; Description idx is the index of the image being painted Left is the X coordinate of the top-left corner of the thumbnail Top is the Y coordinate of the top-left corner of the thumbnail. ImageRect is the actual image rectangle. Canvas is the canvas to draw to. !!} TIEImageDraw2Event = procedure(Sender: TObject; idx: integer; Left, Top: integer; ImageRect: TRect; Canvas: TCanvas) of object; {!! TIEImageDrawEventEx Declaration } TIEImageDrawEventEx = procedure(Sender: TObject; idx: integer; Left, Top: integer; Dest: TBitmap; var ThumbRect: TRect) of object; {!!} {!! TIEImageOutEvent Declaration TIEImageOutEvent = procedure(Sender: TObject; idx: integer; OutBitmap: ) of object; Description Used by during thumbnail drawing, just prior to the drawing of the image. idx specifies the image index. OutBitmap is the image to be drawn. !!} TIEImageOutEvent = procedure(Sender: TObject; idx: integer; OutBitmap: TIEBitmap) of object; {!! TIEImageAtPosEvent Declaration TIEImageAtPosEvent = procedure(Sender: TObject; var idx: integer; x, y: Integer) of object; Description Used by the event to check if the specified coordinates are inside a thumbnail. idx contains the proposed image thumbnail index. You can change this value or set it to -1 for no thumbnail. !!} TIEImageAtPosEvent = procedure(Sender: TObject; var idx: integer; x, y: Integer) of object; {!! TIECreateImageEvent Declaration TIECreateImageEvent = procedure(Sender: TObject; idx: integer) of object; Description Used by whenever (immediately after) a new image is created. !!} TIECreateImageEvent = procedure(Sender: TObject; idx: integer) of object; {!! TIEDestroyImageEvent Declaration TIEDestroyImageEvent = procedure(Sender: TObject; idx: integer) of object; Description Used by whenever (immediately before) an image is destroyed. !!} TIEDestroyImageEvent = procedure(Sender: TObject; idx: integer) of object; {!! TIEProcessStreamEvent Declaration TIEProcessStreamEvent = procedure(Sender: TObject; Stream: TStream) of object; Description Used when loading/saving snapshots to specify extra parameters. !!} TIEProcessStreamEvent = procedure(Sender: TObject; Stream: TStream; Version : Byte) of object; {!! TIEImageEnMViewSortCompare Declaration TIEImageEnMViewSortCompare = function(Item1, Item2: integer): Integer; Description A comparison function that indicates how the items are to be ordered. Return a value below 0 if Item1 is less than Item2 Return 0 if they are equal Return a value above 0 if Item1 is greater than Item2 !!} TIEImageEnMViewSortCompare = function(Item1, Item2: integer): Integer; {!! TIEImageEnMViewSortCompareEx Declaration TIEImageEnMViewSortCompareEx = function(Item1, Item2: integer): Integer of object; Description A comparison function that indicates how the items are to be ordered. Return a value below 0 if Item1 is less than Item2 Return 0 if they are equal Return a value above 0 if Item1 is greater than Item2 !!} TIEImageEnMViewSortCompareEx = function(Item1, Item2: integer): Integer of object; {!! TIEImageEnMViewSortBy Declaration TIEImageEnMViewSortBy = (iesbFilename, iesbTopText, iesbBottomText, iesbInfoText, iesbImageSize, iesbFilenameWithoutPath, iesbFileExtension, iesbFileSize, iesbCreateDate, iesbEditDate, iesbFileType, iesbNone); Description Value Description iesbFilename Sorts by the full file path (using ) iesbTopText Alphabetical sort on iesbBottomText Alphabetical sort on iesbInfoText Alphabetical sort on iesbImageSize Sorting by the image dimensions ( x ) iesbFilenameWithoutPath Sorts only on the name portion of the file (i.e. excluding the file path) iesbFileExtension Sorts by the extension of the file (e.g. .jpeg or .tiff) iesbFileSize Sorting by the size of the files on disk iesbCreateDate Sorting by the date that the files were created (Note: If the image contains an EXIF date, it is used rather than the file date for improved accuracy) iesbEditDate Sorting by the date that the files were last modified iesbFileType Sorting by the file type iesbCustom only: Sorts using the event, (has no effect in TImageEnMView) iesbNone No sorting
!!} TIEImageEnMViewSortBy = (iesbFilename, iesbTopText, iesbBottomText, iesbInfoText, iesbImageSize, iesbFilenameWithoutPath, iesbFileExtension, iesbFileSize, iesbCreateDate, iesbEditDate, iesbFileType, iesbCustom, iesbNone); {!! TIEImageEnMViewIconSize Declaration TIEImageEnMViewIconSize = (ieicStandardSize, ieicDoubleSize, ieicStretchHD, ieicStretchAll); Description Value Description ieicStandardSize Displays a 32x32 icon in the centre of the thumbnail box ieicDoubleSize Stretches the icon to 64x64 and displays it in the centre of the thumbnail box ieicStretchHD Under Windows Vista and newer, high quality icons are stretched to the display size, Low quality icons are shown at double size (ieicDoubleSize). On XP and older versions of Windows it functions the same as _icoDoubleSize. ieicStretchAll Under Windows Vista and newer, all icons (low and high quality) are stretched to the display size. On XP and older versions of Windows it functions the same as _icoDoubleSize.
!!} TIEImageEnMViewIconSize = (ieicStandardSize, ieicDoubleSize, ieicStretchHD, ieicStretchAll); {!! TIEMCheckboxType Declaration TIEMCheckboxType = (iecbNone, iecbShowOnHover, iecbAlways); Description Value Description iecbNone Checkboxes are not shown/supported iecbShowOnHover Checkboxes are shown when a thumbnail is selected, checked, or when hovered over with the mouse iecbAlways Checkboxes are always shown on thumbnails
!!} TIEMCheckboxType = (iecbNone, iecbShowOnHover, iecbAlways); {!! TIEMCheckboxPos Declaration TIEMCheckboxPos = (iecpTopLeft, iecpTopRight, iecpBottomLeft, iecpBottomRight); Description Value Description iecpTopLeft Checkboxes display in the top left of the thumbnail box iecpTopRight Checkboxes display in the top right of the thumbnail box iecpBottomLeft Checkboxes display in the bottom left of the thumbnail box iecpBottomRight Checkboxes display in the bottom right of the thumbnail box
!!} TIEMCheckboxPos = (iecpTopLeft, iecpTopRight, iecpBottomLeft, iecpBottomRight); {!! TIEMSelectMode Declaration TIEMSelectMode = (imsNever, imsAuto, imsAlways); Description Value Description imsNever The inserted frame is not selected imsAuto The inserted frame is selected if there is currently no selection imsAlways The inserted frame is selected
!!} TIEMSelectMode = (imsNever, imsAuto, imsAlways); {!! TIEThumbSizeType Declaration TIEThumbSizeType = (itsImage, itsCell, itsOuter); Description Value Description itsImage Returns the size of the thumbnail image as displayed itsCell Returns the size of the thumbnail cell (image, text and cell border) itsOuter Returns the size of the thumbnail cell and its external spacing (image, text, cell border and horizontal/vertical border)
!!} TIEThumbSizeType = (itsImage, itsCell, itsOuter); {!! TIEImageEnMViewDefaultText Declaration type TIEImageEnMViewDefaultText = (iedtNone, iedtFilename, iedtFilenameNoExt, iedtFilePath, iedtImageDimensions, iedtImageDimAndSize, iedtFileSize, iedtFileCreateDate, iedtFileCreateDateTime, iedtFileCreateDateAndSize, iedtFileEditDate, iedtFileEditDateTime, iedtFileEditDateAndSize, iedtFileType, iedtFileExt) Description Default values for
, and Value Uses Field Displays Example iedtNone Caption will be blank, by default iedtFilename IEM_Filename Name of the file (without path) 'MyImage.jpg' iedtFilenameNoExt IEM_FilenameNoExt Name of the file without its extension (or path) 'MyImage' iedtFilePath IEM_FilePath Path of the file 'C:\Data\My Pictures\' iedtImageDimensions IEM_ImageDimensions Dimensions and color depth of images (Nothing is shown for non-images) '1200 x 800' iedtImageDimAndSize IEM_ImageDimAndSize Dimensions of images with the file size '1200 x 800, 3,900 KB' iedtFileSize IEM_FileSize Size of the file on disk '3,900 KB' iedtFileCreateDate IEM_FileCreateDate The date that the file was created '7/5/13' iedtFileCreateDateTime IEM_FileCreateDateTime The date and time that the file was created '7/5/13 8:03am' iedtFileCreateDateAndSize IEM_FileCreateDateAndSize The create date of the file and its size '7/5/13, 3,900 KB' iedtFileEditDate IEM_FileEditDate The date that the file was last edited '7/5/13' iedtFileEditDateTime IEM_FileEditDateTime The date and time that the file was last edited '7/5/13 8:03am' iedtFileEditDateAndSize IEM_FileEditDateAndSize The last edit date of the file and its size '7/5/13, 3,900 KB' iedtFileType IEM_FileType The ImageEn type for this file 'JPEG Image' iedtFileExt IEM_FileExt The extension only of the file, e.g. JPEG for 'MyImage.jpeg' 'JPEG'
Example // Display the filename and dimensions for each image in C:\Images IEFolderMView1.DefaultImageInfoText := iedtImageDimensions; IEFolderMView1.DefaultImageBottomText := iedtFilename; IEFolderMView1.RefreshFileList; end; !!} TIEImageEnMViewDefaultText = (iedtNone , iedtFilename , iedtFilenameNoExt , iedtFilePath , iedtImageDimensions , iedtImageDimAndSize , iedtFileSize , iedtFileCreateDate , iedtFileCreateDateTime , iedtFileCreateDateAndSize , iedtFileEditDate , iedtFileEditDateTime , iedtFileEditDateAndSize , iedtFileType , iedtFileExt ); {!! TIEStoreType Declaration type TIEStoreType = (ietNormal, ietThumb, ietFastThumb); Description Specifies how images are loaded. Value Description ietNormal The full bitmap is kept in memory ietThumb A sub-sampled copy of the bitmap is kept in memory (of the size specified by and ). ietFastThumb Only the cached image of the display thumbnail is held in memory. If the thumbnail is cleared from the cache it will need to be reloaded
ietThumb vs ietFastThumb When using ietFastThumb, creation of the thumbnail is delayed until it is shown on screen. Prior to this a full size image of each frame may be held in memory. For this reason ietFastThumb should not be used unless thumbnail frames are being loaded on demand (or there is not a large amount of off-screen frames). ietFastThumb can improve the quality of thumbnails, particularly when using and . It cannot be used if you have disabled image caching. If you are using ietFastThumb then you should significantly increase the to something larger, such as 200. !!} TIEStoreType = ( // the image will be full loaded ietNormal, // the image will loaded as thumbnail (see ThumbWidth, ThumbHeight)) ietThumb, // Thumbnail creation is delayed until it is drawn, then it is stored in CacheImage and Image is cleared ietFastThumb ); {!! TIEFolderImageType Declaration type TIEFolderImageType = (ieftSupportedImage, ieftFile, ieftFolder); Description Returns the type of file for a frame/thumbnail. Value Description ieftSupportedImage The frame is a supported image (or video) type ieftFile The frame is for an unknown file type ieftFolder The frame is a system folder or drive
!!} TIEFolderImageType = (ieftSupportedImage, ieftFile, ieftFolder); {!! TIEMTextPos Declaration } TIEMTextPos = (iemtpTop, iemtpBottom, iemtpInfo); {!!} // Whether thumbnails in the cache list can be reused after an update // Only supported by TIEDBMultiBitmap TIEImageCacheReusage = (iecrNone, // No reuse of cached images iecrLoose, // Most Reuse: Any cached thumbnails with matching filename iecrStrict // Least Reuse: Any cached thumbnails with matching filename at same indexed position ); {!! TIEGetTextEvent Declaration type TIEGetTextEvent = procedure(Sender: TObject; Index: integer; Position :
; var Text: WideString) of object; Description Occurs before text is output when drawing a thumbnail allowing you to insert or modify the displayed text (by specifying a new value for Text). Position Description iemtpTop Overrides the text specified for iemtpInfo Overrides the text specified for iemtpBottom Overrides the text specified for
Note: - Ensure that you have set / to allow space for the text - Setting Text only modifies the text that is displayed, not the value in ImageTopText/ImageInfoText/ImageBottomText Example // Note: In form create we set IEFolderMView.UpperGap := 20; // Display the file index above the frame procedure TForm1.IEFolderMViewGetText(Sender: TObject; Index: Integer; Position: TIEMTextPos; var Text: WideString); begin if Position = iemtpTop then Text := 'File #' + IntToStr(Index + 1); end; !!} TIEGetTextEvent = procedure(Sender: TObject; Index: integer; Position : TIEMTextPos; var Text: WideString) of object; {!! TIEGetTextExEvent Declaration type TIEGetTextExEvent = procedure(Sender: TObject; Index: integer; Position : ; var Text: WideString; Font : TFont; var BackgroundStyle: TBrushStyle; var BackgroundColor: TColor; var TruncSide: ) of object; Description Occurs before text is output when drawing a thumbnail allowing you to insert or modify the displayed text or change its formatting. Position Description iemtpTop Overrides the text specified for iemtpInfo Overrides the text specified for iemtpBottom Overrides the text specified for
Note: - Ensure that you have set / to allow space for the text - Setting Text only modifies the text that is displayed, not the value in ImageTopText/ImageInfoText/ImageBottomText - Font.Color cannot be overriden for selected or disabled frames Example // Display the file as bold if it is JPEG procedure TForm1.IEFolderMViewGetTextEx(Sender: TObject; Index: Integer; Position: TIEMTextPos; var Text: WideString; Font : TFont; var BackgroundStyle: TBrushStyle; var BackgroundColor: TColor; var TruncSide: TIEMTruncSide); begin if Position <> iemtpBottom then exit; sFileExt := ExtractFileExt( Text ); if IEExtToFileFormat( sFileExt ) = ioJPEG then Font.Style := [fsBold] else Font.Style := []; end; // Give text on every thumb a random background color procedure TForm1.IEFolderMViewGetTextEx(Sender: TObject; Index: Integer; Position: TIEMTextPos; var Text: WideString; Font : TFont; var BackgroundStyle: TBrushStyle; var BackgroundColor: TColor; var TruncSide: TIEMTruncSide); begin BackgroundColor := RGB(Random(255), Random(255), Random(255));; BackgroundStyle := bsSolid; end; !!} TIEGetTextExEvent = procedure(Sender: TObject; Index: integer; Position : TIEMTextPos; var Text: WideString; Font : TFont; var BackgroundStyle: TBrushStyle; var BackgroundColor: TColor; var TruncSide: TIEMTruncSide) of object; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// {!! TIEMThumbnailOptionsEx Declaration type TIEMThumbnailOptionsEx = set of (ietxCenterThumbnailColumn, ietxShowIconForUnknownFormat, ietxShowIconWhileLoading, ietxShowShadowForIcons, ietxShowShadowForFolders, ietxEnableInternalIcons, ietxStretchSmallImages, ietxOnlyShowIcons); Description Value Description ietxCenterThumbnailColumn If enabled and one or more columns are displayed (i.e. <> 0) then the thumbnails will be centered horizontally in the view (but not vertically centered). If enabled and only one row is displayed (i.e. = 0) then the thumbnails will be centered vertically in the view (but not horizontally centered). When not enabled, the top-left thumbnail will always be at a distance of x from the corner. ietxShowIconForUnknownFormat If enabled, then for any ImageFileName of an unknown format ImageEn will load the default icon for that file type (retrieved from Windows using the ShGetFileInfo Shell API function). Otherwise a question mark is displayed. Note: Don't disable this option if you are showing folders ietxShowIconWhileLoading If enabled, then the default icon for each file type is displayed while the content is loaded (retrieved from Windows using the ShGetFileInfo Shell API function). Otherwise a blank thumbnail is displayed. ietxShowShadowForIcons If is enabled, then this option determines whether the shadow is displayed for file icons ietxShowShadowForFolders If is enabled, then this option determines whether the shadow is displayed for folder icons ietxEnableInternalIcons If ietxShowIconWhileLoading is not specified, then while loading either a blank or internal icon will be displayed (can be set with ). Also, when specified an internal icon is shown for files that cannot be found(can be set with ). ietxStretchSmallImages If specified, images smaller than the thumbnail cell will be stretched (resampled) to the size of other thumbnail images. If not specified, small images shown at 100% size. ietxOnlyShowIcons Disables image thumbnails and only shows file icons (even for supported image types.
Example 1 // Use icons for unknown files ImageEnMView1.ThumbnailOptionsEx := ImageEnMView1.ThumbnailOptionsEx + [ietxShowIconForUnknownFormat]; // Display all files (not only image files) ImageEnMView1.FillFromDirectory('C:\', -1, true); Example 2 // Do not show shadows for any icon types ImageEnMView1.ThumbnailOptionsEx := ImageEnMView1.ThumbnailOptionsEx - [ietxShowShadowForIcons, ietxShowShadowForFolders]; // Redraw the display ImageEnMView1.Update; Example 3 // Create a single column of centered thumbnails ImageEnMView1.GridWidth := 1; ImageEnMView1.ThumbnailOptionsEx := ImageEnMView1.ThumbnailOptionsEx + [ietxCenterThumbnailColumn]; ImageEnMView1.Update; Example 4 // Show file list with icons ImageEnMView1.ThumbnailOptionsEx := ImageEnMView1.ThumbnailOptionsEx + [ ietxOnlyShowIcons ]; ImageEnMView1.GridWidth := 1 ImageEnMView1.SetStyleEx( iemsFlatAndWide, iedtNone, iedtNone, iedtFileName, -24 ); See Also - - - !!} TIEMThumbnailOptionsExItems = (ietxCenterThumbnailColumn, ietxShowIconForUnknownFormat, ietxShowIconWhileLoading, ietxShowShadowForIcons, ietxShowShadowForFolders, ietxEnableInternalIcons, ietxStretchSmallImages, ietxOnlyShowIcons); TIEMThumbnailOptionsEx = set of TIEMThumbnailOptionsExItems; {!! TIEMIOOptionsEx Declaration type TIEMIOOptionsEx = set of (ieixLoadOnlyByFileExt, ieixWantParams, ieixRemoveCorrupted); Description Value Description ieixLoadOnlyByFileExt By default, file types are determined by analyzing the message header. A quicker method is to use the file extension to determine the file type. Though this means that images with incorrect or invalid file extensions will not load ieixWantParams When using ieixLoadOnlyByFileExt or loading of is skipped, so text fields that display this data will be empty. Enabling this option forces the loading of params ieixRemoveCorrupted Images within the grid that are invalid will be automatically removed
Example // Use the file extension to determine its type (to increase speed) ImageEnMView1.IOOptionsEx := ImageEnMView1.IOOptionsEx + [ ieixLoadOnlyByFileExt ]; // Automatically remove any corrupted (unreadable) images from the grid. ImageEnMView1.IOOptionsEx := ImageEnMView1.IOOptionsEx + [ ieixRemoveCorrupted ]; !!} TIEMIOOptionsExItems = (ieixLoadOnlyByFileExt, ieixWantParams, ieixRemoveCorrupted); TIEMIOOptionsEx = set of TIEMIOOptionsExItems; // automatic interactions with mouse {!! TIEMMouseInteractItems Declaration } TIEMMouseInteractItems = ( mmiScroll, // Hand-scroll. Mouse drag scrolls images. mmiSelect // Images selection. Mouse click select images. ); {!!} {!! TIEMMouseInteract Declaration type TIEMMouseInteract = set of ; Description Value Description mmiScroll Dragging the mouse will scroll the images mmiSelect Clicking the mouse will select images
!!} TIEMMouseInteract = set of TIEMMouseInteractItems; {!! TIEMKeyInteractItems Declaration } // automatic interaction with keyboard TIEMKeyInteractItems = ( mkiMoveSelected // move selected item (up, down, left, right) ); {!!} {!! TIEMKeyInteract Declaration TIEMKeyInteract = set of
; !!} TIEMKeyInteract = set of TIEMKeyInteractItems; {!! TIEMDisplayMode Declaration type TIEMDisplayMode = (mdGrid, mdSingle); Description Value Description mdGrid Thumbnail view: Images are shown in a grid (of columns) mdSingle Frame view: Only one image is shown at a time (specified by property)
!!} TIEMDisplayMode = ( mdGrid, // grid (active fGridWidth property) mdSingle // single frame ); {!! TIESeek Declaration TIESeek = (iskLeft, iskRight, iskUp, iskDown, iskFirst, iskLast, iskPagDown, iskPagUp); Description Value Description iskLeft Move to the left (by one column) iskRight Move to the right (by one column) iskUp Move up (by one row) iskDown Move down (by one row) iskFirst Move to first image iskLast Move to the last image iskPagDown Move to the next page iskPagUp Move to the previous page iskPrior Same as iskLeft, but reversed when is bdRightToLeft iskNext Same as iskRight, but reversed when is bdRightToLeft
!!} TIESeek = (iskLeft, iskRight, iskUp, iskDown, iskFirst, iskLast, iskPagDown, iskPagUp, iskPrior, iskNext); {!! TIEMStyle Declaration TIEMStyle = (iemsFlat, iemsACD, iemsFlatAndWide, iemsColumns); Description Value Description iemsFlat Flat style iemsACD 3D style (default) iemsFlatAndWide Flat style with text on the right-hand side iemsColumns Separate columns are used for thumbnails and text fields
Notes on iemsColumns A header row is displayed with the iemsColumns style.
is used for the font formatting, but this can be overriden in the event. The header row caption is based on the default text, but can be overriden in or . Columns will be shown for text fields which have text specified (e.g. using ) and a valid width. Columns are displayed in the order: , , . !!} TIEMStyle = (iemsFlat, iemsACD, iemsFlatAndWide, iemsColumns); {!! TIEMultiSelectionOptions Declaration TIEMultiSelectionOptions = set of (iemoRegion, iemoSelectOnMouseUp, iemoLeaveOneSelected, iemoRegionOnShift, iemoOptimizeForDragging, iemoSelectOnRightClick); Description Value Description iemoRegion Select only items inside selection rectangle iemoSelectOnMouseUp By default, ImageEn selects an image on mouse down. If iemoSelectOnMouseUp is specified, ImageEn delays selection until mouse up iemoLeaveOneSelected If specified, at least one item remains selected. Note: works only when the user deselects multiple images iemoRegionOnShift If specified, pressing Shift only selects items inside rectangle iemoOptimizeForDragging Makes the behavior closer to Windows Explorer when selecting a region. If you click outside a selection it creates a region, if you click on an existing selection it does nothing. This is particularly useful if you need to support dragging iemoSelectOnRightClick Makes the behavior closer to Windows Explorer. When right-clicking outside the selection the new frame is selected. By default this is not specified, meaning that right-clicking has no effect on selection
!!} TIEMultiSelectionOptions = set of (iemoRegion, iemoSelectOnMouseUp, iemoLeaveOneSelected, iemoRegionOnShift, iemoOptimizeForDragging, iemoSelectOnRightClick); {!! TIEPlayFrameEvent Declaration } TIEPlayFrameEvent = procedure(Sender: TObject; FrameIndex: integer; var bShowFrame: Boolean) of object; {!!} TImageEnMView = class; TIEStarter = class(TThread) public mview: TImageEnMView; resumeEvent: THandle; constructor Create; destructor Destroy; override; procedure Execute; override; end; // CLASSES TO HANDLE CACHING OF ICONS // NPC: 10/6/14 TCachedIconType = (citFullDraw, citIconOnly); TIECachedIcon = class private public Bmp : TIEBitmap; Ext : string; constructor Create(aBmp: TIEBitmap; const sExt: string); destructor Destroy(); override; function MatchesExt(const sExt : string) : Boolean; end; TIECachedIconList = class private fOwner : TImageEnMView; fMaxIconCount : Integer; fDataList : TList; fOwnerSoftShadowEnabled : Boolean; fOwnerSoftShadowRadius : Double; procedure ClearLastItem(); function LookUpExt(const sExt : string) : Integer; function GetCacheName(aType : TCachedIconType; const sFilename : string; bIsFolder : Boolean) : string; public constructor Create(Owner : TImageEnMView; iMaxIconCount : Integer); destructor Destroy(); override; procedure Clear(); function RetrieveFromCache(aType : TCachedIconType; const sFilename : string; bIsFolder : Boolean; var Dest : TIEBitmap; bWantCopy : Boolean): boolean; procedure SaveToCache(Image : TIEBitmap; aType : TCachedIconType; const sFilename : string; bIsFolder : Boolean); end; {!! TIEAnimationTextEvent Declaration } TIEAnimationTextEvent = procedure(Sender: TObject; imageIndex: integer; var text: WideString) of object; {!!} {!! TIEAfterEvent Declaration TIEAfterEventEvent = procedure(Sender: TObject; Event:
) of object; Description } TIEAfterEvent = (ieaeMouseDown, ieaeMouseUp, ieaeKeyDown, ieaeKeyUp, ieaePaint); {!!} {!! TIEAfterEventEvent Declaration TIEAfterEventEvent = procedure(Sender: TObject; Event: ) of object; Description Occurs after ImageEn has processed an event. !!} TIEAfterEventEvent = procedure(Sender: TObject; Event: TIEAfterEvent) of object; {!! TIEMViewerGestures Description TImageEnMView supports native Windows gestures: - Dragging the screen to pan an image - Pinching to zoom in - Reverse-pinching to zoom out This class contains the properties to configure the gestures. Methods and Properties !!} TIEMViewerGestures = class private fPan: TIEGesturePanOptions; fZoom: TIEGestureZoomOptions; function GetEnabled(): boolean; public constructor Create(); destructor Destroy(); override; {!! TIEMViewerGestures.Enabled Declaration property Enabled: boolean; (Read-only) Description Returns true whenever at least one gesture is enabled. !!} property Enabled: boolean read GetEnabled; {!! TIEMViewerGestures.Pan Declaration property Pan: ; Description Allows enabling and configuration of the Pan (image scrolling) gesture. The Windows gesture to "Pan with inertia" is performed on the action of "dragging 1 or 2 fingers". !!} property Pan: TIEGesturePanOptions read fPan; {!! TIEMViewerGestures.Zoom Declaration property Zoom: ; Description Allows enabling and configuration of the Zoom gesture. The Windows gesture of "Zoom" is performed by "moving two fingers apart/towards each other". !!} property Zoom: TIEGestureZoomOptions read fZoom; end; {!! TImageEnMView Description The TImageEnMView component is similar to a , but is designed for multiple images: - Multiple images can be displayed in a grid (similar to a thumbnail view in Windows Explorer) - A single frame of a multiple-frame image (such as a GIF, AVI or TIFF) can be displayed. This can also be animated. ImageEn supports loading and saving multiple frames from GIF, TIFF, AVI, DCX, DICOM and ICO formats. It can also load from CUR format, and save to PDF and PS format (loading of PDF is supported if a relevant plug-in is installed). The images can be stored as full images, as thumbnails (a sub-resampled image of the original), loaded when displayed (you need only specify the file name), or upon request (an event is generated whenever an image needs to be shown). Thumbnails for video formats are retrieved from Windows Explorer. This can be disabled or expanded by setting . For rapid UI development a full set of actions is also available. You can also specify a custom function whenever an image is shown (i.e., to paint the image index near the image). Note: Do not attach a component to TImageEnMView. Only the component can be attached to a TImageEnMView component, or you can use embedded object. Demos Demos\Multi\... Demos\Other\Actions_MView\MViewActions.dpr Example // In FormCreate() with ImageEnMView1 do begin // Update to the most modern styling SetModernStyling(False); ThumbWidth := 140; // Better size for thumbnails ThumbHeight := 150; GridWidth := -1; // Auto-column widths BorderStyle := bsNone; // Normally don't require a 3D border StoreType := ietThumb; // Don't need to store whole image in memory, just a sub-sampled thumbnail end; // Now display the images of a folder in the grid ImageEnMView1.FillFromDirectory('C:\MyImages\', -1, False, '', False, '', True); Methods and Properties Display (Column count) Frame Editing Image Access Image Information Image Text Thumbnail Appearance Input/Output (Auto-Rotate) Selections Checkboxes User Interaction (Default) (Ctrl Key) Animations and Transitions Other Events !!} {$ifdef IEHASPLATFORMATTRIBUTE} [ComponentPlatformsAttribute(pidWin32 or pidWin64)] {$endif} TImageEnMView = class(TIEView) private ///////////////////////// // P R I V A T E fMDown: boolean; fBackBuffer: TIEBitmap; fHSVX1, fHSVY1: integer; // view in mouse down fHoverCheckLastIdx : Integer; // for drawing of hover checkboxes fHoverCheckLastPos : TPoint; // Only show checkbox on reasonable mouse movement fScrollBars: TIEScrollStyle; fRXScroll, fRYScroll: Double; fViewX, fViewY: integer; fCacheList: TIEVirtualImageList; fIconList : TIECachedIconList; fStoreType: TIEStoreType; // how to store images fThumbWidth, fThumbHeight: integer; // thumbnail size fZoom: double; // Internally adjusts ThumbWidth and ThumbHeight fHorizBorder: integer; // horizontal border fVertBorder: integer; // vertical border fVWidth, fVHeight: integer; // virtual space size (Updated by UpdateCoords) fOnViewChange: TViewChangeEvent; fOnImageAtPos: TIEImageAtPosEvent; fOnCreateImage: TIECreateImageEvent; fOnDestroyImage: TIEDestroyImageEvent; fOnDrawProgress: TIEMProgressEvent; fOnWrongImage: TIEWrongImageEvent; fHDrawDib: HDRAWDIB; // to draw on display fOnImageIDRequest: TIEImageIDRequestEvent; fOnImageIDRequestEx: TIEImageIDRequestExEvent; fOnImageDraw: TIEImageDrawEvent; fOnImageDraw2: TIEImageDraw2Event; fOnImageOut: TIEImageOutEvent; fOnIOProgress: TIEProgressEvent; fBottomGap: integer; fUpperGap: integer; fTopTextHeight: Integer; fInfoTextHeight: Integer; fBottomTextHeight: Integer; fSideGap : Integer; fModernStyling : Boolean; // Set to true if SetModernStyling fTextMargin : Integer; fTextBlockWidth : Integer; fDisplayMode: TIEMDisplayMode; // display mode fGridWidth: integer; // number of horizontal images (1=all vertical, other is a grid) fCurrentGridWidth : Integer; // Number of horizontal lines as displayed fHSX1, fHSY1: integer; // mouse down coordinates fHSIDX, fLHSIDX: integer; fHSIDXSelected : Boolean; // whether the cell we clicked on was already selected fSelectIdxOnMouseUp : integer; // Delay selection till mouse up so that it does not affect our dragging FLastRegionIdx: integer; fPriorHSIDX: Integer; fLastMouseMoveX, fLastMouseMoveY: integer; fImageEnIO: TImageEnIO; // to load images fLockPaint: integer; // 0 = Paint unlocked fLockUpdate: integer; // 0 = Update unlocked fDrawImageBackground: boolean; // true=draw image background false=draw component background fScrollBarsAlwaysVisible: boolean; // true if the scrollbars are always visible fVScrollBarParams: TIEScrollBarParams; fHScrollBarParams: TIEScrollBarParams; fMouseWheelParams: TIEMouseWheelParams; fMouseWheelParamsAlt: TIEMouseWheelParams; fThumbnailResampleFilter: TResampleFilter; fThumbnailDisplayFilter: TResampleFilter; fThumbnailClipping : Integer; fDestroying: boolean; // component is destroying fStyle: TIEMStyle; fDoubleClicking: boolean; fThumbnailsBackground: TColor; fThumbnailsBackgroundSelected: TColor; fThumbnailsBorderWidth: integer; fThumbnailsBorderColor: TColor; fThumbnailsBorderCurved: boolean; fThumbnailsInternalBorder: boolean; fThumbnailsInternalBorderColor: TColor; fUpdating: boolean; fIconSize : TIEImageEnMViewIconSize; fThumbsRounded: Integer; fEnableAdjustOrientation: Boolean; fEnableLoadEXIFThumbnails: Boolean; // if we need thumbnails, allow to use EXIF thumbnails fEnableLoadExplorerThumbnails: Boolean; // Retrieve thumbnails from Explorer // when true (default) the image will be resized to the thumbnail sizes fEnableAlphaChannel: boolean; fBackgroundStyle: TIEBackgroundStyle; fThumbnailsBackgroundStyle: TIEBackgroundStyle; fFillThumbnail: boolean; fCurrentCompare: TIEImageEnMViewSortCompare; fCurrentCompareEx: TIEImageEnMViewSortCompareEx; fCurrentOrderBy: TIEImageEnMViewSortBy; fCurrentAscending: boolean; fCurrentCaseSensitive : Boolean; // Multithread fThreadPoolSize: integer; // maximum threads count (0=disable multithread) fThreadPoolIO: TList; // list of TImageEnIO objects (maximum size is fThreadPoolSize) fThreadRequests: TList; // list of integers, the indexes of the image to load (no maximum size) fThreadStarter: TIEStarter; // starter main thread fLookAheadList: TList; // list of lookaheaded images (index of) // Wall paper fWallpaper: TPicture; fWallpaperStyle: TIEWallpaperStyle; // Selections fSelectedItem: integer; // selected image index (-1 none) fVisibleSelection: boolean; fSelectionBorderWidth: integer; // selection width with focus fSelectionBorderWidthNoFocus: integer; // selection width without focus fThumbnailsSelectedBorderColor: TColor; // selection color fOnImageSelect: TIEImageSelectEvent; fOnImageDeselect: TIEImageSelectEvent; fOnSelectionChanging : TIESelectionChangingEvent; fOnImageAdd : TIEImageAddEvent; fOnImageAdded : TIEMViewImageNotifyEvent; fOnImageLoaded : TIEMViewImageNotifyEvent; fOnGetText: TIEGetTextEvent; fOnGetTextEx: TIEGetTextExEvent; fMouseInteract: TIEMMouseInteract; fThumbnailOptionsEx : TIEMThumbnailOptionsEx; fIOOptionsEx : TIEMIOOptionsEx; fKeyInteract: TIEMKeyInteract; fSelectedBitmap: TIEBitmap; fMultiSelecting: boolean; fEnableMultiSelect: boolean; fHaveMultiselected: boolean; // last mouseMove has selected images fSelectInclusive: boolean; // when true reselecting an image doesn't unselect it fMultiSelectionOptions: TIEMultiSelectionOptions; fSelectImages: boolean; // if true we are inside BeginSelectImages and EndSelectImages fChangedSel: boolean; // true if the selected is changed fSelectedFontColor : TColor; // text color for selected cells // Play fPlaying: boolean; // true=play actived fPlayTimer: integer; // timer for playback of frames (0=not allocated) fPlayLoop: boolean; // when True executes in loop fTimerInProgress: boolean; fFrame: integer; // current frame on single image mode fSaveDM: TIEMDisplayMode; // displaymode before the animation fSaveSel: integer; // SelectedImage before the play // Following three fields are used by TImageEnMIO to get it updated on added or removed images. fLastImOp: integer; // last operation of insert(1)/delete(2)/move(3)/swap(4) (0=no op) fLastImIdx: integer; // index of processed image by fLastImOp fLastImP1: Integer; // param 1 fLastImGroup: TIEArrayOfInteger; // used by IEM_OP_MOVEGROUP // transition effects fTransition: TIETransitionEffects; // effect engine fTransitionEffect: TIETransitionType; // transition type fTransitionDuration: integer; // transition duration ms // fOnProgress: TIEProgressEvent; fOnBeforeImageDraw: TIEImageDrawEvent; fOnBeforeImageDrawEx: TIEImageDrawEventEx; fEnableImageCaching: boolean; fSoftShadow: TIEVSoftShadow; fChessboardSize: integer; fChessboardBrushStyle: TBrushStyle; fChessboardColor2Customized: Boolean; fGradientEndColor: TColor; fShowText: boolean; fFlatScrollBars: Boolean; fThumbnailFrame: TIEBitmap; fThumbnailFrameSelected: TIEBitmap; fThumbnailFrameRect: TRect; fMultiOnDemands: TList; // list of TImageEnIO for on demand multi page fMaintainInvisibleImages: Integer; // how much invisible images maintain when they are loaded on demand (-1 = maintain all) fLookAhead: Integer; fOnAllDisplayed: TNotifyEvent; // when all images are displayed fAllDisplayed: Boolean; fUserAction: Boolean; // if true user has made an action with mouse or keyboard, events fire fOnFinishWork: TNotifyEvent; fOnAcquireBitmap: TIEAcquireBitmapEvent; fOnPlayFrame: TIEPlayFrameEvent; fThreadCS: TCriticalSection; fBottomTextFont: TFont; fTopTextFont: TFont; fInfoTextFont: TFont; fTextBackgroundStyle: TBrushStyle; fTextBackgroundColor: TColor; fTextTruncSide: TIEMTruncSide; fTrackMouseSelection: Boolean; fDrawMouseSelection: Boolean; fCheckThumbBoundsOnSelect: Boolean; fSelectedImageAlwaysVisible : Boolean; fOnAfterEvent: TIEAfterEventEvent; fFileTypeList: TStringList; // Used only when sorting by iesbFileType so we do not need to store file types for all files fMissingFileIcon : TIEBitmap; // Shown for files that cannot be found fDefaultFileIcon : TIEBitmap; // Shown while loading if icon display is disabled fAnnotationsVisible: Boolean; // Show Wang and ImageEn annotations fImageCacheReusage: TIEImageCacheReusage; // Whether thumbnails in the cache list can be reused after an update. Only supported by TIEDBMultiBitmap fTextColumnWidths : array[ iemtpTop .. iemtpInfo ] of Integer; // Width of each column if style is iemsColumns // For resizing of text columns by dragging fTextColsCurrentRight : array[ iemtpTop .. iemtpInfo ] of Integer; // The right-hand side of each text column of each column if style is iemsColumns for resizing fResizingTextColIdx : Integer; fResizingTextColClickX : Integer; fResizingTextColWidth : Integer; // animations fAnimation: TIEAnimation; fAnimationTimer: TTimer; fAnimationDraggingSlider: Boolean; fOnAnimationText: TIEAnimationTextEvent; // Automatic scrolling when dragging fDragScrollTimer : TTimer; fDragScrollCount : Integer; // Checkbox support fCheckboxes : TIEMCheckboxType; // Show checkboxes? fCheckboxPos : TIEMCheckboxPos; // Corner that checkbox is shown fOnCheckboxClick : TIECheckboxClickEvent; fCheckedCount : Integer; // Cache checked count fCheckedBitmap : TBitmap; // images to draw checkboxes fUncheckedBitmap : TBitmap; fCheckboxMargins : TPoint; // Position of checkbox from edges fDefaultTopText : TIEImageEnMViewDefaultText; fDefaultInfoText : TIEImageEnMViewDefaultText; fDefaultBottomText : TIEImageEnMViewDefaultText; // Gestures fGestures: TIEMViewerGestures; fOnImageEnGesture: TIEImageEnGestureEvent; fGestureStartX: integer; fGestureStartY: integer; fGestureBaseViewX: integer; fGestureBaseViewY: integer; fGestureBaseZoom: double; fGestureStartValue: integer; // Automatic scrolling when dragging procedure InitializeDragScrollTimer; procedure TerminateDragScrollTimer; procedure DragScrollTimer(Sender: TObject); function ThumbnailsOrigin : TPoint; function CurrentTextBlockWidth() : integer; function CurrentHeaderRowHeight : Integer; function GetHintStr(idx : Integer) : string; procedure GetMaxViewXY(var mx, my: integer); procedure SetViewX(v: integer); procedure SetViewY(v: integer); function GetImageX(idx: integer): integer; function GetImageY(idx: integer): integer; function GetImageCol(idx: integer): integer; function GetImageRow(idx: integer): integer; procedure SetThumbWidth(v: integer); procedure SetThumbHeight(v: integer); procedure SetZoom(value: double); function GetImageCount: integer; procedure SetImageTopText(idx: integer; v: WideString); procedure SetImageBottomText(idx: integer; v: WideString); procedure SetImageInfoText(idx: integer; v: WideString); procedure SetImageFileName(idx: integer; v: WideString); function GetImageFileName(idx: integer): WideString; procedure SetImageID(idx, v: integer); function GetImageID(idx: integer): integer; procedure SetImageTag(idx, v: integer); function GetImageTag(idx: integer): integer; procedure SetImageUserPointer(idx: Integer; v: pointer); function GetImageUserPointer(idx: Integer): pointer; function GetImageFileType(idx: integer): WideString; procedure SetHorizBorder(v: integer); procedure SetVertBorder(v: integer); procedure SetSelectedImageAlwaysVisible(v: boolean); procedure SetMouseWheelParams(v: TIEMouseWheelParams); procedure SetMouseWheelParamsAlt(v: TIEMouseWheelParams); function DeleteImageNU(idx: integer; bBatchProcessing : Boolean = False): boolean; procedure DeleteAllImages(); procedure SetCheckboxes(v: TIEMCheckboxType); procedure SetCheckboxPos(v: TIEMCheckboxPos); function GetChecked(index: integer): Boolean; procedure SetChecked(index: integer; v : Boolean); procedure SetVisibleSelection(v: boolean); procedure SetSelectionBorderWidth(v: integer); procedure SetSelectionBorderWidthNoFocus(v: integer); procedure SetThumbnailsSelectedBorderColor(v: TColor); procedure SetSelectedItem(v: integer); procedure SetBottomGap(v: integer); procedure SetUpperGap(v: integer); procedure SetSideGap(v: integer); procedure SetTextMargin(v: integer); procedure SetTextBlockWidth(v: integer); procedure SetImageBackground(idx: integer; v: TColor); function GetImageBackground(idx: integer): TColor; procedure SetImageDelayTime(idx: integer; v: Double); function GetImageDelayTime(idx: integer): Double; function ObtainImageThreaded(idx: integer; priority: Integer): boolean; procedure SetDisplayMode(v: TIEMDisplayMode); procedure SetGridWidth(v: integer); procedure SetPlaying(v: boolean); procedure PlayFrame; procedure SetSelectedItemNU(v: integer); procedure DeselectNU; procedure SetVisibleFrame(v: integer); function GetMouseInteract: TIEMMouseInteract; function GetKeyInteract: TIEMKeyInteract; procedure SetDrawImageBackground(v: boolean); function GetScrollBarsAlwaysVisible: boolean; procedure SetScrollBarsAlwaysVisible(v: boolean); procedure SetImageCacheSize(v: integer); function GetImageCacheSize : integer; procedure SetImageCacheUseDisk(v: boolean); function GetImageCacheUseDisk : boolean; function GetTransitionRunning: boolean; function GetImageTopText(idx: integer): WideString; function GetImageBottomText(idx: integer): WideString; function GetImageInfoText(idx: integer): WideString; procedure SetStyle(value: TIEMStyle); procedure SetEnableMultiSelect(Value: boolean); function GetMultiSelectedImages(index: integer): integer; function GetMultiSelectedImagesCount: integer; function GetMultiSelectedImagesList(): TIEArrayOfInteger; function GetTextColumnWidths(Col: TIEMTextPos): integer; procedure SetTextColumnWidths(Col: TIEMTextPos; value: integer); function CurrentTextColumnWidths(Col: TIEMTextPos): integer; procedure SetThumbnailsBorderWidth(Value: integer); procedure SetThumbnailsBorderColor(Value: TColor); procedure SetThumbnailsBorderCurved(Value: boolean); procedure SetThumbnailsInternalBorder(Value: boolean); procedure SetThumbnailsInternalBorderColor(Value: TColor); {$ifdef IEIncludeDeprecatedInV5} // Deprecated in 6.0.0 (2015-03-06) procedure SetEnableResamplingOnMinor(Value: boolean); {$endif} function GetEnableResamplingOnMinor : boolean; procedure SetIconSize(Value: TIEImageEnMViewIconSize); procedure DrawImage(DestBitmap: TBitmap; info: TIEImageInfo; IsSelected: boolean; Index: integer); procedure DrawColumnsHeaderRow(DestBitmap: TBitmap); procedure ThreadFinish(Sender: TObject); function GetImageBitCount(idx: integer): integer; function GetMaximumViewX: integer; function GetMaximumViewY: integer; procedure SetEnableImageCaching(v: boolean); function SetImageFromStreamOrFile(idx: integer; Stream: TStream; const FileName: WideString; SourceImageIndex: Integer; FileFormat: TIOFileType): boolean; procedure SetEnableAlphaChannel(v: boolean); procedure SetBackgroundStyle(v: TIEBackgroundStyle); procedure SetThumbnailsBackgroundStyle(v: TIEBackgroundStyle); procedure SetGradientEndColor(Value: TColor); procedure SetFillThumbnail(Value: boolean); procedure SetAnnotationsVisible(Value: boolean); procedure SetShowText(Value: boolean); procedure SetThumbnailClipping(Value: Integer); {$ifdef IEINCLUDEFLATSB} procedure SetFlatScrollBars(Value: Boolean); {$endif} function GetJobsRunning: Integer; function GetJobsWaiting: Integer; function SortCompareFunction(index1, index2: Integer): Integer; function SortCompareBy(index1, index2: Integer): Integer; function GetOnDemandIO(const filename: WideString; var FrameIndex: Integer): TImageEnIO; procedure ClearOnDemandIOList; procedure LoadMultiOnDemand(io: TImageEnIO; frameindex: Integer; var dt: Double); function IsOnDemand(info: TIEImageInfo): Boolean; function IsLookAhead(idx: Integer): Boolean; procedure SetOnFinishWork(v: TNotifyEvent); virtual; function GetOnFinishWork: TNotifyEvent; virtual; procedure SetOnAcquireBitmap(v: TIEAcquireBitmapEvent); virtual; function GetOnAcquireBitmap: TIEAcquireBitmapEvent; virtual; function GetImageEnVersion: String; procedure SetImageEnVersion(Value: String); procedure AbortImageLoading(idx: Integer); procedure Sort2(Compare: TIEImageEnMViewSortCompare; CompareEx: TIEImageEnMViewSortCompareEx); function ImageAtPosWithCheckEvent(x, y: integer; checkBounds: Boolean; bRelativeToWindow: boolean = true): Integer; procedure SetAnimation(value: TIEAnimation); procedure AnimGetImageInfo(Sender: TObject; imageIndex: Integer; isVisible: Boolean; var ImageWidth: Integer; var ImageHeight: Integer; var text: WideString); procedure AnimGetImage(Sender: TObject; imageIndex: Integer; var image: TIEBitmap; var text: WideString); procedure AnimReleaseImage(Sender: TObject; imageIndex: Integer; var image: TIEBitmap); procedure AnimPaintTo(dest: TIEBitmap); procedure AnimTimer(Sender: TObject); function BiDiModeIsRTL : Boolean; procedure CheckSelectedImageIsVisible; procedure DoAfterEvent(e: TIEAfterEvent); procedure ProcessUndoRedo(Sender : TObject; bIsUndo : Boolean; Source : TIEUndoSource; UndoObj : TObject; iIndex : Integer; var bHandled : Boolean); function CheckSelectionChangingAllowed : Boolean; procedure WMGestureNotify(var Msg: TIEWMGestureNotify); message IEWM_GESTURENOTIFY; procedure WMEnabled(var Msg: TMessage); message WM_ENABLE; procedure WMGesture(var Msg: TMessage); message IEWM_GESTURE; procedure DoImageEnGestureEvent(const GInfo: TIEGESTUREINFO; var Handled: boolean); virtual; function PerformZoomSnap(Value: double): double; function IEMBitmap_IsTIEDBMultiBitmap: Boolean; procedure Reset(bClear: Boolean = False); function GetStyleInt() : Integer; procedure SetStyleInt(v : Integer); procedure SetShowThumbnailHint(const Value: Boolean); procedure SetDefaultTopText(Value : TIEImageEnMViewDefaultText); procedure SetDefaultInfoText(Value : TIEImageEnMViewDefaultText); procedure SetDefaultBottomText(Value : TIEImageEnMViewDefaultText); procedure UpdateTopTextHeight(bHasText: Boolean); procedure UpdateInfoTextHeight(bHasText: Boolean); procedure UpdateBottomTextHeight(bHasText: Boolean); procedure TopTextFontChange(Sender: TObject); procedure InfoTextFontChange(Sender: TObject); procedure BottomTextFontChange(Sender: TObject); protected /////////////////////// // P R O T E C T E D // // encapsulated components fImageEnMIO: TImageEnMIO; fImageEnProc: TImageEnProc; // selections fMultiSelectedImages: TList; // array of selected images (pointer=integer=index of the selected image) fIEMBitmap: TIECustomMultiBitmap; // contains our images fIEMBitmapIsExternal: Boolean; // True if user has attached a custom IEMBitmap to this control fShowThumbnailHint : Boolean; fDragging: Boolean; function GetIEMBitmap: TIECustomMultiBitmap; procedure UpdateParams(Sender : TObject; Operation: Integer; Idx : integer; ExtraParam: Integer); function GetImageEnMIO: TImageEnMIO; virtual; function GetImageEnProc: TImageEnProc; virtual; procedure SetScrollBars(v: TIEScrollStyle); virtual; procedure SetStoreType(v : TIEStoreType); procedure IEMAutoScroll(var Message: TMessage); message IEM_AUTOSCROLL; procedure WMSize(var Message: TWMSize); message WM_SIZE; procedure WMEraseBkgnd(var Message: TMessage); message WM_ERASEBKGND; procedure WMVScroll(var Message: TMessage); message WM_VSCROLL; procedure WMHScroll(var Message: TMessage); message WM_HSCROLL; procedure WMTimer(var Message: TWMTimer); message WM_TIMER; procedure CMWantSpecialKey(var Msg: TCMWantSpecialKey); message CM_WANTSPECIALKEY; procedure CNKEYUP(var Message: TMessage); message CN_KEYUP; 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 WMLButtonDblClk(var Message: TWMLButtonDblClk); message WM_LBUTTONDBLCLK; procedure WMKillFocus(var Msg: TWMKillFocus); message WM_KILLFOCUS; procedure WMSetFocus(var Msg: TWMSetFocus); message WM_SETFOCUS; procedure WMMouseWheel(var Message: TMessage); message WM_MOUSEWHEEL; procedure CMHintShow(var Message: TMessage); message CM_HINTSHOW; procedure ViewChange(c: integer); virtual; function PaletteChanged(Foreground: Boolean): Boolean; override; procedure SetBackground(cl: TColor); override; function GetFBitmap: TBitmap; override; function GetIEBitmap: TIEBitmap; override; procedure SetThumbnailOptionsEx(v : TIEMThumbnailOptionsEx); procedure SetIOOptionsEx(v : TIEMIOOptionsEx); procedure SetMouseInteract(v: TIEMMouseInteract); virtual; procedure SetKeyInteract(v: TIEMKeyInteract); virtual; function GetImageWidth(idx: integer): integer; function GetImageHeight(idx: integer): integer; function GetImageOriginalWidth(idx: integer): integer; function GetImageOriginalHeight(idx: integer): integer; function GetImageCreateDate(idx: integer): TDateTime; function GetImageFileSize(idx: integer): Int64; function GetImageEditDate(idx: integer): TDateTime; function GetImageType(idx: integer): TIEFolderImageType; procedure SetImageOriginalWidth(idx: integer; Value: integer); procedure SetImageOriginalHeight(idx: integer; Value: integer); procedure SetImageCreateDate(idx: integer; Value: TDateTime); procedure SetImageFileSize(idx: integer; Value: Int64); procedure SetImageEditDate(idx: integer; Value: TDateTime); procedure KeyDown(var Key: Word; Shift: TShiftState); override; procedure KeyUp(var Key: Word; Shift: TShiftState); override; procedure SelectAtPos(X, Y: integer; Shift: TShiftState); procedure SetWallpaper(Value: TPicture); procedure SetWallpaperStyle(Value: TIEWallpaperStyle); function GetHasAlphaChannel: boolean; override; function GetAlphaChannel: TIEBitmap; override; procedure SetOnProgress(v: TIEProgressEvent); virtual; function GetOnProgress: TIEProgressEvent; virtual; procedure ClearThreadsAndRequests; virtual; procedure ClearCache; procedure DoWrongImage(OutBitmap: TIEBitmap; idx: integer; var ASourceType : TIESourceType); virtual; procedure DoImageSelect(idx: integer); virtual; procedure DoImageDeselect(idx: integer); virtual; {$ifdef IEDOTNETVERSION} procedure WMContextMenu(var Message: TWMContextMenu); message WM_CONTEXTMENU; {$endif} procedure SwapImages(idx1, idx2: Integer); function IsRequested(idx: Integer): Integer; procedure PaintBackgroundTo(DestBitmap: TBitmap); function ImageAtPosEx(x, y: integer; checkBounds: Boolean = true; bRelativeToWindow: boolean = true): Integer; function ReplaceIEMConst(const ws : WideString; idx : Integer) : WideString; overload; function ReplaceIEMConst(const DefaultText : TIEImageEnMViewDefaultText; idx : Integer) : WideString; overload; procedure GetFileDetailsForImage(idx: integer); procedure DrawCheckbox(ACanvas : TCanvas; Index : Integer; ThumbRect : TRect; IsSelected : Boolean; bRelativeToView : Boolean = False); overload; procedure DrawCheckbox(ACanvas : TCanvas; Index : Integer; IsSelected : Boolean; bRelativeToView : Boolean = False); overload; function CheckboxAtPos(X, Y : Integer) : Integer; procedure ClickCheckboxAtPos(X, Y : Integer); function ThumbToCheckboxRect(ThumbRect : TRect; bRelativeToView : Boolean = False) : TRect; procedure _UpdateImage(idx: integer; bInvalidateOnly : Boolean); procedure ClickColumnsHeaderRowCell(Col: TIEMTextPos); virtual; procedure DrawColumnsHeaderRowCell(Canvas: TCanvas; Rect: TRect; Col: TIEMTextPos); virtual; public ///////////////////// // P U B L I C constructor Create(Owner: TComponent); override; destructor Destroy; override; {$IFDEF UNITTESTING} function UnitTesting_ObtainImageThreaded(idx: integer): boolean; {$ENDIF} // display procedure Update; override; procedure UpdateEx(bUpdateCache : Boolean; bRespositionSelection : Boolean = False); procedure PaintTo(DestBitmap: TBitmap); virtual; procedure PaintToCanvas(DestCanvas: TCanvas); virtual; procedure Paint; override; property ClientWidth; property ClientHeight; property ViewX: integer read fViewX write SetViewX; property ViewY: integer read fViewY write SetViewY; property Zoom: double read fZoom write SetZoom; property MaximumViewX: integer read GetMaximumViewX; property MaximumViewY: integer read GetMaximumViewY; procedure SetViewXY(x, y: integer); procedure CenterSelected; procedure CenterFrame; procedure LockPaint; override; procedure LockUpdate; virtual; function UnLockPaint: Integer; override; function UnlockUpdate: Integer; virtual; function UnLockUpdateEx: integer; function NPUnLockPaint: integer; override; function ThumbSizeInfo(Data: TIEThumbSizeType): TPoint; // Whether thumbnails in the cache list can be reused after an update. Only supported by TIEDBMultiBitmap property ImageCacheReusage : TIEImageCacheReusage read fImageCacheReusage write fImageCacheReusage; function FindImageInCache( idx: Integer; const sFilename: string ): Pointer; function ObtainImageNow(idx: integer): boolean; procedure SetLastImOp(LastImOp: integer; // last operation of insert(1)/delete(2)/move(3)/swap(4) (0=no op) LastImIdx: integer; // index of processed image by fLastImOp LastImP1: Integer = 0); overload; // param 1 procedure SetLastImOp(LastImOp: integer; LastImIdx: integer; LastImP1: Integer; LastImGroup: TIEArrayOfInteger); overload; // setting LastImGroup default value (nil) generates incorrect C++ headers {!! TImageEnMView.LockPaintCount Declaration property LockPaintCount: Integer; Description Returns the lock painting state. A value of 0 means no locking. A value greater than zero means locking is in place (i.e. painting is disabled). Calling increments , decrements it. !!} property LockPaintCount: integer read fLockPaint; {!! TImageEnMView.LockUpdateCount Declaration property LockUpdateCount: Integer; Description Returns the lock updating state. A value of 0 means no locking. A value greater than zero means locking is in place (i.e. updating is disabled). Calling increments , decrements it. !!} property LockUpdateCount: integer read fLockUpdate; {!! TImageEnMView.SoftShadow Declaration property SoftShadow: ; Description Paints a soft shadow beneath the thumbnails. Notes: - You will need to enable the alpha channel. - Soft shadows are hidden if thumbnails are very small Demo Demos\Multi\Thumbnails2\Thumbnails2.dpr Example ImageEnMView.EnableAlphaChannel := True; ImageEnMView.SoftShadow.Enabled := True; ImageEnMView.SoftShadow.ShadowColor := TColor2TRGB( clBlue ); !!} property SoftShadow: TIEVSoftShadow read fSoftShadow; procedure SetChessboardStyle(Size: Integer; BrushStyle: TBrushStyle = bsSolid; Color1: TColor = clNone_; Color2: TColor = clNone_); property GradientEndColor: TColor read fGradientEndColor write SetGradientEndColor; property FillThumbnail: boolean read fFillThumbnail write SetFillThumbnail; procedure SetModernStyling(bAutoGridWidth : Boolean = False; iThumbWidth : Integer = 0; iThumbHeight : Integer = 0; bSoftShadow: Boolean = True); property AnnotationsVisible: Boolean read fAnnotationsVisible write SetAnnotationsVisible; {!! TImageEnMView.ThumbsRounded Declaration property ThumbsRounded: Integer; Description If value greater than zero is specified for ThumbsRounded then the image is drawn with rounded corners. Smaller values provide the maximum roundness, while large value produce minimal roundness. Demo Demos\Multi\Thumbnails2\Thumbnails2.dpr Example ImageEnMView1.ThumbsRounded := 5; !!} property ThumbsRounded: Integer read fThumbsRounded write fThumbsRounded; procedure SetPresetThumbnailFrame(PresetIndex: Integer; UnselectedColor: TColor; SelectedColor: TColor); {!! TImageEnMView.ThumbnailFrame Declaration property ThumbnailFrame: ; Description Specifies a bitmap to display under the thumbnail. Examples ImageEnMView1.ThumbnailFrame := ImageEnViewUnselected.IEBitmap; ImageEnMView1.ThumbnailFrameSelected := ImageEnViewSelected.IEBitmap; ImageEnMView1.ThumbnailFrameRect := Rect(10, 10, 50, 50); !!} property ThumbnailFrame: TIEBitmap read fThumbnailFrame write fThumbnailFrame; {!! TImageEnMView.ThumbnailFrameSelected Declaration property ThumbnailFrameSelected: ; Description Specifies a bitmap to display under the thumbnail when it is selected. Examples ImageEnMView1.ThumbnailFrame := ImageEnViewUnselected.IEBitmap; ImageEnMView1.ThumbnailFrameSelected := ImageEnViewSelected.IEBitmap; ImageEnMView1.ThumbnailFrameRect := Rect(10, 10, 50, 50); !!} property ThumbnailFrameSelected: TIEBitmap read fThumbnailFrameSelected write fThumbnailFrameSelected; {!! TImageEnMView.ThumbnailFrameRect Declaration property ThumbnailFrameRect: TRect; Description Using and , this property specifies where the image (the thumbnail) will be drawn. Examples ImageEnMView1.ThumbnailFrame := ImageEnViewUnselected.IEBitmap; ImageEnMView1.ThumbnailFrameSelected := ImageEnViewSelected.IEBitmap; ImageEnMView1.ThumbnailFrameRect := Rect(10, 10, 50, 50); !!} property ThumbnailFrameRect: TRect read fThumbnailFrameRect write fThumbnailFrameRect; // others property MouseCapture; procedure Assign(Source: TPersistent); override; procedure AssignEx(Source: TObject; bCopyParams: Boolean = False); procedure AssignLayers(Source: TImageEnView; HighlightSel: Boolean; DoClear: Boolean = True); procedure SetBounds(ALeft, ATop, AWidth, AHeight: Integer); override; function GetLastOp(): integer; function GetLastOpIdx(): integer; function GetLastOpP1(): integer; function GetLastOpGroup(): TIEArrayOfInteger; property ScrollBarsAlwaysVisible: boolean read GetScrollBarsAlwaysVisible write SetScrollBarsAlwaysVisible; // NB: No default. Always store! function RemoveBlankPages(Tolerance: Double = 0; Complete: boolean = true; LeftToRight: boolean = true): Integer; function RemoveDuplicates(): Integer; function CalcGridWidth(): Integer; function CalcGridHeight(): Integer; {!! TImageEnMView.VScrollBarParams Declaration property VScrollBarParams: ; Description Properties to customize the behavior of the vertical scroll bar. This includes tracking (display refresh on mouse dragging), up/down buttons scroll distance and pagedown/up scroll distance. Example // disable tracking ImageEnMView1.VScrollBarParams.Tracking := False; !!} property VScrollBarParams: TIEScrollBarParams read fVScrollBarParams; {!! TImageEnMView.HScrollBarParams Declaration property HScrollBarParams: ; Description Properties to customize the behavior of the horizontal scroll bar. This includes tracking (display refresh on mouse dragging), up/down buttons scroll distance and pagedown/up scroll distance. Example // disable tracking ImageEnMView1.HScrollBarParams.Tracking := False; !!} property HScrollBarParams: TIEScrollBarParams read fHScrollBarParams; procedure RemoveAlphaChannel(Merge: boolean); override; procedure CallBitmapChangeEvents; override; procedure EnsureImageLoaded(idx : Integer); procedure FillFromDirectory(const Directory: WideString; Limit : integer = -1; AllowUnknownFormats : boolean = false; const ExcludeExtensions : WideString = ''; DetectFileFormat : boolean = false; const FilterMask : WideString = ''; IncludeVideoFiles : Boolean = False; LoadOnDemand : boolean = true; DefaultTopText : TIEImageEnMViewDefaultText = iedtNone; DefaultInfoText : TIEImageEnMViewDefaultText = iedtNone; DefaultBottomText : TIEImageEnMViewDefaultText = iedtFilename; bShowHiddenFiles : Boolean = False; bShowFolders : Boolean = False); {!! TImageEnMView.EnableAdjustOrientation Declaration property EnableAdjustOrientation: Boolean; Description When this property is True all images which have orientation information (typically jpeg with EXIF data) will be automatically rotated for display (actual file is not modified). Orientation information is often found in digital photos from high-end cameras. ImageEn uses the data found in or to determine the orientation. !!} property EnableAdjustOrientation: Boolean read fEnableAdjustOrientation write fEnableAdjustOrientation; {!! TImageEnMView.MaintainInvisibleImages Declaration property MaintainInvisibleImages: Integer; Description Specifies the number of images to maintain when they are no longer visible (scrolled out of view). Default: 15 Specify -1 to maintain all images in memory. Specify 0 to discard all images when they are not visible. Note: This property only applies when images are loaded on demand, e.g. by setting , or . !!} property MaintainInvisibleImages: Integer read fMaintainInvisibleImages write fMaintainInvisibleImages; procedure LoadFromFileOnDemand(const FileName: WideString; Append: Boolean = false); {!! TImageEnMView.EnableLoadEXIFThumbnails Declaration property EnableLoadEXIFThumbnails : Boolean; Description Images from digital camera often contain a small thumnbail in their Exif data. When this option is enabled, ImageEn will use the EXIF thumbnail for display rather than loading and sub-sampling the full size image. This speeds up loading of large images. By default, EnableLoadEXIFThumbnails is true. Note: Has no effect if is ietNormal. Example // Do not use EXIF thumbnails for digital camera images ImageEnMView1.EnableLoadEXIFThumbnails := False; See Also - !!} property EnableLoadEXIFThumbnails: Boolean read fEnableLoadEXIFThumbnails write fEnableLoadEXIFThumbnails; {!! TImageEnMView.EnableLoadExplorerThumbnails Declaration property EnableLoadExplorerThumbnails : Boolean; Description Rather than generating thumbnails, they will be obtained from Windows Explorer. This is significantly quicker, and also thumbnails will be cached to disk for fast reuse. By default, EnableLoadExplorerThumbnails is False. Notes: - Has no effect if is ietNormal - Image meta-data will not be valid if EnableLoadExplorerThumbnails is used unless ieixWantParams is enabled Example // Use Windows Explorer thumbnails ImageEnMView1.EnableLoadExplorerThumbnails := True; See Also - !!} property EnableLoadExplorerThumbnails: Boolean read fEnableLoadExplorerThumbnails write fEnableLoadExplorerThumbnails; procedure CreateMorphingSequence(Source: TImageEnVect; Target: TImageEnVect; FramesCount: Integer); // multithreads property JobsRunning: Integer read GetJobsRunning; property JobsWaiting: Integer read GetJobsWaiting; {!! TImageEnMView.LookAhead Declaration property LookAhead: Integer; Description Specifies the number of images to pre-load (load before they are required for display). Note: This property only applies when images are loaded on demand, e.g. by setting , or . Default: 0 !!} property LookAhead: Integer read fLookAhead write fLookAhead; // cache procedure ClearImageCache(idx: integer); property EnableImageCaching: boolean read fEnableImageCaching write SetEnableImageCaching default true; // images property ImageWidth[idx: integer]: integer read GetImageWidth; property ImageHeight[idx: integer]: integer read GetImageHeight; property ImageOriginalWidth[idx: integer]: integer read GetImageOriginalWidth write SetImageOriginalWidth; property ImageOriginalHeight[idx: integer]: integer read GetImageOriginalHeight write SetImageOriginalHeight; property ImageBitCount[idx: integer]: integer read GetImageBitCount; property ImageX[idx: integer]: integer read GetImageX; property ImageY[idx: integer]: integer read GetImageY; property ImageRow[idx: integer]: integer read GetImageRow; property ImageCol[idx: integer]: integer read GetImageCol; property ImageFileName[idx: integer]: WideString read GetImageFileName write SetImageFileName; property ImageID[idx: integer]: integer read GetImageID write SetImageID; property ImageTag[idx: integer]: integer read GetImageTag write SetImageTag; property ImageUserPointer[idx: Integer]: pointer read GetImageUserPointer write SetImageUserPointer; property ImageBackground[idx: integer]: TColor read GetImageBackground write SetImageBackground; property ImageDelayTime[idx: integer]: Double read GetImageDelayTime write SetimageDelayTime; property ImageCreateDate[idx: Integer]: TDateTime read GetImageCreateDate write SetImageCreateDate; property ImageEditDate[idx: integer]: TDateTime read GetImageEditDate write SetImageEditDate; property ImageFileSize[idx: integer]: Int64 read GetImageFileSize write SetImageFileSize; property ImageTopText[idx: integer]: WideString read GetImageTopText write SetImageTopText; property ImageBottomText[idx: integer]: WideString read GetImageBottomText write SetImageBottomText; property ImageInfoText[idx: integer]: WideString read GetImageInfoText write SetImageInfoText; property ImageFileType[idx: integer]: WideString read GetImageFileType; {$ifdef IEIncludeDeprecatedInV5} // Deprecated in 6.0.0 (2015-02-27) // Keep for legacy projects property DefaultBottomTextFont: TFont read fBottomTextFont; property DefaultTopTextFont: TFont read fTopTextFont; property DefaultInfoTextFont: TFont read fInfoTextFont; property DefaultTextBackgroundStyle: TBrushStyle read fTextBackgroundStyle write fTextBackgroundStyle; {$endif} {$ifdef IEIncludeDeprecatedInV5} // Deprecated in 6.0.0 (2015-03-06) property EnableResamplingOnMinor: boolean read GetEnableResamplingOnMinor write SetEnableResamplingOnMinor; {$endif} {!! TImageEnMView.BottomTextFont Declaration property BottomTextFont: TFont; Description Specify the font if you are using to add text to your thumbnails. Notes: - If you need to change the font or styling of particular thumbnails, use the event. - The color of this font may be overridden if is enabled. Example ImageEnMView1.BottomTextFont.Height := 14; ImageEnMView1.BottomTextFont.Name := 'Arial'; ImageEnMView1.FillFromDirectory('C:\Pictures'); See Also - - - !!} property BottomTextFont: TFont read fBottomTextFont; {!! TImageEnMView.TopTextFont Declaration property TopTextFont: TFont; Description Specify the font if you are using to add text to your thumbnails. Notes: - If you need to change the font or styling of particular thumbnails, use the event. - The color of this font may be overridden if is enabled. See Also - - - !!} property TopTextFont: TFont read fTopTextFont; {!! TImageEnMView.InfoTextFont Declaration property InfoTextFont: TFont; Description Specify the font if you are using to add text to your thumbnails. Notes: - If you need to change the font or styling of particular thumbnails, use the event. - The color of this font may be overridden if is enabled. - If is iemsColumns then InfoTextFont is also used for the header row font (though it can be overriden in the event) See Also - - - !!} property InfoTextFont: TFont read fInfoTextFont; {!! TImageEnMView.TextBackgroundStyle Declaration property TextBackgroundStyle: TBrushStyle; Description Specify a background style for your thumbnail text. Note: You can customize the styling of specific frames using the event. Example // Give Thumbnail text a solid yellow background ImageEnMView1.TextBackgroundStyle := bsSolid; ImageEnMView1.TextBackgroundColor := clYellow; ImageEnMView1.FillFromDirectory('C:\Pictures'); See Also - - - - !!} property TextBackgroundStyle: TBrushStyle read fTextBackgroundStyle write fTextBackgroundStyle; property TextColumnWidths[Col : TIEMTextPos] : Integer read GetTextColumnWidths write SetTextColumnWidths; {!! TImageEnMView.TextBackgroundColor Declaration property TextBackgroundColor: TColor; Description Specify a background Color for your thumbnail text. Note: - You can customize the styling of specific frames using the event. - This value may be overridden if is enabled. Example // Give Thumbnail text a solid yellow background ImageEnMView1.TextBackgroundStyle := bsSolid; ImageEnMView1.TextBackgroundColor := clYellow; ImageEnMView1.FillFromDirectory('C:\Pictures'); See Also - - - - !!} property TextBackgroundColor: TColor read fTextBackgroundColor write fTextBackgroundColor; {!! TImageEnMView.TextTruncSide Declaration property TextTruncSide: ; Description Specifies the side to truncate the text if it is too wide to be displayed. !!} property TextTruncSide: TIEMTruncSide read fTextTruncSide write fTextTruncSide; property ShowText: boolean read fShowText write SetShowText; procedure UpdateImage(idx: integer); procedure InsertImage(Idx : integer); overload; procedure InsertImage(Idx : integer; Stream : TStream); overload; procedure InsertImage(Idx : integer; Bitmap : TIEBitmap); overload; procedure InsertImage(Idx : integer; Bitmap : TBitmap); overload; procedure InsertImage(Idx : integer; Width, Height : integer; PixelFormat : TIEPixelFormat = ie24RGB); overload; procedure InsertImage(Idx : integer; const FileName : string); overload; procedure InsertImage(Idx : integer; const FileName : string; LoadOnDemand : boolean; DefaultTopText : TIEImageEnMViewDefaultText = iedtNone; DefaultInfoText : TIEImageEnMViewDefaultText = iedtNone; DefaultBottomText : TIEImageEnMViewDefaultText = iedtFilename; bSelectIt : Boolean = true); overload; procedure InsertImageEx(idx: integer; SelectMode : TIEMSelectMode = imsNever); procedure InsertTransitionFrames(Idx : integer; iFrameCount : Integer; Effect : TIETransitionType; iWidth : Integer = -1; iHeight : Integer = -1; BackgroundColor : TColor = -1; ResamplingFilter: TResampleFilter = rfFastLinear); procedure InsertTransitionFramesEx(Idx : integer; iFrameCount : Integer; Effect : TIETransitionType; StartRect, EndRect : TRect; RectMaintainAspectRatio : boolean = True; iWidth : Integer = -1; iHeight : Integer = -1; bStretchSmall : Boolean = False; BackgroundColor : TColor = -1; ResamplingFilter: TResampleFilter = rfFastLinear; Smoothing: Integer = 96; Timing : TIETransitionTiming = iettLinear); procedure MoveImage(idx: integer; destination: integer); procedure MoveSelectedImagesTo(beforeImage: Integer; bUseDisplayOrder: Boolean = true); procedure Sort(Compare: TIEImageEnMViewSortCompare); overload; procedure Sort(Compare: TIEImageEnMViewSortCompareEx); overload; procedure Sort(OrderBy: TIEImageEnMViewSortBy; Ascending: boolean = true; CaseSensitive: boolean = true); overload; function AppendImage(): integer; overload; function AppendImage(Stream: TStream): integer; overload; function AppendImage(Bitmap: TIEBitmap): integer; overload; function AppendImage(Bitmap : TBitmap): integer; overload; function AppendImage(Width, Height: Integer; PixelFormat: TIEPixelFormat = ie24RGB): Integer; overload; function AppendImage(const FileName: String): integer; overload; function AppendImage(const FileName: String; LoadOnDemand : boolean; DefaultTopText : TIEImageEnMViewDefaultText = iedtNone; DefaultInfoText : TIEImageEnMViewDefaultText = iedtNone; DefaultBottomText : TIEImageEnMViewDefaultText = iedtFilename; bSelectIt : Boolean = true): integer; overload; {$ifdef IEIncludeDeprecatedInV5} // Deprecated in 6.0.0 (2014-11-11) function AppendImage2(Width, Height: Integer; PixelFormat: TIEPixelFormat=ie24RGB): Integer; {$ifdef IEWarningForDeprecated} deprecated {$ifdef IESupportDeprecatedDescription} 'Use AppendImage instead - http://imageen.com/help/Compatibility.html' {$endif}; {$endif} {$endif} function AppendSplit(SourceGrid: TIEBitmap; cellWidth: Integer; cellHeight: Integer; maxCount: Integer = 0): Integer; procedure DeleteImage(idx: integer); procedure DeleteSelectedImages; property ImageCount: integer read GetImageCount; procedure UpdateCoords; procedure SetImage(idx: integer; srcImage: TBitmap); overload; procedure SetImage(idx: integer; srcImage: TIEBaseBitmap); overload; procedure SetImage(idx: Integer; width, height: Integer; PixelFormat: TIEPixelFormat); overload; procedure SetImageEx(idx: integer; srcImage: TBitmap); procedure SetIEBitmapEx(idx: integer; srcImage: TIEBaseBitmap); {$ifdef IEIncludeDeprecatedInV6} // Deprecated in 6.2.0 (2015-08-24) procedure SetIEBitmap(idx: integer; srcImage: TIEBaseBitmap); {$ifdef IEWarningForDeprecated} deprecated {$ifdef IESupportDeprecatedDescription} 'Use SetImage instead - http://imageen.com/help/Compatibility.html' {$endif}; {$endif} {$endif} function SetImageFromFile(idx: integer; const FileName: WideString; SourceImageIndex: Integer = 0; FileFormat: TIOFileType = ioUnknown): boolean; function SetImageFromStream(idx: integer; Stream: TStream; SourceImageIndex: Integer = 0; FileFormat: TIOFileType = ioUnknown): boolean; procedure GetImageToFile(idx: Integer; const FileName: WideString); procedure GetImageToStream(idx: Integer; Stream: TStream; ImageFormat: TIOFileType); procedure SetImageRect(idx: integer; srcImage: TBitmap; x1, y1, x2, y2: integer); overload; procedure SetImageRect(idx: integer; srcImage: TIEBitmap; x1, y1, x2, y2: integer); overload; procedure Clear; function GetBitmap(idx: integer): TBitmap; procedure ReleaseBitmap(idx: integer; saveChanges: Boolean = true); function GetTIEBitmap(idx: integer): TIEBitmap; function GetImageVisibility(idx: integer): integer; function ImageAtPos(x, y: integer; checkBounds: Boolean = true): integer; function ImageAtGridPos(row, col: integer): integer; function InsertingPoint(x, y: integer): integer; procedure SetThumbnailSize(width, height: Integer; SetImageSize: Boolean = False); property ThumbnailClipping : Integer read fThumbnailClipping write SetThumbnailClipping default 0; property IconSize : TIEImageEnMViewIconSize read fIconSize write SetIconSize; procedure CopyToIEBitmap(idx: integer; bmp: TIEBitmap); function IsVisible(idx: integer): boolean; procedure ReloadImage(idx: Integer); // allocations procedure PrepareSpaceFor(Width, Height: integer; Bitcount: integer; ImageCount: integer); property ImageCacheUseDisk: Boolean read GetImageCacheUseDisk write SetImageCacheUseDisk; // selection property SelectedImage: integer read fSelectedItem write SetSelectedItem; property SelectedImageAlwaysVisible: Boolean read fSelectedImageAlwaysVisible write SetSelectedImageAlwaysVisible; procedure Deselect; procedure SelectSeek(pos: TIESeek); procedure CopySelection(SourceMView: TImageEnMView); {!! TImageEnMView.CheckThumbBoundsOnSelect Declaration property CheckThumbBoundsOnSelect: Boolean; Description When enabled, ImageEn checks the thumbnail bounding rectangle before selecting it. The default is False, which allows more flexible selections. Note: When using multi-selection, CheckThumbBoundsOnSelect must be set to false (the default) !!} property CheckThumbBoundsOnSelect: Boolean read fCheckThumbBoundsOnSelect write fCheckThumbBoundsOnSelect; {!! TImageEnMView.TrackMouseSelection Declaration property TrackMouseSelection: Boolean; Description If True a semi-transparent rectangle is shown during mouse selection. Default: False Demo Demos\Multi\Multiview\Multiview.dpr !!} property TrackMouseSelection: Boolean read fTrackMouseSelection write fTrackMouseSelection; {!! TImageEnMView.MultiSelecting Declaration property MultiSelecting: Boolean; Description Set MultiSelecting to True to simulate a CTRL key press. It allows the user to select multiple images with mouse or arrow keys without pressing the CTRL key. Also, MultiSelecting can be used to select more than one image using the property. Note: To allow multi-selection, the property must be True. Example // select images 0 and 1 (assumes that you have set ImageEnMView1.EnableMultiSelect := True at design time) ImageEnMView1.Deselect; ImageEnMView1.MultiSelecting := True; ImageEnMView1.SelectedImage := 0; ImageEnMView1.SelectedImage := 1; ImageEnMView1.MultiSelecting := False; !!} property MultiSelecting: boolean read fMultiSelecting write fMultiSelecting; property MultiSelectedImages[index: integer]: integer read GetMultiSelectedImages; property MultiSelectedImagesCount: integer read GetMultiSelectedImagesCount; property MultiSelectedImagesList: TIEArrayOfInteger read GetMultiSelectedImagesList; procedure MultiSelectSortList; procedure UnselectImage(idx: integer); procedure ToggleSelectImage(idx: integer); procedure SelectImage(idx: integer); procedure SelectAll; procedure BeginSelectImages; procedure EndSelectImages; function IsSelected(idx: integer): boolean; procedure DisplayImageAt(idx: Integer; x, y: Integer); // play property Playing: boolean read fPlaying write SetPlaying; {!! TImageEnMView.PlayLoop Declaration property PlayLoop: boolean; Description Set PlayLoop to True to continuously loop playback of animated GIF and AVI files (when is enabled). !!} property PlayLoop: boolean read fPlayLoop write fPlayLoop; property VisibleFrame: integer read fFrame write SetVisibleFrame; // property TransitionRunning: boolean read GetTransitionRunning; // encapsulated components {!! TImageEnMView.MIO Declaration property MIO: ; Description Encapsulates the component inside TImageEnMView (it is created automatically the first time that it is used). Example ImageEnMView1.MIO.LoadFromFile('C:\film.avi'); ImageEnMView1.MIO.Acquire; !!} property MIO: TImageEnMIO read GetImageEnMIO; {!! TImageEnMView.IEMBitmap Declaration property IEMBitmap: ; Description Encapsulates the object which stores all images of the TImageEnMView. Note: You must call if you modify IEMBitmap directly. Though not for built-in TIEMultiBitmap methods such as Read, Flip, Rotate, Resample, etc. Example ImageEnMView1.IEMBitmap.RotateAll( 90 ); !!} property IEMBitmap: TIECustomMultiBitmap read GetIEMBitmap; {!! TImageEnMView.Proc Declaration property Proc: ; Description The Proc property encapsulates the component inside TImageEnMView (it is created automatically the first time that it is used). It allows you to perform image editing on the selected image. Example // Reverse colors of the selected image ImageEnMView1.Proc.Negative; // Reverse colors of all images in the TImageEnMView ImageEnMView1.LockUpdate; for i := 0 to ImageEnMView1.ImageCount - 1 do begin ImageEnMView1.SelectedImage := i; ImageEnMView1.Proc.Negative; end; ImageEnMView1.SelectedImage := 0; ImageEnMView1.UnlockUpdate; !!} property Proc: TImageEnProc read GetImageEnProc; procedure SetExternalMBitmap(value : TIECustomMultiBitmap); {$IFDEF UNITTESTING} function UnitTesting_GetExternalMBitmap: TIECustomMultiBitmap; {$ENDIF} // drag&drop procedure IEBeginDrag(Immediate: Boolean; Threshold: Integer=-1); procedure IEEndDrag; // input&output procedure SaveSnapshot(Stream: TStream; SaveCache: Boolean = True; Compressed: Boolean = False; SaveParams: Boolean = False); overload; virtual; procedure SaveSnapshot(FileName: WideString; SaveCache: Boolean = True; Compressed: Boolean = False; SaveParams: Boolean = False); overload; virtual; procedure SaveSnapshotEx(Stream: TStream; SaveCache: Boolean; Compressed: Boolean; SaveParams: Boolean; GetExtraParams: TIEProcessStreamEvent); function LoadSnapshot(Stream: TStream): Boolean; overload; virtual; function LoadSnapshot(FileName: WideString): Boolean; overload; virtual; function LoadSnapshotEx(Stream: TStream; SetExtraParams: TIEProcessStreamEvent): Boolean; // animations property Animation: TIEAnimation read fAnimation write SetAnimation; function Seek(Destination: TIEIOSeekDestination) : integer; // Checkboxes property CheckboxPos : TIEMCheckboxPos read fCheckboxPos write SetCheckboxPos; function CheckedCount : Integer; property Checked[index: integer]: Boolean read GetChecked write SetChecked; procedure SetCheckboxParams(iHorzMargin, iVertMargin : Integer; CustomCheckedImage : TBitmap = nil; CustomUncheckedImage : TBitmap = nil); procedure CheckAll; procedure UncheckAll; // Gestures {!! TImageEnMView.Gestures Declaration property Gestures: ; Description TImageEnMView supports native Windows gestures: - Dragging the screen to pan an image - Pinching to zoom in - Reverse-pinching to zoom out ImageEn automatically handles the Windows gesture events, so adding gesture support to your applications requires only that you enable the relevant Gesture property. Example // enable Pan (scroll) and Zoom gestures ImageEnMView1.Gestures.Pan.Enabled := True; ImageEnMView1.Gestures.Zoom.Enabled := True; !!} property Gestures: TIEMViewerGestures read fGestures; // not: cannot stay in published section without an property editor procedure SetAllText(TopText : TIEImageEnMViewDefaultText; InfoText : TIEImageEnMViewDefaultText; BottomText : TIEImageEnMViewDefaultText); property TextBlockWidth: integer read fTextBlockWidth write SetTextBlockWidth; function FilenameToIndex(const sFilename : string) : integer; // Thumbnails property SelectionWidthNoFocus: integer read fSelectionBorderWidthNoFocus write SetSelectionBorderWidthNoFocus; property ThumbnailsBorderCurved: boolean read fThumbnailsBorderCurved write SetThumbnailsBorderCurved; {$ifdef IEIncludeDeprecatedInV6} // Deprecated in 7.0.0 (14/3/2017) property SelectionAntialiased: Boolean read fThumbnailsBorderCurved write SetThumbnailsBorderCurved; {$endif} procedure ProbeLastSort(out OrderBy: TIEImageEnMViewSortBy; out Ascending: boolean; out CaseSensitive: Boolean); {!! TImageEnMView.MissingFileIcon Declaration property MissingFileIcon: TIEBitmap; Description Image that is displayed for files that cannot be found (i.e. have an invalid file path). Note: Only valid if ietxEnableInternalIcons is specified in See Also - !!} property MissingFileIcon: TIEBitmap read fMissingFileIcon; {!! TImageEnMView.DefaultFileIcon Declaration property DefaultFileIcon: TIEBitmap; Description Image that is displayed for files while loading. Note: Only valid if ietxEnableInternalIcons is specified in , and ietxShowIconWhileLoading is not included. See Also - !!} property DefaultFileIcon: TIEBitmap read fDefaultFileIcon; published /////////////////////// // P U B L I S H E D property ScrollBars: TIEScrollStyle read fScrollBars write SetScrollBars default ssBoth; property StoreType: TIEStoreType read fStoreType write SetStoreType; // NB: No default. Always store! property ThumbWidth: integer read fThumbWidth write SetThumbWidth; // NB: No default. Always store! property ThumbHeight: integer read fThumbHeight write SetThumbHeight; // NB: No default. Always store! property HorizBorder: integer read fHorizBorder write SetHorizBorder; // NB: No default. Always store! property VertBorder: integer read fVertBorder write SetVertBorder; // NB: No default. Always store! property BottomGap: integer read fBottomGap write SetBottomGap default 0; property UpperGap: integer read fUpperGap write SetUpperGap default 0; property SideGap: integer read fSideGap write SetSideGap default 0; property TextMargin: integer read fTextMargin write SetTextMargin default 0; property ThumbnailOptionsEx : TIEMThumbnailOptionsEx read fThumbnailOptionsEx write SetThumbnailOptionsEx default [ietxShowIconForUnknownFormat, ietxShowIconWhileLoading, ietxEnableInternalIcons, ietxStretchSmallImages]; property IOOptionsEx : TIEMIOOptionsEx read fIOOptionsEx write SetIOOptionsEx default []; {!! TImageEnMView.OnViewChange Declaration property OnViewChange: ; Description Occurs when the or properties change. !!} property OnViewChange: TViewChangeEvent read fOnViewChange write fOnViewChange; {!! TImageEnMView.OnImageAtPos Declaration property OnImageAtPos: ; Description Occurs whenever it is necessary to check if specified coordinates are inside a thumbnail. !!} property OnImageAtPos: TIEImageAtPosEvent read fOnImageAtPos write fOnImageAtPos; {!! TImageEnMView.OnCreateImage Declaration property OnCreateImage: ; Description Occurs whenever (immediately after) a new image is created (i.e whenever a new image is added to the TImageEnMView). !!} property OnCreateImage: TIECreateImageEvent read fOnCreateImage write fOnCreateImage; {!! TImageEnMView.OnDestroyImage Declaration property OnDestroyImage: ; Description Occurs whenever (immediately before) an image is destroyed (i.e whenever an image is removed from the TImageEnMView). !!} property OnDestroyImage: TIEDestroyImageEvent read fOnDestroyImage write fOnDestroyImage; {!! TImageEnMView.OnImageIDRequest Declaration property OnImageIDRequest: ; Description Occurs whenever an image is required, if you have specified a value for its property. ID is the value you have specified in property; Bitmap is the image to display. It is a TBitmap (use if you require a ). The bitmap is copied in TImageEnMView, and then automatically freed. Example procedure TMyForm.ImageEnMViewOnImageIDRequest(Sender: TObject; ID: integer; var Bitmap: TBitmap); begin // Retrieve the image from a TImageList Bitmap := TBitmap.create; ImageList1.GetBitmap(ID, Bitmap); end; !!} property OnImageIDRequest: TIEImageIDRequestEvent read fOnImageIDRequest write fOnImageIDRequest; {!! TImageEnMView.OnImageIDRequestEx Declaration property OnImageIDRequestEx: ; Description Occurs whenever an image is required if you have specified a value for the property. ID is the value you have specified in property; Bitmap is the image to display. It is a (use if you require a TBitmap). The bitmap is copied in TImageEnMView, and then automatically freed. Example procedure TMyForm.ImageEnMViewOnImageIDRequestEx(Sender: TObject; ID: integer; var Bitmap: TIEBitmap); begin // Create the image dynamically Bitmap := TIEBitmap.create; GenerateChartOfID(ID, Bitmap); end; !!} property OnImageIDRequestEx: TIEImageIDRequestExEvent read fOnImageIDRequestEx write fOnImageIDRequestEx; {!! TImageEnMView.OnBeforeImageDraw Declaration property OnBeforeImageDraw: ; Description Occurs immediately before an image is drawn. It can be used to prepare parameters prior to drawing the image (e.g. , and ). Note: OnBeforeImageDraw and are identical, except that includes a ThumbRect parameter. Also if is used the selection is not shown. !!} property OnBeforeImageDraw: TIEImageDrawEvent read fOnBeforeImageDraw write fOnBeforeImageDraw; {!! TImageEnMView.OnBeforeImageDrawEx Declaration property OnBeforeImageDrawEx: ; Description Occurs immediately before the image of index, idx, is painted. Left, Top are the top-left coordinates where the image will be drawn (i.e. destination bitmap coordinates). Dest is the destination bitmap (containing the canvas where the image must be drawn). ThumbRect specifies the destination rectangle for the image. You can change this parameter to control where the image is drawn. Note: When this event is assigned, the selection is not shown. See the Multi\CustomThumbs demo for more info. Note: and OnBeforeImageDrawEx are identical, except that OnBeforeImageDrawEx includes a ThumbRect parameter. Also if OnBeforeImageDrawEx is used the selection is not shown. !!} property OnBeforeImageDrawEx: TIEImageDrawEventEx read fOnBeforeImageDrawEx write fOnBeforeImageDrawEx; {!! TImageEnMView.OnImageDraw Declaration property OnImageDraw: ; Description Occurs whenever an image is painted. Note: OnImageDraw and are identical, except that includes a ThumbRect parameter to return the thumbnail rectangle. Example // Display the image index and sizes on bottom of the thumbnail // Ensure you have set the BottomGap property procedure TForm1.ImageEnMView1ImageDraw(Sender: TObject; idx: Integer; Left, Top: Integer; Canvas: TCanvas); begin with canvas do begin Font.Height := 15; Font.Color := clWhite; TextOut(Left, Top + imageenmview1.ThumbHeight - imageenmview1.bottomgap + 2, IntToStr(idx)); TextOut(Left, Top, IntToStr(imageenmview1.ImageWidth[idx]) + 'x' + IntToStr(imageenmview1.ImageHeight[idx])); end; end; !!} property OnImageDraw: TIEImageDrawEvent read fOnImageDraw write fOnImageDraw; {!! TImageEnMView.OnImageDraw2 Declaration property OnImageDraw2: ; Description Occurs whenever an image is painted. Note: and OnImageDraw2 are identical, except that OnImageDraw2 includes a ThumbRect parameter to return the thumbnail rectangle. Demo Demos\Multi\CustomThumbs2\CustomThumbs2.dpr Example // Display the image index and sizes on bottom of the thumbnail // Ensure you have set the BottomGap property procedure TForm1.ImageEnMView1ImageDraw2(Sender: TObject; idx: Integer; Left, Top: Integer; Canvas: TCanvas); begin with canvas do begin Font.Height := 15; Font.Color := clWhite; TextOut(Left, Top + imageenmview1.ThumbHeight - imageenmview1.bottomgap + 2, IntToStr(idx)); TextOut(Left, Top, IntToStr(imageenmview1.ImageWidth[idx]) + 'x' + IntToStr(imageenmview1.ImageHeight[idx])); end; end; !!} property OnImageDraw2: TIEImageDraw2Event read fOnImageDraw2 write fOnImageDraw2; {!! TImageEnMView.OnImageOut Declaration property OnImageOut: ; Description Occurs during the drawing of thumbnails, just prior to the painting of the image. It can be used to manipulate the image (rotate, color effects, etc) or add annotations. Note: Only the drawing of the image is affected, not the image itself. Example // Rotate all images 90 dec. CCW procedure TForm1.ImageEnMView1ImageOut(Sender: TObject; idx: Integer; OutBitmap: TIEBitmap); begin OutBitmap.Rotate( 90 ); end; !!} property OnImageOut: TIEImageOutEvent read fOnImageOut write fOnImageOut; {!! TImageEnMView.OnImageSelect Declaration property OnImageSelect: ; Description Occurs whenever an image is selected. Example // Show the selected image in a TImageEnView procedure TMainForm.ImageEnMView1ImageSelect(Sender: TObject; idx: Integer); begin ImageEnMView1.CopyToIEBitmap( idx, ImageEnView1.IEBitmap ); ImageEnVeiw1.Update; end; !!} property OnImageSelect: TIEImageSelectEvent read fOnImageSelect write fOnImageSelect; {!! TImageEnMView.OnImageAdd Declaration property OnImageAdd: ; Description Occurs whenever an image is added to a or when using TImageEnMView.FillFromDirectory. See Also - - !!} property OnImageAdd: TIEImageAddEvent read fOnImageAdd write fOnImageAdd; {!! TImageEnMView.OnImageAdded Declaration property OnImageAdded: ; Description Occurs whenever an image has been added to the control. See Also - - !!} property OnImageAdded: TIEMViewImageNotifyEvent read fOnImageAdded write fOnImageAdded; {!! TImageEnMView.OnImageLoaded Declaration property OnImageLoaded: ; Description Occurs whenever an image is completes loading within the control. If an image is loaded on demand, some properties of the image, such as its are not available. This event occurs once the image has completed loading and its content and properties are available. Note: The event occurs once all images are loaded and displayed See Also - - !!} property OnImageLoaded: TIEMViewImageNotifyEvent read fOnImageLoaded write fOnImageLoaded; {!! TImageEnMView.OnGetText Declaration property OnGetText: ; Description Occurs before text is output when drawing a thumbnail allowing you to insert or modify the displayed text. Notes: - If is iemsColumns then OnGetText is also called for the header row. The Index will be -1. - If default text has not been specified for any thumbnails, you may need to set / to allow space for the text Example // Note: In form create we set IEFolderMView.UpperGap := 20; // Display the file index above the frame procedure TForm1.IEFolderMViewGetText(Sender: TObject; Index: Integer; Position: TIEMTextPos; var Text: WideString); begin if Index = -1 then Text := 'File Number' // Header row else if Position = iemtpTop then Text := 'File #' + IntToStr(Index + 1); end; See Also - !!} property OnGetText: TIEGetTextEvent read fOnGetText write fOnGetText; {!! TImageEnMView.OnGetTextEx Declaration property OnGetTextEx: ; Description Occurs before text is output when drawing a thumbnail allowing you to insert or modify the displayed text and change the styling. Notes: - If is iemsColumns then OnGetText is also called for the header row. The Index will be -1. - If default text has not been specified for any thumbnails, or you are increasing the size of the font, you may need to set / to allow space for the text Example // Display the file as bold if it is JPEG procedure TForm1.IEFolderMViewGetTextEx(Sender: TObject; Index: Integer; Position: TIEMTextPos; var Text: WideString; var Font : TFont; var BackgroundStyle: TBrushStyle; var BackgroundColor: TColor; var TruncSide: TIEMTruncSide); begin if ( Position <> iemtpBottom ) or ( Index = -1 ) then exit; sFileExt := ExtractFileExt( Text ); if IEExtToFileFormat( sFileExt ) = ioJPEG then Font.Style := [fsBold] else Font.Style := []; end; // Give text on every thumb a random background color procedure TForm1.IEFolderMViewGetTextEx(Sender: TObject; Index: Integer; Position: TIEMTextPos; var Text: WideString; Font : TFont; var BackgroundStyle: TBrushStyle; var BackgroundColor: TColor; var TruncSide: TIEMTruncSide); begin BackgroundColor := RGB( Random( 256 ), Random( 256 ), Random( 256 )); BackgroundStyle := bsSolid; end; See Also - !!} property OnGetTextEx: TIEGetTextExEvent read fOnGetTextEx write fOnGetTextEx; {!! TImageEnMView.OnImageDeselect Declaration property OnImageDeselect: ; Description Occurs whenever the user removes the selection from an image. Note: must be true. !!} property OnImageDeselect: TIEImageSelectEvent read fOnImageDeselect write fOnImageDeselect; {!! TImageEnMView.OnSelectionChanging Declaration property OnSelectionChanging: ; Description Occurs prior to a change in the selected frame/thumbnail due to user action (i.e. mouse or keyboard). This can be used to prevent changing of a selection (e.g. due to the current selection not being saved). !!} property OnSelectionChanging: TIESelectionChangingEvent read fOnSelectionChanging write fOnSelectionChanging; {!! TImageEnMView.OnIOProgress Declaration property OnIOProgress: ; Description Occurs during input/output operations to advise the progress of the operation. !!} property OnIOProgress: TIEProgressEvent read fOnIOProgress write fOnIOProgress; {!! TImageEnMView.OnDrawProgress Declaration property OnDrawProgress: ; Description Occurs during painting for each image drawn. Example procedure TForm1.ImageEnMView1DrawProgress(Sender: TObject; per, idx: Integer); begin ProgressBar1.Position := per; end; !!} property OnDrawProgress: TIEMProgressEvent read fOnDrawProgress write fOnDrawProgress; {!! TImageEnMView.OnWrongImage Declaration property OnWrongImage: ; Description Occurs whenever TImageEnMView cannot load the image specified by the property, for instance when the file is corrupt or of an unrecognized format. You can specify an alternative bitmap to display by changing the OutBitmap property. Example Procedure MyForm1OnWrongImage(Sender: TObject; OutBitmap: TIEBitmap; idx: Integer; var Handled: Boolean); Var io: TImageEnIO; begin io := TImageEnIO.CreateFromBitmap(OutBitmap); io.LoadFromFile('error_image.bmp'); io.Free; Handled := True; end; !!} property OnWrongImage: TIEWrongImageEvent read fOnWrongImage write fOnWrongImage; {!! TImageEnMView.OnCheckboxClick Declaration property OnCheckboxClick: ; Description Occurs whenever a user clicks a checkbox. idx is the index of the clicked image. bChecked specifies the new status of the image. You can override it, e.g. set it to false if the image cannot be checked Note: Don't read in this event which will not yet be valid. Use OnClick or OnMouseUp. Example procedure TfMain.ImageEnMView1CheckboxClick(Sender: TObject; idx: integer; var bChecked : Boolean); begin // Only allow JPEG images to be checked if bChecked and (IEFileIsOfFormat(ImageEnMView1.ImageFilename[idx], ioJPEG) = False) then begin MessageBeep(MB_ICONEXCLAMATION); bChecked := False; end; end; See also - - !!} property OnCheckboxClick: TIECheckboxClickEvent read fOnCheckboxClick write fOnCheckboxClick; property Checkboxes : TIEMCheckboxType read fCheckboxes write SetCheckboxes default iecbNone; property VisibleSelection: boolean read fVisibleSelection write SetVisibleSelection default true; property MouseInteract: TIEMMouseInteract read GetMouseInteract write SetMouseInteract default [mmiSelect]; property KeyInteract: TIEMKeyInteract read GetKeyInteract write SetKeyInteract default [mkiMoveSelected]; property DisplayMode: TIEMDisplayMode read fDisplayMode write SetDisplayMode default mdGrid; property GridWidth: integer read fGridWidth write SetGridWidth; // NB: No default. Always store! property SelectionWidth: integer read fSelectionBorderWidth write SetSelectionBorderWidth default 2; property SelectionColor: TColor read fThumbnailsSelectedBorderColor write SetThumbnailsSelectedBorderColor; property DrawImageBackground: boolean read fDrawImageBackground write SetDrawImageBackground default false; property ImageCacheSize: integer read GetImageCacheSize write SetImageCacheSize default 10; {!! TImageEnMView.TransitionEffect Declaration property TransitionEffect: ; Description Specifies the effect to apply when the application changes the currently displayed frame. Note: must be mdSingle. To change current frame, use the property. iettShreddedFromLeft iettCubeRotateFromTop2 Example // Design time properties... ImageEnMView1.DisplayMode := mdSingle; ImageEnMView1.TransitionEffect := iettCrossDissolve; ImageEnMView1.TransitionDuration := 1500; // Display next frame using cross dissolve effect ImageEnMView1.VisibleFrame := ImageEnMView1.VisibleFrame + 1; See Also - !!} property TransitionEffect: TIETransitionType read fTransitionEffect write fTransitionEffect default iettNone; {!! TImageEnMView.TransitionDuration Declaration property TransitionDuration: Integer; Description Specifies the duration of the transition in milliseconds. Example // Design time properties... ImageEnMView1.DisplayMode := mdSingle; ImageEnMView1.TransitionEffect := iettCrossDissolve; ImageEnMView1.TransitionDuration := 1500; // Display next frame using cross dissolve effect ImageEnMView1.VisibleFrame := ImageEnMView1.VisibleFrame + 1; See Also - !!} property TransitionDuration: integer read fTransitionDuration write fTransitionDuration default 1000; property Style: TIEMStyle read fStyle write SetStyle; // NB: No default. Always store! procedure SetStyleEx(aStyle: TIEMStyle; TopText : TIEImageEnMViewDefaultText; InfoText : TIEImageEnMViewDefaultText; BottomText : TIEImageEnMViewDefaultText; iThumbZoom: Double = 0; bAdjustSpacing: Boolean = True; bAdjustStyle: Boolean = True; bAdjustFont: Boolean = True); {!! TImageEnMView.ThumbnailsBackground Declaration property ThumbnailsBackground: TColor; Description Specifies the background color of the thumbnails when they are NOT selected. Use to set the color when selected. Notes: - This value may be overridden if is enabled. - Not used if is enabled !!} property ThumbnailsBackground: TColor read fThumbnailsBackground write fThumbnailsBackground; // NB: No default. Always store! {!! TImageEnMView.ThumbnailsBackgroundSelected Declaration property ThumbnailsBackgroundSelected: TColor; Description Specifies the background color of the thumbnails when they are selected. Use to set the color when NOT selected. Notes: - This value may be overridden if is enabled. - Not used if is enabled !!} property ThumbnailsBackgroundSelected: TColor read fThumbnailsBackgroundSelected write fThumbnailsBackgroundSelected; // NB: No default. Always store! property EnableMultiSelect: boolean read fEnableMultiSelect write SetEnableMultiSelect default false; {!! TImageEnMView.MultiSelectionOptions Declaration property MultiSelectionOptions: ; Description Controls the behaviour of selection. Example // If you do not specify iemoRegion the entire row is selected: ImageEnMView1.MultiSelectionOptions := []; // By specifying iemoRegion only the specified columns are selected: ImageEnMView1.MultiSelectionOptions := [iemoRegion]; !!} property MultiSelectionOptions: TIEMultiSelectionOptions read fMultiSelectionOptions write fMultiSelectionOptions; // NB: No default property ThumbnailsBorderWidth: integer read fThumbnailsBorderWidth write SetThumbnailsBorderWidth; // NB: No default property ThumbnailsBorderColor: TColor read fThumbnailsBorderColor write SetThumbnailsBorderColor default clBtnFace; property ThumbnailsInternalBorder: boolean read fThumbnailsInternalBorder write SetThumbnailsInternalBorder default false; property ThumbnailsInternalBorderColor: TColor read fThumbnailsInternalBorderColor write SetThumbnailsInternalBorderColor default clBlack; property Wallpaper: TPicture read fWallpaper write SetWallpaper; property WallpaperStyle: TIEWallpaperStyle read fWallpaperStyle write SetWallpaperStyle default iewoNormal; {!! TImageEnMView.ThreadPoolSize Declaration property ThreadPoolSize: Integer; Description Specifies how many threads can be created to load images (to load images in the background). If ThreadPoolSize is set to 0 all images are loaded in the main thread. !!} property ThreadPoolSize: integer read fThreadPoolSize write fThreadPoolSize default 5; property EnableAlphaChannel: boolean read fEnableAlphaChannel write SetEnableAlphaChannel default true; property BackgroundStyle: TIEBackgroundStyle read fBackgroundStyle write SetBackgroundStyle default iebsSolid; property ThumbnailsBackgroundStyle: TIEBackgroundStyle read fThumbnailsBackgroundStyle write SetThumbnailsBackgroundStyle default iebsSolid; property OnProgress: TIEProgressEvent read GetOnProgress write SetOnProgress; property OnAcquireBitmap: TIEAcquireBitmapEvent read GetOnAcquireBitmap write SetOnAcquireBitmap; {!! TImageEnMView.OnAllDisplayed Declaration property OnAllDisplayed: TNotifyEvent; Description Occurs when all images have been loaded and displayed. See Also - !!} property OnAllDisplayed: TNotifyEvent read fOnAllDisplayed write fOnAllDisplayed; property OnFinishWork: TNotifyEvent read GetOnFinishWork write SetOnFinishWork; {!! TImageEnMView.OnPlayFrame Declaration property OnPlayFrame: ; Description Occurs whenever a frame is displayed. You can set bShowFrame to False to skip playback of specific frames. See also: . Example // We have two TImageEnMViews showing the same set of images: iemFileList shows thumbnails of all images. iemDisplay shows a slideshow. A button displays a slideshow of all checked images in iemFileList procedure TMainForm.iemDisplayPlayFrame(Sender: TObject; FrameIndex: integer; var bShowFrame: Boolean); begin if iemFileList.Checked[FrameIndex] = False then bShowFrame := False; end; !!} property OnPlayFrame: TIEPlayFrameEvent read fOnPlayFrame write fOnPlayFrame; {!! TImageEnMView.OnAnimationText Declaration property OnAnimationText: ; Description Occurs whenever text needs to be displayed during an animation. See Also - !!} property OnAnimationText: TIEAnimationTextEvent read fOnAnimationText write fOnAnimationText; {!! TImageEnMView.OnAfterEvent Declaration property OnAfterEvent: ; Description Occurs immediately after ImageEn has processed an event. See for a list of handled events. !!} property OnAfterEvent: TIEAfterEventEvent read fOnAfterEvent write fOnAfterEvent; {!! TImageEnMView.OnImageEnGesture Declaration property OnImageEnGesture: ; Description Occurs whenever a gesture is handled by ImageEn. !!} property OnImageEnGesture: TIEImageEnGestureEvent read fOnImageEnGesture write fOnImageEnGesture; property DefaultTopText : TIEImageEnMViewDefaultText read fDefaultTopText write SetDefaultTopText Default iedtNone; property DefaultInfoText : TIEImageEnMViewDefaultText read fDefaultInfoText write SetDefaultInfoText Default iedtNone; property DefaultBottomText : TIEImageEnMViewDefaultText read fDefaultBottomText write SetDefaultBottomText; // NO DEFAULT property ImageEnVersion: String read GetImageEnVersion write SetImageEnVersion stored false; {$ifdef IEINCLUDEFLATSB} property FlatScrollBars: Boolean read fFlatScrollBars write SetFlatScrollBars default False; {$endif} property OnMouseWheel; property OnMouseWheelDown; property OnMouseWheelUp; property Align; property Anchors; property ShowThumbnailHint: Boolean read fShowThumbnailHint write SetShowThumbnailHint default False; {!! TImageEnMView.ThumbnailResampleFilter Declaration property ThumbnailResampleFilter: ; Description Specifies the filter to use when thumbnails are generated (when assigning images to a TImageEnMView and = ietThumb). Filters improve the quality of the thumbnail, but can slow down the application. A value of rfNone provides no quality enhancement. Filters such as rfLanczos3 provide excellent quality, but are slower. Default: rfFastLinear (improve quality with negligible speed impact) Note: Unlike , ThumbnailResampleFilter is only used once for each image (when it first assigned/loaded) Example // insert image 1.jpg and 2.jpg. Only 1.jpg will be filtered. ImageEnMView1.ThumbnailResampleFilter := rfBSpline; Idx := ImageEnMView1.AppendImage; ImageEnMView1.SetImageFromFile('1.jpg'); ImageEnMView1.ThumbnailResampleFilter := rfNone; Idx := ImageEnMView1.AppendImage; ImageEnMView1.SetImageFromFile('2.jpg'); !!} property ThumbnailResampleFilter: TResampleFilter read fThumbnailResampleFilter write fThumbnailResampleFilter; {!! TImageEnMView.ThumbnailDisplayFilter Declaration property ThumbnailDisplayFilter: ; Description ThumbnailDisplayFilter specifies a filter to apply when an image (thumbnail) need to be resized for display. Filters improve the quality of the thumbnail, but can slow down the application. A value of rfNone provides no quality enhancement. Filters such as rfLanczos3 provide excellent quality, but are slower. A typical value is rfFastLinear which improves quality with negligible speed impact. Notes: - Unlike , ThumbnailDisplayFilter is used every time the image needs to be displayed - For black/white images rfFastLinear is always used. Default: rfNone Example // Use high quality thumbnails ImageEnMView1.ThumbnailDisplayFilter := rfLanczos3; ImageEnMView1.Repaint; !!} property ThumbnailDisplayFilter: TResampleFilter read fThumbnailDisplayFilter write fThumbnailDisplayFilter; {!! TImageEnMView.SelectedFontColor Declaration property SelectedFontColor: TColor; Description By default (when SelectedFontColor = clNone) the color of the text on both selected and unselected thumbnails is the same (as specified by , and ). If you specify a color for SelectedFontColor it will be used for selected cells. Note: This value may be overridden if is enabled. Default: clNone See Also - !!} property SelectedFontColor: TColor read fSelectedFontColor write fSelectedFontColor; {!! TImageEnMView.MouseWheelParams Declaration property MouseWheelParams: ; Description MouseWheelParams and allow you to customize the behavior of the mouse wheel. MouseWheelParams is used to specify the default mouse wheel behaviour, whereas is used when the Ctrl key is pressed. Examples // For iemwVScroll used with iemwPercentage, TImageEnMView assumes a theoretical grid of 12.5 thumbnails high // So the default of 8% will scroll one thumbnail with each wheel click // Whereas 16% would scroll the height of two thumbnails ImageEnMView1.MouseWheelParams.Action := iemwVScroll; ImageEnMView1.MouseWheelParams.Variation := iemwPercentage; ImageEnMView1.MouseWheelParams.value := 4; // half a thumbnail // Mouse wheel will navigate to the next or previous image ImageEnMView1.MouseWheelParams.Action := iemwNavigate; // Explorer like behavior. Mouse wheel scrolls the control and Ctrl + Mouse wheel changes the thumbnail view ImageEnMView1.MouseWheelParams.Action := iemwVScroll; ImageEnMView1.MouseWheelParamsAlt.Action := iemwZoomView; Demo Demos\Other\MouseWheel\MouseWheelParams.dpr !!} property MouseWheelParams: TIEMouseWheelParams read fMouseWheelParams write SetMouseWheelParams; {!! TImageEnMView.MouseWheelParamsAlt Declaration property MouseWheelParams: ; Description and MouseWheelParamsAlt allow you to customize the behavior of the mouse wheel. is used to specify the default mouse wheel behaviour, whereas TImageEnMView.MouseWheelParamsAlt is used when the Ctrl key is pressed. Examples // Explorer like behavior. Mouse wheel scrolls the control and Ctrl + Mouse wheel changes the thumbnail view ImageEnMView1.MouseWheelParams.Action := iemwVScroll; ImageEnMView1.MouseWheelParamsAlt.Action := iemwZoomView; Demo \Other\MouseWheel\MouseWheelParams.dpr !!} property MouseWheelParamsAlt: TIEMouseWheelParams read fMouseWheelParamsAlt write SetMouseWheelParamsAlt; {!! TImageEnMView.BiDiMode Declaration property BiDiMode: TBiDiMode; Description Determine whether grid is filled left to right (bdLeftToRight) or right to left (bdRightToLeft). Note: bdRightToLeftNoAlign and bdRightToLeftReadingOnly are treated as bdLeftToRight. !!} property BiDiMode; property DragCursor; property DragMode; property Enabled; property ParentShowHint; property PopupMenu; property ShowHint; property Visible; property TabOrder; property TabStop; property OnClick; property OnDblClick; property OnDragDrop; property OnDragOver; property OnEndDrag; property OnMouseDown; property OnMouseMove; property OnMouseUp; property OnStartDrag; property OnKeyDown; property OnKeyPress; property OnKeyUp; property OnContextPopup; {$ifdef IEHASONGESTURE} property OnGesture; {$endif} end; function IEMDefaultTextToStr(DefaultText: TIEImageEnMViewDefaultText): string; const IEM_Path_Index_Delimiter = '::'; // Delimits a filename from its image index. See ImageFilename[] // Possible consts for captions that are replaced at paint time IEM_Filename = '$IEM_FILENAME$'; IEM_FilenameNoExt = '$IEM_FILENAMENOEXT$'; IEM_FilePath = '$IEM_FILEPATH$'; IEM_ImageDimensions = '$IEM_IMAGE_DIMENSIONS$'; IEM_ImageDimAndSize = '$IEM_IMAGE_DIM_AND_SIZE$'; IEM_FileSize = '$IEM_FILESIZE$'; IEM_FileCreateDate = '$IEM_FILECREATEDATE$'; IEM_FileCreateDateTime = '$IEM_FILECREATEDATETIME$'; IEM_FileCreateDateAndSize = '$IEM_FILECREATEDATE_AND_SIZE$'; IEM_FileEditDate = '$IEM_FILEEDITDATE$'; IEM_FileEditDateTime = '$IEM_FILEEDITDATETIME$'; IEM_FileEditDateAndSize = '$IEM_FILEEDITDATE_AND_SIZE$'; IEM_FileType = '$IEM_FILETYPE$'; IEM_FileExt = '$IEM_FILEEXT$'; IEM_ImageDict = '$IEM_IMAGEDICT$'; // a faux file item that adds a "My Computer" item IEF_Drives_Folder = 'IEF_DRIVES_FOLDER'; Max_Icon_Images_To_Cache = 50; // How many icons should be cached in memory? Thumbnail_Background_When_Disabled = cl3DLight; Thumbnail_Border_When_Disabled = clBtnShadow; Text_Color_When_Disabled = clGrayText; implementation uses math, {$IFDEF IEHASTHEMING} Themes, uxTheme { For checkbox drawing }, {$ENDIF} {$ifdef IEINCLUDEFLATSB} flatsb, {$endif} {$ifdef IEUSEVCLZLIB}zlib, {$else}iezlib, {$endif} {$ifdef IEVISION} ievision, {$endif} {$IFDEF VIDEO_THUMBNAILS} iexShellThumbnails, {$ENDIF} iexThemes, iegdiplus, bmpfilt, iesettings, ShellApi, iexCanvasUtils; // Icons to show as "Default" (1000) and "Missing" (1001) files (PNG files stored as RT_RCDATA resources) {$R imvres.res} const IMVRES_DEFAULT_IMAGE = 1000; IMVRES_BROKEN_IMAGE = 1001; {$R-} const CALCULATE_NOW = -13; // Delay calcuation of text heights requiring canvas until handle is created {$IFDEF VIDEO_THUMBNAILS} function OleInitialize(pwReserved: Pointer): HResult; stdcall; external 'ole32.dll' name 'OleInitialize'; procedure OleUninitialize; stdcall; external 'ole32.dll' name 'OleUninitialize'; {$ENDIF} constructor TImageEnMView.Create(Owner: TComponent); begin fThreadCS := TCriticalSection.Create(); fBackBuffer := TIEBitmap.Create; fBackBuffer.Location := ieTBitmap; fImageEnMIO := nil; fImageEnProc := nil; inherited Create(Owner); {$ifdef IEVISION} if (csDesigning in ComponentState) then begin // design mode, unload ievision IEFinalize_ievision(); end; {$endif} IEGDIPLoadLibrary(); fUpdating := false; fMultiSelectedImages := TList.Create; fDestroying := false; fScrollBarsAlwaysVisible := false; fRXScroll := 1; fRYScroll := 1; fHoverCheckLastIdx := -1; fHoverCheckLastPos.X := -1; fScrollBars := ssBoth; Height := 90; Width := 180; fIEMBitmap := TIEMultiBitmap.Create( not ( csDesigning in ComponentState )); fIEMBitmapIsExternal := False; fIEMBitmap.fOwner := Self; fIEMBitmap.OnUpdateParams := UpdateParams; fStoreType := ietNormal; fThumbWidth := 100; fThumbHeight := 100; fZoom := 100.0; fHorizBorder := 4; fVertBorder := 4; fVWidth := 0; fVHeight := 0; fOnViewChange := nil; fOnImageIDRequest := nil; fOnImageIDRequestEx := nil; fOnImageDraw := nil; fOnImageDraw2 := nil; fOnImageOut := nil; fOnImageSelect := nil; fOnImageAdd := nil; fOnImageAdded := nil; fOnImageLoaded := nil; fOnImageDeselect := nil; fOnSelectionChanging := nil; fOnBeforeImageDrawEx := nil; fOnDrawProgress := nil; fOnWrongImage := nil; fOnCreateImage := nil; fOnDestroyImage := nil; fOnCheckboxClick := nil; fOnImageEnGesture := nil; fHDrawDib := IEDrawDibOpen; fImageEnIO := TImageEnIO.Create(self); fSelectedItem := -1; fVisibleSelection := true; fSelectionBorderWidth := 2; fSelectionBorderWidthNoFocus := -1; fThumbnailsSelectedBorderColor := clExplorer_Selection_Border_Color; fBottomGap := 0; fUpperGap := 0; fTopTextHeight := 0; fInfoTextHeight := 0; fBottomTextHeight := 0; fSideGap := 0; fTextMargin := 0; fTextBlockWidth := -1; fModernStyling := False; fMouseInteract := [mmiSelect]; fKeyInteract := [mkiMoveSelected]; fDisplayMode := mdGrid; fGridWidth := 0; fCurrentGridWidth := 0; fPlayTimer := 0; fPlayLoop := true; fLastImOp := IEM_OP_NONE; fLastImIdx := 0; fLastImP1 := 0; fTimerInProgress := false; fFrame := 0; fLockPaint := 0; fLockUpdate := 0; fOnIOProgress := nil; fOnImageAtPos := nil; fDrawImageBackground := false; fThumbnailResampleFilter := rfFastLinear; fThumbnailDisplayFilter := rfNone; fThumbnailClipping := 0; fVScrollBarParams := TIEScrollBarParams.Create; fHScrollBarParams := TIEScrollBarParams.Create; fMouseWheelParams := TIEMouseWheelParams.Create( iemwVScroll ); fMouseWheelParamsAlt := TIEMouseWheelParams.Create( iemwZoom ); fCacheList := TIEVirtualImageList.Create('ICACHE', GetImageCacheUseDisk); fIconList := TIECachedIconList.create(Self, Max_Icon_Images_To_Cache); fTransition := TIETransitionEffects.Create( Self ); fTransitionEffect := iettNone; fTransitionDuration := 1000; fStyle := iemsACD; fDoubleClicking := false; fThumbnailsBackground := clBtnFace; fThumbnailsBackgroundSelected := clBtnFace; fMultiSelecting := false; fEnableMultiSelect := false; fSelectInclusive := false; fMultiSelectionOptions := []; fThumbnailsBorderWidth := 0; fThumbnailsBorderColor := clBtnFace; fThumbnailsBorderCurved := True; fThumbnailsInternalBorderColor := clBlack; fWallpaper := TPicture.Create; fWallpaperStyle := iewoNormal; fIconSize := ieicStretchHD; fOnProgress := nil; fOnBeforeImageDraw := nil; fThreadPoolSize := 5; fThreadPoolIO := TList.Create; fThreadRequests := TList.Create; fLookAheadList := TList.Create; fThreadStarter := TIEStarter.Create; fThreadStarter.mview := self; fSelectImages := false; fEnableImageCaching := true; fHaveMultiselected := false; fSoftShadow := TIEVSoftShadow.Create; fEnableAlphaChannel := true; fBackgroundStyle := iebsSolid; fThumbnailsBackgroundStyle := iebsSolid; fChessboardSize := 16; fChessboardBrushStyle := bsSolid; fChessboardColor2Customized := False; fGradientEndColor := clBtnShadow; fFillThumbnail := true; fMDown := false; fShowText := true; fCurrentCompare := nil; fCurrentCompareEx := nil; fChangedSel := false; fThumbsRounded := 0; fFlatScrollBars := false; fThumbnailFrame := nil; fThumbnailFrameSelected := nil; fThumbnailFrameRect := Rect(0, 0, 0, 0); fDragging := false; fEnableAdjustOrientation := false; fMultiOnDemands := TList.Create; fMaintainInvisibleImages := 15; fLookAhead := 0; fOnAllDisplayed := nil; fAllDisplayed := false; fUserAction := false; fEnableLoadEXIFThumbnails := true; fEnableLoadExplorerThumbnails:= False; fOnFinishWork := nil; fOnAcquireBitmap := nil; fSelectedFontColor := clNone_; fOnPlayFrame := nil; fOnAnimationText := nil; fOnAfterEvent := nil; fBottomTextFont := TFont.Create; fBottomTextFont.OnChange := BottomTextFontChange; fTopTextFont := TFont.Create; fTopTextFont.OnChange := TopTextFontChange; fInfoTextFont := TFont.Create; fInfoTextFont.OnChange := InfoTextFontChange; fTextBackgroundStyle := bsClear; fTextBackgroundColor := clBtnFace; fTextTruncSide := iemtsLeft; fAnimation := nil; fAnimationDraggingSlider := false; fAnimationTimer := TTimer.Create(self); fLastMouseMoveX := -1; fLastMouseMoveY := -1; fTrackMouseSelection := false; fDrawMouseSelection := false; fCheckThumbBoundsOnSelect := false; fSelectedImageAlwaysVisible := True; fThumbnailOptionsEx := [ietxShowIconForUnknownFormat, ietxShowIconWhileLoading, ietxEnableInternalIcons, ietxStretchSmallImages]; fIOOptionsEx := []; fCheckboxes := iecbNone; fCheckedCount := -1; fCheckedBitmap := nil; fUncheckedBitmap := nil; fMissingFileIcon := nil; fDefaultFileIcon := nil; fAnnotationsVisible := False; fCheckboxPos := iecpTopLeft; fCheckboxMargins := Point(4, 4); fTextColumnWidths[ iemtpTop ] := -1; fTextColumnWidths[ iemtpBottom ] := -1; fTextColumnWidths[ iemtpInfo ] := -1; fResizingTextColIdx := -1; fResizingTextColClickX := -1; fShowThumbnailHint := False; fDefaultTopText := iedtNone; fDefaultInfoText := iedtNone; fDefaultBottomText := iedtNone; if ClassName = 'TImageEnFolderMView' then begin fDefaultBottomText := iedtFilename; fBottomTextHeight := CALCULATE_NOW; end; fGestures := TIEMViewerGestures.Create(); fImageCacheReusage := iecrNone; end; procedure TImageEnMView.ClearThreadsAndRequests; var i: Integer; begin fThreadCS.Enter(); try fLookAheadList.Clear; fThreadRequests.Clear; for i := 0 to fThreadPoolIO.Count - 1 do if TImageEnIO(fThreadPoolIO[i]).Tag > -1 then begin TImageEnIO(fThreadPoolIO[i]).Tag := -2; TImageEnIO(fThreadPoolIO[i]).Aborting := true; end; finally fThreadCS.Leave(); end; // wait up to 1 second for i := 1 to 10 do if fThreadPoolIO.Count > 0 then sleep(100); end; procedure TImageEnMView.AbortImageLoading(idx: Integer); var i: Integer; begin if assigned(fThreadRequests) and assigned(fLookAheadList) and assigned(fThreadPoolIO) then begin fThreadCS.Enter(); try fThreadRequests.Remove(pointer(idx)); fLookAheadList.Remove(pointer(idx)); for i := 0 to fThreadPoolIO.Count - 1 do if TImageEnIO(fThreadPoolIO[i]).Tag = idx then begin TImageEnIO(fThreadPoolIO[i]).Tag := -2; TImageEnIO(fThreadPoolIO[i]).Aborting := true; break; end; finally fThreadCS.Leave(); end; end; end; // note: the timer object is not destroyed because the win32 should destroy it. destructor TImageEnMView.Destroy; var toDestroy: TIEBitmap; begin fDestroying := true; // Disconnect any attached IEMBitmap SetExternalMBitmap( nil ); DeselectNU; fThreadStarter.Terminate; Windows.SetEvent(fThreadStarter.resumeEvent); fThreadStarter.WaitFor(); // threads ClearThreadsAndRequests; while fThreadPoolIO.Count > 0 do begin toDestroy := TImageEnIO(fThreadPoolIO[0]).IEBitmap; TImageEnIO(fThreadPoolIO[0]).free; fThreadPoolIO[0] := nil; FreeAndNil(toDestroy); fThreadPoolIO.Delete(0); end; FreeAndNil(fThreadStarter); FreeAndNil(fThreadRequests); FreeAndNil(fThreadPoolIO); // ClearOnDemandIOList; FreeAndNil(fMultiOnDemands); // if assigned(fImageEnMIO) then FreeAndNil(fImageEnMIO); if assigned(fImageEnProc) then FreeAndNil(fImageEnProc); // remove all objects DeleteAllImages(); // FreeAndNil(fWallpaper); FreeAndNil(fTransition); Deselect; FreeAndNil(fCacheList); FreeAndNil(fIconList); FreeAndNil(fIEMBitmap); IEDrawDibClose(fHDrawDib); FreeAndNil(fImageEnIO); FreeAndNil(fMultiSelectedImages); if assigned(fThumbnailFrame) then FreeAndNil(fThumbnailFrame); if assigned(fThumbnailFrameSelected) then FreeAndNil(fThumbnailFrameSelected); // if assigned(fDragScrollTimer) then FreeAndNil(fDragScrollTimer); FreeAndNil(fVScrollBarParams); FreeAndNil(fHScrollBarParams); FreeAndNil(fMouseWheelParams); FreeAndNil(fMouseWheelParamsAlt); FreeAndNil(fSoftShadow); FreeAndNil(fLookAheadlist); FreeAndNil(fBottomTextFont); FreeAndNil(fTopTextFont); FreeAndNil(fInfoTextFont); FreeAndNil(fCheckedBitmap); FreeAndNil(fUncheckedBitmap); FreeAndNil(fMissingFileIcon); FreeAndNil(fDefaultFileIcon); FreeAndNil(fGestures); FreeAndNil(fAnimationTimer); if assigned(fAnimation) then FreeAndNil(fAnimation); FreeAndNil(fBackBuffer); FreeAndNil(fThreadCS); IEGDIPUnLoadLibrary(); inherited; end; {!! TImageEnMView.ScrollBars Declaration property ScrollBars: TScrollType; Description Specifies whether the TImageEnView control displays scroll bars. Note: Scrollbars are never displayed if they are not required (unless is set to true) Value Description ssNone No scroll bars are shown ssHorizontal A single scroll bar is shown along the bottom edge when needed ssVertical A single scroll bar is shown along the right edge when needed ssBoth Scroll bars are shown on both the bottom and right edges when needed
!!} procedure TImageEnMView.SetScrollBars(v: TIEScrollStyle); begin fScrollBars := v; if ((GetParentForm(self) = nil) and (ParentWindow = 0)) or (not HandleAllocated) then exit; if (fScrollBars <> ssVertical) and (fScrollBars <> ssBoth) then IEShowScrollBar(handle, SB_VERT, false, fFlatScrollBars); if (fScrollBars <> ssHorizontal) and (fScrollBars <> ssBoth) then IEShowScrollBar(handle, SB_HORZ, false, fFlatScrollBars); UpdateEx(false); end; {!! TImageEnMView.StoreType Declaration property StoreType:
; Description Specifies how image used by the TImageEnMView component are stored in memory (as full size images or thumbnails at their display size) !!} procedure TImageEnMView.SetStoreType(v : TIEStoreType); begin fStoreType := v; if fStoreType = ietFastThumb then begin fEnableImageCaching := True; if fThumbnailDisplayFilter = rfNone then fThumbnailDisplayFilter := rfFastLinear; end; end; procedure TImageEnMView.WMSize(var Message: TWMSize); begin inherited; UpdateEx(false); end; procedure TImageEnMView.IEMAutoScroll(var Message: TMessage); var iX, iY: integer; begin try if HiByte(GetAsyncKeyState(VK_LBUTTON)) <> 0 then begin // Mouse still down iX := ScreenToClient(Mouse.CursorPos).X; iY := ScreenToClient(Mouse.CursorPos).Y; MouseMove([], iX, iY); end; except // Unexpected mouse error end; end; procedure TImageEnMView.WMEraseBkgnd(var Message: TMessage); begin Message.Result := 0; end; procedure TImageEnMView.WMMouseWheel(var Message: TMessage); var zDelta, nPos: integer; dir: integer; Params: TIEMouseWheelParams; begin inherited; // Ctrl key pressed? if GetKeyState( VK_CONTROL) < 0 then Params := fMouseWheelParamsAlt else Params := fMouseWheelParams; if Params.Action = iemwNone then exit; fUserAction := true; try zDelta := smallint($FFFF and (Message.wParam shr 16)); if zDelta > 0 then dir := -1 else dir := 1; if Params.InvertDirection then dir := -1 * dir; case Params.Action of iemwVScroll: begin case Params.Variation of iemwAbsolute: // pixel based if fCurrentGridWidth = 0 then begin // horizontal nPos := fViewX + dir * Params.Value; SetViewX(nPos); end else begin // vertical nPos := fViewY + dir * Params.Value; SetViewY(nPos); end; iemwPercentage: // thumbnail based // NOTE: DEFAULT VALUE OF Params is Value=8/Variation=iemwPercentage // For compatibility with TImageEnView and previous versions of TImageEnMView // We will work on a theoretical grid of 12.5 thumbnails high, so "8% of window" // will always equate to one thumbnail height regardless of thumbnail size if fCurrentGridWidth = 0 then begin // Horizontal scroll nPos := fViewX + dir * Trunc( ThumbSizeInfo( itsOuter ).X / 8 * Params.Value ); SetViewX(nPos); end else begin // Vertical scroll nPos := fViewY + dir * Trunc( ThumbSizeInfo( itsOuter ).Y / 8 * Params.Value ); SetViewY(nPos); end; end; ViewChange(0); end; iemwZoom: begin case Params.Variation of iemwAbsolute: Zoom := fZoom + dir * Params.Value; iemwPercentage: Zoom := fZoom + imax(round(fZoom * Params.Value / 100), 1) * dir; end; end; iemwZoomView: SetStyleInt( GetStyleInt - dir ); iemwNavigate: begin if dir < 0 then Seek(ieioSeekPrior) else Seek(ieioSeekNext); end; end; finally // user action in ViewChange could raise exceptions fUserAction := false; end; end; procedure TImageEnMView.WMVScroll(var Message: TMessage); var nPos: integer; mx, my: integer; begin inherited; fUserAction := true; try case Message.WParamLo of SB_THUMBPOSITION, SB_THUMBTRACK: begin if (not fVScrollBarParams.Tracking) and (Message.WParamLo = SB_THUMBTRACK) then exit; nPos := trunc(Message.WParamHi * fRYScroll); end; SB_BOTTOM: begin GetMaxViewXY(mx, my); nPos := my; end; SB_TOP: nPos := 0; SB_LINEDOWN: if fVScrollBarParams.LineStep = -1 then nPos := fViewY + ThumbSizeInfo( itsOuter ).Y else nPos := fViewY + fVScrollBarParams.LineStep; SB_LINEUP: if fVScrollBarParams.LineStep = -1 then nPos := fViewY - ThumbSizeInfo( itsCell ).Y - fVertBorder else nPos := fViewY - fVScrollBarParams.LineStep; SB_PAGEDOWN: if fVScrollBarParams.PageStep = -1 then nPos := fViewY + ClientHeight else nPos := fViewY + fVScrollBarParams.PageStep; SB_PAGEUP: if fVScrollBarParams.PageStep = -1 then nPos := fViewY - ClientHeight else nPos := fViewY - fVScrollBarParams.PageStep; else nPos := fViewY; end; SetViewY(nPos); ViewChange(0); finally fUserAction := false; end; end; procedure TImageEnMView.WMHScroll(var Message: TMessage); var nPos: integer; mx, my: integer; begin inherited; fUserAction := true; try case Message.WParamLo of SB_THUMBPOSITION, SB_THUMBTRACK: begin if (not fHScrollBarParams.Tracking) and (Message.WParamLo = SB_THUMBTRACK) then exit; nPos := trunc(Message.WParamHi * fRXScroll); end; SB_BOTTOM: begin GetMaxViewXY(mx, my); nPos := mx; end; SB_TOP: nPos := 0; SB_LINEDOWN: if fHScrollBarParams.LineStep = -1 then nPos := fViewX + ThumbSizeInfo( itsOuter ).X else nPos := fViewX + fVScrollBarParams.LineStep; SB_LINEUP: if fVScrollBarParams.LineStep = -1 then nPos := fViewX - ThumbSizeInfo( itsCell ).X - fHorizBorder else nPos := fViewX - fVScrollBarParams.LineStep; SB_PAGEDOWN: if fHScrollBarParams.PageStep = -1 then nPos := fViewX + ClientWidth else nPos := fViewX + fVScrollBarParams.PageStep; SB_PAGEUP: if fVScrollBarParams.PageStep = -1 then nPos := fViewX - ClientWidth else nPos := fViewX - fVScrollBarParams.PageStep; else nPos := fViewX; end; SetViewX(nPos); ViewChange(0); finally fUserAction := false; end; end; Procedure _SetLoadParams(MView : TImageEnMView; Params : TIOParams); const SMALLEST_RAW_IMAGE_WIDTH = 1800; SMALLEST_RAW_IMAGE_HEIGHT = 1400; Quality_Scaler = 3; // Improve quality of thumbnails when resampled var iMaxX, iMaxY : Integer; begin if mview.fStoreType in [ietThumb, ietFastThumb] then begin Params.JPEG_Scale := IOJPEG_AUTOCALC; Params.JPEG_GetExifThumbnail := ( mview.ThumbSizeInfo( itsImage ).X <= 200 ) and (mview.ThumbSizeInfo( itsImage ).Y <= 200) and mview.fEnableLoadEXIFThumbnails; Params.JPEG_DCTMethod := ioJPEG_IFAST; iMaxX := MulDiv( mview.ThumbSizeInfo( itsImage ).X, 100 + mView.ThumbnailClipping, 100 ); iMaxY := MulDiv( mview.ThumbSizeInfo( itsImage ).Y, 100 + mView.ThumbnailClipping, 100 ); if mview.fStoreType = ietFastThumb then begin iMaxX := iMaxX * Quality_Scaler; iMaxY := iMaxY * Quality_Scaler; end; Params.Width := iMaxX; Params.Height := iMaxY; {$ifdef IEINCLUDERAWFORMATS} Params.RAW_GetExifThumbnail := mview.fEnableLoadEXIFThumbnails and ( mview.ThumbSizeInfo( itsImage ).X <= 200 ) and (mview.ThumbSizeInfo( itsImage ).Y <= 200); Params.RAW_HalfSize := ( mview.ThumbSizeInfo( itsImage ).X <= SMALLEST_RAW_IMAGE_WIDTH ) and ( mview.ThumbSizeInfo( itsImage ).Y <= SMALLEST_RAW_IMAGE_HEIGHT ); {$endif} Params.IEN_GetThumbnail := ( mview.ThumbSizeInfo( itsImage ).X <= IEGlobalSettings().ThumbnailSize ) and ( mview.ThumbSizeInfo( itsImage ).Y <= IEGlobalSettings().ThumbnailSize ); end else Params.JPEG_Scale := IOJPEG_FULLSIZE; Params.EnableAdjustOrientation := mview.fEnableAdjustOrientation; end; // frees some I/O parameters when loading thumbnails procedure StripOffIOParams(MView: TImageEnMView; Params: TIOParams); begin if mview.fStoreType in [ietThumb, ietFastThumb] then begin Params.TIFF_PhotoshopImageResources := nil; Params.TIFF_PhotoshopImageSourceData := nil; end; end; // double click procedure TImageEnMView.WMLButtonDblClk(var Message: TWMLButtonDblClk); begin fDoubleClicking := true; inherited; end; {!! TImageEnMView.Assign Declaration procedure Assign(Source: TPersistent); Description Replace the existing content with the frames in TImageEnMView, , , TBitmap or TImageList. Notes: - Params are NOT copied. See Cannot be used if a is attached to the control See Also - - !!} procedure TImageEnMView.Assign(Source: TPersistent); begin AssignEx( Source ); end; {!! TImageEnMView.AssignEx Declaration procedure AssignEx(Source: TObject; bCopyParams: Boolean = False); Description Replace the existing content with the frames in TImageEnMView, , , TBitmap or TImageList. if bCopyParams is true then Params are also copied. Note: Cannot be used if a is attached to the control !!} procedure TImageEnMView.AssignEx(Source: TObject; bCopyParams: Boolean = False); begin if IEMBitmap_IsTIEDBMultiBitmap then raise EIEException.create('Cannot assign to a TIEDBMultiBitmap'); TIEMultiBitmap( fIEMBitmap ).Assign( Source ); if bCopyParams and ( Source is TIECustomMultiBitmap ) and TIECustomMultiBitmap( Source ).ParamsEnabled then MIO.fParamsList.Assign( TIECustomMultiBitmap( Source ).ParamsList ) else if bCopyParams and ( Source is TIEBitmap ) and TIEBitmap( Source ).ParamsEnabled then MIO.Params[ 0 ].Assign( TIEBitmap( Source ).Params ) else if bCopyParams and ( Source is TImageEnMView ) then MIO.fParamsList.Assign( TImageEnMView( Source ).MIO.ParamsList ); Update; end; {!! TImageEnMView.AssignLayers Declaration procedure TImageEnMView.AssignLayers(Source: ; HighlightSel: Boolean; DoClear: Boolean = True); Description Fill content with the layers of a TImageEnView. If HighlightSel is true, the selected layers will be also be shown as selected in this TImageEnMView. Set DoClear to true if you don't wish to clear the existing content. Example // Show layer content of a TImageEnView in a TImageEnMView. Allow selection of layers via the TImageEnMView // For more info, see the demo: \Demos\ImageEditing\Layers\Layers.dpr procedure Tfmain.ImageEnMView1ImageSelect(Sender: TObject; idx: Integer); begin ImageEnView1.LayersCurrent := idx; end; procedure Tfmain.ImageEnMView1ImageDeselect(Sender: TObject; idx: Integer); begin ImageEnView1.Layers[ idx ].Selected := False; end; procedure Tfmain.ImageEnView1LayerNotify(Sender: TObject; layer: Integer; event: TIELayerEvent); begin if event in [ ielSelected, ielDeselected, ielMoved, ielResized, ielRotated, ielCreated, ielAction ] then RefreshLayerViewer(); end; procedure Tfmain.LayerControlChange(Sender: TObject); begin RefreshLayerViewer(); end; procedure Tfmain.ImageEnView1NewLayer(Sender: TObject; LayerIdx: Integer; LayerKind: TIELayerKind); begin RefreshLayerViewer(); end; procedure Tfmain.RefreshLayerViewer(); begin ImageEnMView1.AssignLayers( ImageEnView1, True ); end; !!} // Fill ImageEnMView1 with all layers of ImageEnView1 procedure TImageEnMView.AssignLayers(Source: TImageEnView; HighlightSel: Boolean; DoClear: Boolean = True); var bmp: TIEBitmap; i, idx, offsetIndex: integer; begin bmp := TIEBitmap.create; LockUpdate(); try if DoClear then Clear; offsetIndex := ImageCount; for i := 0 to Source.LayersCount - 1 do begin if StoreType = ietNormal then Source.Layers[i].CopyToBitmap( bmp, -1, -1 ) else Source.Layers[i].CopyToBitmap( bmp, ThumbSizeInfo( itsImage ).X, ThumbSizeInfo( itsImage ).Y ); idx := AppendImage( bmp ); if Source.Layers[i].Name = '' then ImageTopText[ idx ] := 'Layer ' + inttostr( i + 1 ) else ImageTopText[ idx ] := Source.Layers[i].Name; end; // Mark selected layers and highlight the current layer if HighlightSel then begin BeginSelectImages; for i := 0 to Source.LayersCount - 1 do if Source.Layers[ i ].Selected then SelectedImage := offsetIndex + i; SelectedImage := offsetIndex + Source.LayersCurrent; // Make it the active image EndSelectImages; end; finally UnlockUpdate(); bmp.Free(); end; end; procedure TImageEnMView.SetBounds(ALeft, ATop, AWidth, AHeight: Integer); begin inherited; end; procedure TImageEnMView.GetMaxViewXY(var mx, my: integer); begin mx := imax(fVWidth - ClientWidth, 0); my := imax(fVHeight - ClientHeight, 0); end; {!! TImageEnMView.ViewX Declaration property ViewX: integer; Description ViewX is the first column visible at the top-left corner of the control, in pixels (for example, if the user has scrolled horizontally by two columns then it will return 2 * ). It is only relevant when has a value greater than zero (otherwise it always returns 0). You can set ViewX to simulate horizontal scrollbar movement. See also: . !!} procedure TImageEnMView.SetViewX(v: integer); var max_x, max_y: integer; begin if v = fViewX then exit; GetMaxViewXY(max_x, max_y); fViewX := ilimit(v, 0, max_x); invalidate; if (fScrollBars = ssHorizontal) or (fScrollBars = ssBoth) then IESetScrollPos(Handle, SB_HORZ, trunc(fViewX / fRXScroll), true, fFlatScrollBars); end; {!! TImageEnMView.ViewY Declaration property ViewY: integer; Description ViewY is the first row visible at the top-left corner of the control, in pixels (for example, if the user has scrolled vertically by two rows then it will return 2 * ). It is not relevant if = 0 (in which case it always returns 0). You can set ViewY to simulate vertical scrollbar movement. See also: . !!} procedure TImageEnMView.SetViewY(v: integer); var max_x, max_y: integer; begin if v = fViewY then exit; GetMaxViewXY(max_x, max_y); fViewY := ilimit(v, 0, max_y); invalidate; if (fScrollBars = ssVertical) or (fScrollBars = ssBoth) then IESetScrollPos(Handle, SB_VERT, trunc(fViewY / fRYScroll), true, fFlatScrollBars); end; {!! TImageEnMView.SetViewXY Declaration procedure SetViewXY(x, y: integer); Description Sets and simultaneously. !!} procedure TImageEnMView.SetViewXY(x, y: integer); var max_x, max_y: integer; begin if Parent = nil then exit; if (x = fViewX) and (y = fViewY) then exit; GetMaxViewXY(max_x, max_y); fViewX := ilimit(x, 0, max_x); fViewY := ilimit(y, 0, max_y); invalidate; if (fScrollBars = ssHorizontal) or (fScrollBars = ssBoth) then IESetScrollPos(Handle, SB_HORZ, trunc(fViewX / fRXScroll), true, fFlatScrollBars); if (fScrollBars = ssVertical) or (fScrollBars = ssBoth) then IESetScrollPos(Handle, SB_VERT, trunc(fViewY / fRYScroll), true, fFlatScrollBars); end; procedure TImageEnMView.PaintToCanvas(DestCanvas: TCanvas); var iStartX, iStartY: integer; begin if fLockPaint = 0 then begin if (not HandleAllocated) or (ClientWidth=0) or (ClientHeight=0) then // 3.0.0 exit; if (fBackBuffer.Width <> ClientWidth) or (fBackBuffer.Height <> ClientHeight) then fBackBuffer.Allocate(ClientWidth, ClientHeight, ie24RGB); if fLockUpdate = 0 then begin if assigned(fAnimation) then AnimPaintTo(fBackBuffer) else begin PaintTo(fBackBuffer.VclBitmap); if fTrackMouseSelection and fDrawMouseSelection then with TIECanvas.Create(fBackBuffer.Canvas) do begin Brush.Color := $85664F; Brush.Style := bsSolid; Brush.Transparency := 128; Pen.Color := Brush.Color; Pen.Width := 1; Pen.Style := psSolid; Pen.Transparency := 255; iStartX := fHSVX1 + fHSX1 - ViewX; iStartY := fHSVY1 + fHSY1 - ViewY; Rectangle(iStartX, iStartY, fLastMouseMoveX, fLastMouseMoveY); Free(); end; end; end; if (IEGlobalSettings().SystemColors < 24) and not IEGlobalSettings().IsRemoteSession then begin // dithering needed (for example display with 16bit depth need dithering) SetStretchBltMode(DestCanvas.Handle, HALFTONE); StretchBlt(DestCanvas.Handle, 0, 0, fBackBuffer.Width, fBackBuffer.Height, fBackBuffer.Canvas.Handle, 0, 0, fBackBuffer.Width, fBackBuffer.Height, SRCCOPY); end else begin // no dithering needed (fastest way) BitBlt(DestCanvas.handle, 0, 0, fBackBuffer.Width, fBackBuffer.Height, fBackBuffer.Canvas.Handle, 0, 0, SRCCOPY); end; end; end; procedure TImageEnMView.Paint; begin PaintToCanvas(Canvas); DoAfterEvent(ieaePaint); end; {!! TImageEnMView.ImageWidth Declaration property ImageWidth[idx: Integer]: Integer; Description ImageWidth and return the dimensions of the image, idx. Note: If images are being loaded on demand, then the image dimensions will not be valid until the image is loaded. Either use the to delay until the image is ready, or force loading of the image by using Example // Display the image size below the thumbnail // Ensure you have set the BottomGap property procedure TForm1.ImageEnMView1ImageDraw(Sender: TObject; idx: Integer; Left, Top: Integer; Canvas: TCanvas); begin Canvas.Font.Height := 15; Canvas.Font.Color := clWhite; Canvas.TextOut(Left, Top + imageenmview1.ThumbHeight - imageenmview1.bottomgap + 2, IntToStr(imageenmview1.ImageWidth[idx]) + 'x' + IntToStr(imageenmview1.ImageHeight[idx])); end; !!} function TImageEnMView.GetImageWidth(idx: integer): integer; begin result := fIEMBitmap.ImageWidth[ idx ]; end; {!! TImageEnMView.ImageHeight Declaration property ImageHeight[idx: Integer]: Integer; Description and ImageHeight return the dimensions of the image, idx. Note: If images are being loaded on demand, then the image dimensions will not be valid until the image is loaded. Either use the to delay until the image is ready, or force loading of the image by using Example // Display the image size below the thumbnail // Ensure you have set the BottomGap property procedure TForm1.ImageEnMView1ImageDraw(Sender: TObject; idx: Integer; Left, Top: Integer; Canvas: TCanvas); begin Canvas.Font.Height := 15; Canvas.Font.Color := clWhite; Canvas.TextOut(Left, Top + imageenmview1.ThumbHeight - imageenmview1.bottomgap + 2, IntToStr(imageenmview1.ImageWidth[idx]) + 'x' + IntToStr(imageenmview1.ImageHeight[idx])); end; !!} function TImageEnMView.GetImageHeight(idx: integer): integer; begin result := fIEMBitmap.ImageHeight[ idx ]; end; {!! TImageEnMView.ImageOriginalWidth Declaration property ImageOriginalWidth[idx: Integer]: Integer; Description Use ImageOriginalWidth to read or set the original width of the image, idx. This is useful only when images are stored as thumbnails ( = ietThumb/ietFastThumb) and you need to know the original image size. Note: If images are being loaded on demand, then the image dimensions will not be valid until the image is loaded. Either use the to delay until the image is ready, or force loading of the image by using See Also - !!} function TImageEnMView.GetImageOriginalWidth(idx: integer): integer; begin result := 0; if (idx >= 0) and (idx < fIEMBitmap.Count) then with fIEMBitmap.GetImageInfo( idx ) do begin if image <> nil then result := fIEMBitmap.fImageList.GetImageOriginalWidth( image ) else if cacheImage <> nil then result := fCacheList.GetImageOriginalWidth(cacheImage); end; end; {!! TImageEnMView.ImageOriginalHeight Declaration property ImageOriginalHeight[idx: Integer]: Integer; Description Use ImageOriginalHeight to read or set the original height of the image, idx. This is useful only when images are stored as thumbnails ( = ietThumb/ietFastThumb) and you need to know the original image size. Note: If images are being loaded on demand, then the image dimensions will not be valid until the image is loaded. Either use the to delay until the image is ready, or force loading of the image by using See Also - !!} function TImageEnMView.GetImageOriginalHeight(idx: integer): integer; begin result := 0; if (idx >= 0) and (idx < fIEMBitmap.Count) then with fIEMBitmap.GetImageInfo( idx ) do begin if image <> nil then result := fIEMBitmap.fImageList.GetImageOriginalHeight( image ) else if cacheImage <> nil then result := fCacheList.GetImageOriginalHeight(cacheImage); end; end; procedure TImageEnMView.SetImageOriginalWidth(idx: integer; Value: integer); begin fIEMBitmap.ImageOriginalWidth[ idx ] := Value; end; procedure TImageEnMView.SetImageOriginalHeight(idx: integer; Value: integer); begin fIEMBitmap.ImageOriginalHeight[ idx ] := Value; end; // Retrieve the size and dates of the image at idx, from the file system procedure TImageEnMView.GetFileDetailsForImage(idx: integer); var ii: TIEImageInfo; iFileSizeBytes: Int64; dtCreateDate: TDateTime; dtModifiedDate: TDateTime; begin // Assumes we have already checked index is valid! ii := fIEMBitmap.GetImageInfo( idx ); if ii.FileSize = -1 then exit; // we have already checked this if (ii.Filename <> '') and IEGetFileDetails(ii.Filename, iFileSizeBytes, dtCreateDate, dtModifiedDate) then begin ii.FileSize := iFileSizeBytes; ii.CreateDate := dtCreateDate; ii.EditDate := dtModifiedDate; end else begin ii.FileSize := -1; ii.CreateDate := 0; ii.EditDate := 0; end; end; {!! TImageEnMView.ImageCreateDate Declaration property ImageCreateDate[idx: Integer]: TDateTime; Description Returns the creation date for the file at index, idx. If the file is a JPEG then this will be read from the EXIF data for greater accuracy. Otherwise it is read from the file system. Result is 0 if this frame does not exist as a file on disk and has no exif data. See also: . !!} function TImageEnMView.GetImageCreateDate(idx: integer): TDateTime; begin result := 0; if (idx >= 0) and (idx < fIEMBitmap.Count) then begin result := fIEMBitmap.GetImageInfo( idx ).CreateDate; if Result = 0 then begin GetFileDetailsForImage(idx); result := fIEMBitmap.GetImageInfo( idx ).CreateDate; end; end; end; procedure TImageEnMView.SetImageCreateDate(idx: integer; Value: TDateTime); begin if (idx >= 0) and (idx < fIEMBitmap.Count) then fIEMBitmap.GetImageInfo( idx ).CreateDate := Value; end; {!! TImageEnMView.ImageEditDate Declaration property ImageEditDate[idx: Integer]: TDateTime; Description Returns the last modification date for the file at index, idx, which is read from the file system. Result is 0 if this frame does not exist as a file on disk. See also: . !!} function TImageEnMView.GetImageEditDate(idx: integer): TDateTime; begin result := 0; if (idx >= 0) and (idx < fIEMBitmap.Count) then begin result := fIEMBitmap.GetImageInfo( idx ).EditDate; if Result = 0 then begin GetFileDetailsForImage(idx); result := fIEMBitmap.GetImageInfo( idx ).EditDate; end; end; end; procedure TImageEnMView.SetImageEditDate(idx: integer; Value: TDateTime); begin if (idx >= 0) and (idx < fIEMBitmap.Count) then fIEMBitmap.GetImageInfo( idx ).EditDate := Value; end; {!! TImageEnMView.ImageFileSize Declaration property ImageFileSize[idx: Integer]: Int64; Description Returns the file size (in Bytes) for the file at index, idx. Result is -1 if this frame does not exist as a file on disk. !!} function TImageEnMView.GetImageFileSize(idx: integer): Int64; begin Result := -1; if (idx >= 0) and (idx < fIEMBitmap.Count) then begin result := fIEMBitmap.GetImageInfo( idx ).FileSize; if Result = -1 then begin GetFileDetailsForImage(idx); result := fIEMBitmap.GetImageInfo( idx ).FileSize; end; end; end; {!! TImageEnMView.ImageFileType Declaration property ImageFileType[idx: Integer]: WideString; Description Returns the Window's file type for the file at index, idx. !!} function TImageEnMView.GetImageFileType(idx: integer): WideString; function IEGetFileFileType(const sFilename : String): String; var shfi: TShFileInfo; begin try ShGetFileInfo(PChar(sFilename), 0, shfi, SizeOf(TShFileInfo), SHGFI_TYPENAME); Result := shfi.szTypeName; except Result := ''; end; end; var sFilename: string; begin Result := ''; if (idx >= 0) and (idx < fIEMBitmap.Count) then begin sFilename := fIEMBitmap.GetImageInfo( idx ).Filename; if sFilename <> '' then result := IEGetFileFileType(sFilename); end; end; {!! TImageEnMView.ImageType Declaration property ImageType[idx: Integer]: ; Description Determines the type of file at at index, idx. Example case IEFolderMView1.ImageType[idx] of ieftFolder : Caption := 'Folder'; ieftSupportedImage : Caption := 'Image/Video'; ieftFile : Caption := 'File'; end; !!} function TImageEnMView.GetImageType(idx: integer): TIEFolderImageType; begin Result := ieftSupportedImage; if (idx >= 0) and (idx < fIEMBitmap.Count) then begin if fIEMBitmap.GetImageInfo( idx ).SourceType = iestFolderIcon then Result := ieftFolder else if IsKnownFormat(fIEMBitmap.GetImageInfo( idx ).Filename) then Result := ieftSupportedImage else Result := ieftFile; end; end; procedure TImageEnMView.SetImageFileSize(idx: integer; Value: Int64); begin if (idx >= 0) and (idx < fIEMBitmap.Count) then fIEMBitmap.GetImageInfo( idx ).FileSize := Value; end; {!! TImageEnMView.ImageBitCount Declaration property ImageBitCount[idx: Integer]: Integer; Description Returns the bit count of the image, idx. It can be: 1 : Black/white image 24 : True color image Note: If images are being loaded on demand, then the image dimensions will not be valid until the image is loaded. Either use the to delay until the image is ready, or force loading of the image by using !!} function TImageEnMView.GetImageBitCount(idx: integer): integer; begin result := 0; if (idx >= 0) and (idx < fIEMBitmap.Count) then with fIEMBitmap.GetImageInfo( idx ) do begin if image <> nil then result := fIEMBitmap.fImageList.GetImageBitCount(image) else if cacheImage <> nil then result := fCacheList.GetImageBitCount(cacheImage); end; end; {!! TImageEnMView.ImageY Declaration property ImageY[idx: Integer]: integer; Description Returns the Y position (in pixels) where image idx will be shown. Read-only !!} function TImageEnMView.GetImageY(idx: integer): integer; begin result := 0; if (idx >= 0) and (idx < fIEMBitmap.Count) then result := fIEMBitmap.GetImageInfo( idx ).Y; end; {!! TImageEnMView.ImageX Declaration property ImageX[idx: Integer]: integer; Description Returns the X position (in pixels) where image idx will be shown. Read-only !!} function TImageEnMView.GetImageX(idx: integer): integer; begin result := 0; if (idx >= 0) and (idx < fIEMBitmap.Count) then result := fIEMBitmap.GetImageInfo( idx ).X; end; {!! TImageEnMView.ImageRow Declaration property ImageRow[idx: Integer]: integer; (Read-only) Description Returns the row where image idx will be shown. ImageRow[] returns 0 for the first image, 1 for an image on the second row, etc. !!} function TImageEnMView.GetImageRow(idx: integer): integer; begin result := 0; if (idx >= 0) and (idx < fIEMBitmap.Count) then result := fIEMBitmap.GetImageInfo( idx ).row; end; {!! TImageEnMView.ImageCol Declaration property ImageCol[idx: Integer]: integer; (Read-only) Description ImageCol returns the column where is the image idx will be shown. ImageCol[] returns 0 for the first image, 1 for an image on the second column, etc. !!} function TImageEnMView.GetImageCol(idx: integer): integer; begin result := 0; if (idx >= 0) and (idx < fIEMBitmap.Count) then result := fIEMBitmap.GetImageInfo( idx ).col; end; // Note: set ID = -1 procedure TImageEnMView.SetImageFileName(idx: integer; v: WideString); begin fIEMBitmap.ImageFileName[ idx ] := v; end; procedure TImageEnMView.SetImageTopText(idx: integer; v: WideString); begin if (idx >= 0) and (idx < fIEMBitmap.Count) then with fIEMBitmap.GetImageInfo( idx ) do if TopText <> v then begin TopText := v; if v <> '' then UpdateTopTextHeight( True ); Update; end; end; procedure TImageEnMView.SetImageBottomText(idx: integer; v: WideString); begin if (idx >= 0) and (idx < fIEMBitmap.Count) then with fIEMBitmap.GetImageInfo( idx ) do if BottomText <> v then begin BottomText := v; if v <> '' then UpdateBottomTextHeight( True ); Update; end; end; procedure TImageEnMView.SetImageInfoText(idx: integer; v: WideString); begin if (idx >= 0) and (idx < fIEMBitmap.Count) then with fIEMBitmap.GetImageInfo( idx ) do if InfoText <> v then begin InfoText := v; if v <> '' then UpdateInfoTextHeight( True ); Update; end; end; {!! TImageEnMView.ImageFileName Declaration property ImageFileName[idx: Integer]: WideString; Description Specifies the file from where TImageEnMView will load the image for index, idx (loading is delayed until it needs to be shown). A full file path must be specified. Optionally an image index can be specified for multi-page files in the form: "FullFilePath::ImageIndex" Example 1 // Load image1.jpg as thumbnail 0 and image2.jpg as thumbnail 1 ImageEnView1.ImageFileName[0] := 'C:\image1.jpg'; ImageEnView1.ImageFileName[1] := 'C:\image2.jpg'; Example 2 // Load frame 0 and 1 from input.mpeg ImageEnView1.ImageFileName[0] := 'C:\input.mpeg::0'; ImageEnView1.ImageFileName[1] := 'C:\input.mpeg::1'; Example 3 This example inserts two images. The first is loaded from 'one.tif' and the second from 'two.tif'. The images are loaded only when these are shown (otherwise they are freed). ImageEnMView1.InsertImage(0); ImageEnMView1.ImageFileName[0] := 'C:\one.tif'; ImageEnMView1.InsertImage(1); ImageEnMView1.ImageFileName[1] := 'C:\two.tif'; See Also - !!} function TImageEnMView.GetImageFileName(idx: integer): WideString; begin result := fIEMBitmap.ImageFileName[ idx ]; end; {!! TImageEnMView.ImageTopText Declaration property ImageTopText[idx: Integer]: WideString; Description Use ImageTopText to specify custom text to appear above the thumbnail of index, idx. The default top text is specified by but you can override this for a specific thumbnail by setting a value for ImageTopText. Notes: - The font style is set by . But you can customize it for specific thumbnails using the event. - will be adjusted to fit the text. - Other text fields that can be set are: and You can optionally specify the following constants: Value Displays Example IEM_Filename Name of the file 'MyImage.jpg' IEM_FilenameNoExt Name of the file without its extension (or path) 'MyImage' IEM_FilePath Path of the file 'C:\Data\My Pictures\' IEM_ImageDimensions Dimensions and color depth of images (Nothing is shown for non-images) '1200 x 800' IEM_ImageDimAndSize Dimensions of images with the file size '1200 x 800, 3,900 KB' IEM_FileSize Size of the file on disk '3,900 KB' IEM_FileCreateDate The date that the file was created '7/5/13' IEM_FileCreateDateTime The date and time that the file was created '7/5/13 8:03am' IEM_FileCreateDateAndSize The create date of the file and its size '7/5/13, 3,900 KB' IEM_FileEditDate The date that the file was last edited '7/5/13' IEM_FileEditDateTime The date and time that the file was last edited '7/5/13 8:03am' IEM_FileEditDateAndSize The last edit date of the file and its size '7/5/13, 3,900 KB' IEM_FileType The ImageEn type for this file 'JPEG Image' IEM_FileExt The extension only of the file, e.g. JPEG for 'MyImage.jpeg' 'JPEG' IEM_ImageDict"xyz" Returns the value of key xyz from the 'Some Dictionary Value'
Example ImageEnMView1.ImageTopText[idx] := 'Top text'; ImageEnMView1.ImageInfoText[idx] := 'Info text'; ImageEnMView1.ImageBottomText[idx] := 'Bottom text'; // Display the filename and dimensions for each image for I := 0 to ImageEnMView1.ImageCount - 1 do begin ImageInfoText[I] := IEM_ImageDimensions; ImageBottomText[I] := IEM_Filename; end; Compatibility Notes Prior to v6.0.0, ImageTopText was a class that held properties for Font, Caption, etc. This was simplified in v6.0.0. ImageTopText is now only a widestring that carries the caption for a cell. So code that was previously: ImageTopText[idx].Caption := 'Abc'; Is now: ImageTopText[idx] := 'Abc'; To set the font of the text, use . and now control the background for all cells, and allows you to change the truncation. These properties affect all cells, so to customize the styling of a particular cell use the event. See Also - !!} function TImageEnMView.GetImageTopText(idx: integer): WideString; begin result := ''; if (idx >= 0) and (idx < fIEMBitmap.Count) then result := fIEMBitmap.GetImageInfo( idx ).TopText; end; {!! TImageEnMView.ImageBottomText Declaration property ImageBottomText[idx: Integer]: WideString; Description Use ImageBottomText to specify custom text to appear below the thumbnail of index, idx. The default bottom text is specified by but you can override this for a specific thumbnail by setting a value for ImageBottomText. Notes: - The font style is set by . But you can customize it for specific thumbnails using the event. - will be adjusted to fit the text. - Other text fields that can be set are: and You can optionally specify the following constants: Value Displays Example IEM_Filename Name of the file 'MyImage.jpg' IEM_FilenameNoExt Name of the file without its extension (or path) 'MyImage' IEM_FilePath Path of the file 'C:\Data\My Pictures\' IEM_ImageDimensions Dimensions and color depth of images (Nothing is shown for non-images) '1200 x 800' IEM_ImageDimAndSize Dimensions of images with the file size '1200 x 800, 3,900 KB' IEM_FileSize Size of the file on disk '3,900 KB' IEM_FileCreateDate The date that the file was created '7/5/13' IEM_FileCreateDateTime The date and time that the file was created '7/5/13 8:03am' IEM_FileCreateDateAndSize The create date of the file and its size '7/5/13, 3,900 KB' IEM_FileEditDate The date that the file was last edited '7/5/13' IEM_FileEditDateTime The date and time that the file was last edited '7/5/13 8:03am' IEM_FileEditDateAndSize The last edit date of the file and its size '7/5/13, 3,900 KB' IEM_FileType The ImageEn type for this file 'JPEG Image' IEM_FileExt The extension only of the file, e.g. JPEG for 'MyImage.jpeg' 'JPEG' IEM_ImageDict"xyz" Returns the value of key xyz from the 'Some Dictionary Value'
Example ImageEnMView1.ImageTopText[idx] := 'Top text'; ImageEnMView1.ImageInfoText[idx] := 'Info text'; ImageEnMView1.ImageBottomText[idx] := 'Bottom text'; // Display the filename and dimensions for each image for I := 0 to ImageEnMView1.ImageCount - 1 do begin ImageInfoText[I] := IEM_ImageDimensions; ImageBottomText[I] := IEM_Filename; end; Compatibility Notes Prior to v6.0.0, ImageBottomText was a class that held properties for Font, Caption, etc. This was simplified in v6.0.0. ImageBottomText is now only a widestring that carries the caption for a cell. So code that was previously: ImageBottomText[idx].Caption := 'Abc'; Is now: ImageBottomText[idx] := 'Abc'; To set the font of the text, use . and now control the background for all cells, and allows you to change the truncation. These properties affect all cells, so to customize the styling of a particular cell use the event. See Also - !!} function TImageEnMView.GetImageBottomText(idx: integer): WideString; begin result := ''; if (idx >= 0) and (idx < fIEMBitmap.Count) then result := fIEMBitmap.GetImageInfo( idx ).BottomText; end; {!! TImageEnMView.ImageInfoText Declaration property ImageInfoText[idx: Integer]: WideString; Description Use ImageInfoText to specify custom text to appear directly below the thumbnail of index, idx (above ). The default info text is specified by but you can override this for a specific thumbnail by setting a value for ImageInfoText. Notes: - The font style is set by . But you can customize it for specific thumbnails using the event. - Other text fields that can be set are: and You can optionally specify the following constants: Value Displays Example IEM_Filename Name of the file 'MyImage.jpg' IEM_FilenameNoExt Name of the file without its extension (or path) 'MyImage' IEM_FilePath Path of the file 'C:\Data\My Pictures\' IEM_ImageDimensions Dimensions and color depth of images (Nothing is shown for non-images) '1200 x 800' IEM_ImageDimAndSize Dimensions of images with the file size '1200 x 800, 3,900 KB' IEM_FileSize Size of the file on disk '3,900 KB' IEM_FileCreateDate The date that the file was created '7/5/13' IEM_FileCreateDateTime The date and time that the file was created '7/5/13 8:03am' IEM_FileCreateDateAndSize The create date of the file and its size '7/5/13, 3,900 KB' IEM_FileEditDate The date that the file was last edited '7/5/13' IEM_FileEditDateTime The date and time that the file was last edited '7/5/13 8:03am' IEM_FileEditDateAndSize The last edit date of the file and its size '7/5/13, 3,900 KB' IEM_FileType The ImageEn type for this file 'JPEG Image' IEM_FileExt The extension only of the file, e.g. JPEG for 'MyImage.jpeg' 'JPEG' IEM_ImageDict"xyz" Returns the value of key xyz from the 'Some Dictionary Value'
Example ImageEnMView1.ImageTopText[idx] := 'Top text'; ImageEnMView1.ImageInfoText[idx] := 'Info text'; ImageEnMView1.ImageBottomText[idx] := 'Bottom text'; // Display the filename and dimensions for each image for I := 0 to ImageEnMView1.ImageCount - 1 do begin ImageInfoText[I] := IEM_ImageDimensions; ImageBottomText[I] := IEM_Filename; end; Compatibility Notes Prior to v6.0.0, ImageInfoText was a class that held properties for Font, Caption, etc. This was simplified in v6.0.0. ImageInfoText is now only a widestring that carries the caption for a cell. So code that was previously: ImageInfoText[idx].Caption := 'Abc'; Is now: ImageInfoText[idx] := 'Abc'; To set the font of the text, use . and now control the background for all cells, and allows you to change the truncation. These properties affect all cells, so to customize the styling of a particular cell use the event. See Also - !!} function TImageEnMView.GetImageInfoText(idx: integer): WideString; begin result := ''; if (idx >= 0) and (idx < fIEMBitmap.Count) then result := fIEMBitmap.GetImageInfo( idx ).InfoText; end; // set name='' procedure TImageEnMView.SetImageID(idx, v: integer); begin if (idx >= 0) and (idx < fIEMBitmap.Count) then with fIEMBitmap.GetImageInfo( idx ) do begin ID := v; Filename := ''; end; end; procedure TImageEnMView.SetImageTag(idx, v: integer); begin fIEMBitmap.ImageTag[ idx ] := v; end; {!! TImageEnMView.ImageTag Declaration property ImageTag[idx: Integer]: integer; Description Associates a numeric integer value with the image, idx. Note: - This property is not used by TImageEnMView in any way and is provided for custom use (similar to the Tag property of components). - The value is not loaded/saved from file and streams, or copied/pasted to clipboard. !!} function TImageEnMView.GetImageTag(idx: integer): integer; begin result := fIEMBitmap.ImageTag[ idx ]; end; procedure TImageEnMView.SetImageUserPointer(idx: Integer; v: pointer); begin fIEMBitmap.ImageUserPointer[ idx ] := v; end; {!! TImageEnMView.ImageUserPointer Declaration property ImageUserPointer[idx: Integer]: pointer; Description ImageUserPointer associates a pointer with image, idx. Note: - This property is not used by TImageEnMView in any way and is provided for custom use. - The value is not loaded/saved from file and streams, or copied/pasted to clipboard. Example // Store a description and record ID when adding files to our grid type TFileDataRecord = Record Description : string[100]; RecordID : Byte; end; Procedure TfMain.AddImageToGrid(const sFilename, sDescription : string; iRecordID : Integer); var POurRecord : ^TFileDataRecord; iNewIndex: Integer; begin // Allocate memory GetMem(POurRecord, SizeOf(TFileDataRecord)); iNewIndex := ImageEnMView1.AppendImage(sFilename); POurRecord.Description := sDescription; POurRecord.RecordID := iRecordID; ImageEnMView1.ImageUserPointer[iNewIndex] := POurRecord; end; // When removing items from the ImageEnMView1 deallocate the memory... Procedure TfMain.ClearGrid; begin for i := 0 to ImageEnMView1.ImageCount - 1 do FreeMem(ImageEnMView1.ImageUserPointer[i]); ImageEnMView1.Clear; end; !!} function TImageEnMView.GetImageUserPointer(idx: Integer): pointer; begin result := fIEMBitmap.ImageUserPointer[ idx ]; end; {!! TImageEnMView.ImageID Declaration property ImageID[idx: Integer]: integer; Description ImageID associates a numeric ID with image, idx. It is mainly used to allow dynamic loading of content into a TImageEnMView. This ID is returned in the and events. Note: is not valid when using ImageID. Example // Display all bitmaps in a TImageList in a TImageEnView procedure TMyForm.FormShow(Sender: TObject); var I : Integer; begin ImageEnMView1.Clear; // Add an ID for every bitmap in a TImageList for I := 0 to ImageList1.Count - 1 do begin ImageEnMView1.InsertImage(I); ImageEnMView1.ImageID[I] := I; end; end; procedure TMyForm.ImageEnMViewOnImageIDRequest(Sender: TObject; ID: integer; var Bitmap: TBitmap); begin // Retrieve the image from a TImageList Bitmap := TBitmap.create; ImageList1.GetBitmap(ID, Bitmap); end; !!} function TImageEnMView.GetImageID(idx: integer): integer; begin result := -1; if (idx >= 0) and (idx < fIEMBitmap.Count) then result := fIEMBitmap.GetImageInfo( idx ).ID; end; procedure TImageEnMView.SetImageBackground(idx: integer; v: TColor); begin if (idx >= 0) and (idx < fIEMBitmap.Count) then begin fIEMBitmap.ImageBackground[ idx ] := v; ClearImageCache(idx); UpdateEx(false); end; end; {!! TImageEnMView.ImageBackground Declaration property ImageBackground: TColor; Description Specifies the color of the area between images. !!} function TImageEnMView.GetImageBackground(idx: integer): TColor; begin result := fIEMBitmap.ImageBackground[ idx ]; end; procedure TImageEnMView.SetImageDelayTime(idx: integer; v: Double); begin fIEMBitmap.ImageDelayTime[ idx ] := v; end; {!! TImageEnMView.ImageDelayTime Declaration property ImageDelayTime[idx: Integer]: Double; Description ImageDelayTime is the time in milliseconds the image, idx, will be shown during playback ( = True). !!} function TImageEnMView.GetImageDelayTime(idx: integer): Double; begin result := fIEMBitmap.ImageDelayTime[ idx ]; end; {!! TImageEnMView.ThumbWidth Declaration property ThumbWidth: integer; Description Specifies the width of the thumbnails displayed in the TImageEnView. Note: This is the width of the thumbnail frame (when the is iemsFlat). The thumbnail image itself will be ThumbWidth less 2 x . See for actual display size. Use if you want to set the display size of the image itself. See Also - - - !!} procedure TImageEnMView.SetThumbWidth(v: integer); begin fThumbWidth := v; ClearCache; Update; end; {!! TImageEnMView.ThumbHeight Declaration property ThumbHeight: integer; Description Specifies the height of the thumbnails displayed in the TImageEnView. Note: This is the height of the thumbnail frame (when the is iemsFlat). The thumbnail image itself will be ThumbHeight less and . See for actual display size. Use if you want to set the display size of the image itself. See Also - - - !!} procedure TImageEnMView.SetThumbHeight(v: integer); begin fThumbHeight := v; ClearCache; Update; end; {!! TImageEnMView.ThumbSizeInfo Declaration function ThumbSizeInfo(Data: ): TPoint; Description Returns internal information about the current displayed size of thumbnail cells in the TImageEnView. Data can be one of: Value Description itsImage Returns the size of the thumbnail image as displayed itsCell Returns the size of the thumbnail cell (image, text and cell border) itsOuter Returns the size of the thumbnail cell and its external spacing (image, text, cell border and horizontal/vertical border)
It takes into account: -
and - - , and - and !!} { Here is a filled TImageEnMView: _[o]_[o]_[o]_[o]_ _[o]_[o]_[o]_[o]_ _[o]_[o]_[o]_[o]_ _[o]_[o]_[o]_[o]_ itsImage: Just the thumbnail "o" itsCell: Just the thumb cell "[o]" itsOuter: Cell and the spacing around it "_[o]_" } function TImageEnMView.ThumbSizeInfo(Data: TIEThumbSizeType): TPoint; var iWidth, iHeight: Integer; ActUpperGap, ActBottomGap: Integer; begin // WIDTH iWidth := trunc( fThumbWidth * fZoom / 100.0 ); if Data = itsImage then Dec( iWidth, 2 * fSideGap ); if Data in [ itsCell, itsOuter ] then Inc( iWidth, CurrentTextBlockWidth ); if Data = itsOuter then Inc( iWidth, fHorizBorder ); // HEIGHT iHeight := trunc( fThumbHeight * fZoom / 100.0 ); if Data = itsImage then begin // UPPER ActUpperGap := fUpperGap; if fShowText and ( CurrentTextBlockWidth = 0 ) then begin if fTopTextHeight = CALCULATE_NOW then UpdateTopTextHeight( True ); {$ifdef IEIncludeDeprecatedInV6} // Legacy Handling - Prior to v6.2.2 UpperGap was enlarged to handle text height if fUpperGap > 12 then ActUpperGap := fUpperGap else {$endif} ActUpperGap := fUpperGap + fTopTextHeight end; // LOWER ActBottomGap := fBottomGap; if fShowText and ( CurrentTextBlockWidth = 0 ) then begin if fBottomTextHeight = CALCULATE_NOW then UpdateBottomTextHeight( True ); {$ifdef IEIncludeDeprecatedInV6} // Legacy Handling - Prior to v6.2.2 UpperGap was enlarged to handle text height if fBottomGap > 12 then ActBottomGap := fBottomGap else {$endif} ActBottomGap := fBottomGap + fBottomTextHeight end; Dec( iHeight, ActUpperGap + ActBottomGap ); end; if Data = itsOuter then Inc( iHeight, fVertBorder ); Result := Point( iWidth, iHeight ); end; {!! TImageEnMView.SetThumbnailSize Declaration procedure SetThumbnailSize(width, height: Integer); Description Sets and in one step. If SetImageSize is false, then the specified size is for thumbnail area (including border and text space). Otherwise, if true, it specifies the display size of the image only. Declaration // Set thumbnails to 200, 150 ImageEnMView1.SetThumbnailSize( 200, 150 ); // Set so images in the grid are shown at exactly 200, 150 ImageEnMView1.SetThumbnailSize( 200, 150, True ); See Also - - - !!} procedure TImageEnMView.SetThumbnailSize(width, height: Integer; SetImageSize: Boolean = False); var horzGap, vertGap: Integer; imgSize: TPoint; begin horzGap := 0; vertGap := 0; if SetImageSize then begin imgSize := ThumbSizeInfo( itsImage ); horzGap := trunc( fThumbWidth * fZoom / 100.0 ) - imgSize.X; vertGap := trunc( fThumbHeight * fZoom / 100.0 ) - imgSize.Y; end; fThumbWidth := width + horzGap; fThumbHeight := height + vertGap; ClearCache; Update; end; {!! TImageEnMView.Zoom Declaration property Zoom: Double; Description Enlarge or reduce the size of the thumbnail display. Note: This property is only recomended for handling of temporary display enlargement. It is better to set the size of the thumbnails. See Also - - !!} procedure TImageEnMView.SetZoom(value: double); begin fCurrentGridWidth := fGridWidth; if Value <> 100 then fCurrentGridWidth := CalcGridWidth(); SetViewXY(round(ViewX / (fZoom / 100.0) * (value / 100.0)), round(ViewY / (fZoom / 100.0) * (value / 100.0))); fZoom := value; ClearCache(); Update(); end; {!! TImageEnMView.ImageCount Declaration property ImageCount: integer; (Read-only) Description Returns the number of images stored in the TImageEnMView component. Example // Display the filename and dimensions for each image for I := 0 to ImageEnMView1.ImageCount - 1 do begin ImageInfoText[I] := IEM_ImageDimensions; ImageBottomText[I] := IEM_Filename; end; !!} function TImageEnMView.GetImageCount: integer; begin result := fIEMBitmap.Count; end; {!! TImageEnMView.HorizBorder Declaration property HorizBorder: integer; Description Specifies the horizontal distance between thumbnail cells. See also: !!} procedure TImageEnMView.SetHorizBorder(v: integer); begin fHorizBorder := v; Update; end; {!! TImageEnMView.VertBorder Declaration property VertBorder: integer; Description Specifies the vertical distance between thumbnail cells. See also: !!} procedure TImageEnMView.SetVertBorder(v: integer); begin fVertBorder := v; Update; end; // The top-left point of the top-left thumbnail function TImageEnMView.ThumbnailsOrigin : TPoint; const Header_Gap = 4; // Space between header and first item var iLeft, iTop: Integer; iColCount: Integer; iHeadHeight: Integer; begin // LEFT POSITION iLeft := 0; if (fDisplayMode = mdGrid) and (ietxCenterThumbnailColumn in fThumbnailOptionsEx) then begin if fCurrentGridWidth = 1 then iLeft := ( ClientWidth - ThumbSizeInfo( itsCell ).X ) div 2 else if fCurrentGridWidth <> 0 then begin iColCount := fCurrentGridWidth; if iColCount = -1 then iColCount := CalcGridWidth(); iLeft := imax(0, (ClientWidth - ( iColCount * ThumbSizeInfo( itsOuter ).X )) div 2); end; end; // TOP POSITION iTop := 0; // If in columns mode add the height of the fixed row + margin. iHeadHeight := CurrentHeaderRowHeight; if iHeadHeight > 0 then inc( iTop, iHeadHeight + Header_Gap ); // Center vertically if we have only a single row if (fDisplayMode = mdGrid) and (ietxCenterThumbnailColumn in fThumbnailOptionsEx) and (fCurrentGridWidth = 0) then iTop := ( ClientHeight - ThumbSizeInfo( itsCell ).Y ) div 2; Result := Point( iLeft, iTop ); end; // recalc x, y image positions // update fVWidth and fVHeight procedure TImageEnMView.UpdateCoords; var q, xx, yy, gw: integer; begin fCurrentGridWidth := fGridWidth; if fZoom <> 100 then fCurrentGridWidth := CalcGridWidth(); gw := CalcGridWidth(); xx := 0; yy := 0; fVWidth := 0; fVHeight := 0; for q := 0 to fIEMBitmap.Count - 1 do begin with fIEMBitmap.GetImageInfo( q ) do begin if BiDiModeIsRTL() then x := ( gw - xx - 1 ) * ThumbSizeInfo( itsOuter ).X else x := xx * ThumbSizeInfo( itsOuter ).X; y := yy * ThumbSizeInfo( itsOuter ).Y; if fDisplayMode = mdGrid then begin inc( x, imax( ThumbnailsOrigin.X, fHorizBorder )); inc( y, imax( ThumbnailsOrigin.Y, fVertBorder )); end; row := yy; col := xx; if x > fVWidth then fVWidth := x; if y > fVHeight then fVHeight := y; end; // calculates next position inc(xx); if ( fDisplayMode = mdSingle ) or ( xx = gw ) then begin // horizontal limit, clear column, go to next row xx := 0; inc(yy); if fDisplayMode = mdSingle then begin // vertical limit, go back to top-left side yy := 0; xx := 0; end; end; end; inc( fVWidth, ThumbSizeInfo( itsOuter ).X ); inc( fVHeight, ThumbSizeInfo( itsOuter ).Y ); end; {!! TImageEnMView.InsertImage Declaration procedure InsertImage(idx: integer); procedure InsertImage(Idx : integer; Stream : TStream); procedure InsertImage(Idx : integer; Bitmap : ); procedure InsertImage(Idx : integer; Bitmap : TBitmap); procedure InsertImage(Idx : integer; Width, Height : integer; PixelFormat : = ie24RGB); procedure InsertImage(Idx : integer; const FileName : string); procedure InsertImage(const FileName: String; LoadOnDemand : boolean; DefaultTopText : = iedtNone; DefaultInfoText : = iedtNone; DefaultBottomText : = iedtFilename; bSelectIt : Boolean = true); Description Inserts a new image at position, idx (0 is the first). Note: First overload, InsertImage(idx: integer), doesn't create the bitmap. The parameters for the final overload are as follows: Parameter Description Filename A file or folder available on the system, or an HTTP or FTP link to a remote file LoadOnDemand If True, the image will not be loaded from disk until it is displayed (i.e. when it is scrolled into view) DefaultTopText Specify the text that is applied to DefaultInfoText Specify the text that is applied to DefaultBottomText Specify the text that is applied to (defaults to the filename) bSelectIt The new image will be selected in the control
Examples ImageEnView1.IO.LoadFromFile('C:\000.tif'); ImageEnMView1.InsertImage(0); ImageEnMView1.SetImage(0, ImageEnView1.Bitmap); // Which is the same as... ImageEnMView1.InsertImage(0, 'C:\000.tif'); // Insert 256 x 256 bitmap ImageEnMView1.InsertImage(0, 256, 256, ie24RGB); // Insert a file from the web ImageEnMView1.InsertImage(0, 'http://www.imageen.com/graphics/imageen.gif'); // Show the first ten frames of a video file for I := 0 to 9 do ImageEnMView1.InsertImage( I, 'D:\Temp\Cement.avi' + IEM_Path_Index_Delimiter + IntToStr( I * 10 )); See Also - - !!} procedure TImageEnMView.InsertImage(idx: integer); begin if IEMBitmap_IsTIEDBMultiBitmap then begin fIEMBitmap.InsertImage( Idx ); exit; end; InsertImageEx(idx, imsAlways); if assigned( fOnImageAdded ) then fOnImageAdded( self, idx ); end; procedure TImageEnMView.InsertImage(Idx : integer; Stream : TStream); begin if IEMBitmap_IsTIEDBMultiBitmap then begin fIEMBitmap.InsertImage( Idx, Stream ); exit; end; InsertImageEx(idx, imsAlways); SetImageFromStream(Idx, Stream); if assigned( fOnImageAdded ) then fOnImageAdded( self, idx ); if assigned(fAnimation) then fAnimation.RestartAnimation; end; procedure TImageEnMView.InsertImage(Idx : integer; Bitmap : TIEBitmap); begin if IEMBitmap_IsTIEDBMultiBitmap then begin fIEMBitmap.InsertImage( Idx, Bitmap ); exit; end; InsertImageEx(idx, imsAlways); SetImage(Idx, Bitmap); if assigned( fOnImageAdded ) then fOnImageAdded( self, idx ); if assigned(fAnimation) then fAnimation.RestartAnimation; end; procedure TImageEnMView.InsertImage(Idx : integer; Bitmap : TBitmap); begin if IEMBitmap_IsTIEDBMultiBitmap then begin fIEMBitmap.InsertImage( Idx, Bitmap ); exit; end; InsertImageEx(idx, imsAlways); SetImage(Idx, Bitmap); if assigned( fOnImageAdded ) then fOnImageAdded( self, idx ); if assigned(fAnimation) then fAnimation.RestartAnimation; end; procedure TImageEnMView.InsertImage(Idx : integer; Width, Height : integer; PixelFormat : TIEPixelFormat); var temp: TIEBitmap; begin if IEMBitmap_IsTIEDBMultiBitmap then begin fIEMBitmap.InsertImage( Idx, Width, Height, PixelFormat ); exit; end; InsertImageEx(idx, imsAlways); temp := TIEBitmap.Create; try temp.Allocate(Width, Height, PixelFormat); temp.Fill(clBlack); SetImage(Idx, temp); if assigned( fOnImageAdded ) then fOnImageAdded( self, idx ); if assigned(fAnimation) then fAnimation.RestartAnimation; finally temp.free; end; end; procedure TImageEnMView.InsertImage(Idx : integer; const FileName : string); begin if IEMBitmap_IsTIEDBMultiBitmap then begin fIEMBitmap.InsertImage( Idx, FileName ); exit; end; InsertImageEx(idx, imsAlways); // Load on demand if Pos(IEM_Path_Index_Delimiter, Filename) > 0 then ImageFileName[ Idx ] := FileName else SetImageFromFile(Idx, FileName); if assigned( fOnImageAdded ) then fOnImageAdded( self, idx ); if assigned(fAnimation) then fAnimation.RestartAnimation; end; function StripShortcutExt(const sFilename : string) : string; const Windows_Shortcut_File_Ext = '.LNK'; var iPos: Integer; begin Result := sFilename; iPos := Pos(Windows_Shortcut_File_Ext, uppercase(Result)); if (iPos > 0) and (iPos = Length(Result) - Length(Windows_Shortcut_File_Ext) + 1) then SetLength(Result, iPos - 1); end; function GetDisplayName(const sFilename : string; bStripShortcutExt : Boolean = False) : string; begin Result := IEExtractFileNameW( sFileName ); if bStripShortcutExt then Result := StripShortcutExt( Result ); if Result = '' then Result := sFileName // Drive? {$ifdef VIDEO_THUMBNAILS} else if SameText( Result, IEF_Drives_Folder ) then Result := IEGetMyComputerName; {$endif} end; function ConstToIEMDefaultText(const value: WideString) : TIEImageEnMViewDefaultText; begin Result := iedtNone; if (value = '') or (value[1] <> '$') then exit; if SameText(value, IEM_Filename) then Result := iedtFilename else if SameText(value, IEM_FilenameNoExt) then Result := iedtFilenameNoExt else if SameText(value, IEM_FilePath) then Result := iedtFilePath else if SameText(value, IEM_ImageDimensions) then Result := iedtImageDimensions else if SameText(value, IEM_ImageDimAndSize) then Result := iedtImageDimAndSize else if SameText(value, IEM_FileSize) then Result := iedtFileSize else if SameText(value, IEM_FileCreateDate) then Result := iedtFileCreateDate else if SameText(value, IEM_FileCreateDateTime) then Result := iedtFileCreateDateTime else if SameText(value, IEM_FileCreateDateAndSize) then Result := iedtFileCreateDateAndSize else if SameText(value, IEM_FileEditDate) then Result := iedtFileEditDate else if SameText(value, IEM_FileEditDateTime) then Result := iedtFileEditDateTime else if SameText(value, IEM_FileEditDateAndSize) then Result := iedtFileEditDateAndSize else if SameText(value, IEM_FileType) then Result := iedtFileType else if SameText(value, IEM_FileExt) then Result := iedtFileExt; end; function IEMDefaultTextToConst(DefaultText : TIEImageEnMViewDefaultText) : WideString; begin Result := ''; case DefaultText of iedtFilename : Result := IEM_Filename ; iedtFilenameNoExt : Result := IEM_FilenameNoExt ; iedtFilePath : Result := IEM_FilePath ; iedtImageDimensions : Result := IEM_ImageDimensions ; iedtImageDimAndSize : Result := IEM_ImageDimAndSize ; iedtFileSize : Result := IEM_FileSize ; iedtFileCreateDate : Result := IEM_FileCreateDate ; iedtFileCreateDateTime : Result := IEM_FileCreateDateTime ; iedtFileCreateDateAndSize : Result := IEM_FileCreateDateAndSize; iedtFileEditDate : Result := IEM_FileEditDate ; iedtFileEditDateTime : Result := IEM_FileEditDateTime ; iedtFileEditDateAndSize : Result := IEM_FileEditDateAndSize ; iedtFileType : Result := IEM_FileType ; iedtFileExt : Result := IEM_FileExt ; end; end; procedure TImageEnMView.InsertImage(Idx : integer; const FileName : string; LoadOnDemand : boolean; DefaultTopText : TIEImageEnMViewDefaultText = iedtNone; DefaultInfoText : TIEImageEnMViewDefaultText = iedtNone; DefaultBottomText : TIEImageEnMViewDefaultText = iedtFilename; bSelectIt : Boolean = true); begin if bSelectIt then InsertImageEx(Idx, imsAlways) else InsertImageEx(Idx, imsAuto); ImageFileName[idx] := FileName; if LoadOnDemand = False then SetImageFromFile(Idx, FileName); if DefaultTopText = iedtFilename then ImageTopText[idx] := GetDisplayName( FileName, True ) else ImageTopText[idx] := IEMDefaultTextToConst(DefaultTopText); if DefaultInfoText = iedtFilename then ImageInfoText[idx] := GetDisplayName( FileName, True ) else ImageInfoText[idx] := IEMDefaultTextToConst(DefaultInfoText); if DefaultBottomText = iedtFilename then ImageBottomText[idx] := GetDisplayName( FileName, True ) else ImageBottomText[idx] := IEMDefaultTextToConst(DefaultBottomText); if assigned(fAnimation) then fAnimation.RestartAnimation; end; {!! TImageEnMView.InsertImageEx Declaration procedure InsertImageEx(idx: integer; SelectMode : = imsNever); Description InsertImageEx inserts a new image in position, idx (0 is the first). Unlike , InsertImageEx doesn't create the bitmap. Also, you can configure whether the image is selected. Examples ImageEnView1.IO.LoadFromFile('000.tif'); ImageEnMView1.InsertImageEx(0); ImageEnMView1.SetImage(0, ImageEnView1.Bitmap); // Append an image without selecting it ImageEnMView1.InsertImageEx( ImageEnMView1.ImageCount, imsNever ); See Also - - - !!} // Insert a new image // idx is the index where to insert the new image // If idx is equal to ImageCount it is added at the end // The bitmap (Image[]) is created as "nil" // The bitmap position is based on fHorizImages and fVertImages values // calls Update // The image is not selected // disable player procedure TImageEnMView.InsertImageEx(idx: integer; SelectMode : TIEMSelectMode = imsNever); var bAppend: Boolean; begin SetPlaying(false); fIEMBitmap.InsertImage( idx ); if ( SelectMode = imsAlways ) or (( SelectMode = imsAuto ) and (fSelectedItem < 0 )) then SetSelectedItemNU(idx); bAppend := idx >= GetImageCount; if ( SelectMode <> imsNever ) and bAppend then fPriorHSIDX := fSelectedItem; if assigned(fOnCreateImage) then fOnCreateImage(self, idx); if ( fLockPaint = 0 ) and ( fLockUpdate = 0 ) and assigned( fAnimation ) then fAnimation.InsertImage(idx); CallBitmapChangeEvents; fCheckedCount := -1; UpdateEx(false, ( SelectMode <> imsNever ) and fSelectedImageAlwaysVisible ); end; {!! TImageEnMView.InsertTransitionFrames Declaration procedure InsertTransitionFrames(Idx : integer; iFrameCount : integer; Effect : ; iWidth : Integer = -1; iHeight : Integer = -1; BackgroundColor : TColor = -1; ResamplingFilter: = rfFastLinear); Description Create a series of transition frames from the image at Idx - 1 to the image at Idx (and insert them at position Idx). If Idx = 0 then the transition is from a blank frame to the first image. If Idx = ImageCount then the transition is from the last image to a blank frame. Parameter Description Idx The insertion position iFrameCount The number of frames to insert Effect The desired transition effect iWidth, iHeight The size to create the transition bitmaps. If either of these are -1 then the size will be the larger of the two images in each dimension. Aspect Ratios will be maintained and any non-image area will be filled with BackgroundColor. BackgroundColor The color that will be used for blank frames or non-image area (if -1 then is used) ResamplingFilter The algorithm that is used to improve quality when resizing images
Notes: - Does not call - Use if you need to create frames for an iettPanZoom transition - Cannot be used if a is attached to the control Demo Demos\Multi\CreateTransitionFrames\CreateTransitionFrames.dpr Example // Create ten frames that use a cross dissolve transition from image 5 to image 6 ImageEnMView1.InsertTransitionFrames(6, 10, iettCrossDissolve); See Also - !!} procedure TImageEnMView.InsertTransitionFrames(Idx : integer; iFrameCount : integer; Effect : TIETransitionType; iWidth : Integer = -1; iHeight : Integer = -1; BackgroundColor : TColor = -1; ResamplingFilter: TResampleFilter = rfFastLinear); begin if IEMBitmap_IsTIEDBMultiBitmap then raise EIEException.create('Not available when attached to TIEDBMultiBitmap'); LockPaint; try TIEMultiBitmap( fIEMBitmap ).InsertTransitionFrames(Idx, iFrameCount, Effect, iWidth, iHeight, BackgroundColor, ResamplingFilter); finally UnLockPaint; Update; end; end; {!! TImageEnMView.InsertTransitionFramesEx Declaration procedure InsertTransitionFramesEx(Idx : Integer; iFrameCount : Integer; Effect : ; StartRect, EndRect : TRect; RectMaintainAspectRatio : boolean = True; iWidth : Integer = -1; iHeight : Integer = -1; bStretchSmall : Boolean = False; BackgroundColor : TColor = -1; ResamplingFilter : ; Smoothing: Integer = 96; Timing : = iettLinear); Description This is an extended version of that includes more parameters and is primarily used when you need to create a series of frames that show a Pan Zoom from StartRect to EndRect for the image specified at Idx - 1. Parameter Description Idx The insertion position iFrameCount The number of frames to insert Effect The desired transition effect StartRect When using an iettPanZoom effect this is the portion of the image that is shown at the start EndRect When using an iettPanZoom effect this is the portion of the image that is shown at the end RectMaintainAspectRatio ImageEn will ensure that the starting and ending rects are automatically adjusted to ensure the resultant image has the correct aspect ratio (iettPanZoom only) iWidth, iHeight The size to create the transition bitmaps. If either of these are -1 then the size will be the larger of the two images in each dimension. Aspect Ratios will be maintained and any non-image area will be filled with BackgroundColor. bStretchSmall If the images are smaller than the transition bitmap size (iWidth x iHeight) should they be stretched to fit (which can lead to distortion). BackgroundColor The color that will be used for blank frames or non-image area (if -1 then is used) ResamplingFilter The algorithm that is used to improve quality when resizing images Timing The rate at which the transition progresses Smoothing In order to reduce the "jumpiness" of pan zoom effects, transition frames are alpha blended. A low value will improve smoothness, but increase blurriness. A high value will improve clarity, but increase jumpiness. Typical range is 64 - 196. 255 means no alpha blending
Notes: - Does not call - Cannot be used if a is attached to the control Example // Create ten Pan Zoom frames for the image at index 5 // Top Left corner of image StartingRect := Rect(0, 0, ImageEnMView1.ImageWidth[5] div 4, ImageEnMView1.ImageHeight[5] div 4); // Bottom right corner of image EndingRect := Rect(MulDiv(ImageEnMView1.ImageWidth[5], 3, 4), MulDiv(ImageEnMView1.ImageHeight[5], 3, 4), ImageEnMView1.ImageWidth[5], ImageEnMView1.ImageHeight[5]); // Create frames ImageEnMView1.InsertTransitionFramesEx(5, 10, iettPanZoom, StartRect, EndRect); See Also - !!} procedure TImageEnMView.InsertTransitionFramesEx(Idx : integer; iFrameCount : Integer; Effect : TIETransitionType; StartRect, EndRect : TRect; RectMaintainAspectRatio : boolean = True; iWidth : Integer = -1; iHeight : Integer = -1; bStretchSmall : Boolean = False; BackgroundColor : TColor = -1; ResamplingFilter: TResampleFilter = rfFastLinear; Smoothing: Integer = 96; Timing : TIETransitionTiming = iettLinear); begin if IEMBitmap_IsTIEDBMultiBitmap then raise EIEException.create('Not available when attached to TIEDBMultiBitmap'); LockPaint; try TIEMultiBitmap( fIEMBitmap ).InsertTransitionFramesEx( Idx, iFrameCount, Effect, StartRect, EndRect, RectMaintainAspectRatio, iWidth, iHeight, bStretchSmall, BackgroundColor, ResamplingFilter, Smoothing, Timing); finally UnLockPaint; Update; end; end; {!! TImageEnMView.AppendImage Declaration function AppendImage: Integer; function AppendImage(Stream: TStream): integer; function AppendImage(Bitmap: ): integer; function AppendImage(Bitmap : TBitmap): integer; function AppendImage(Width, Height: Integer; PixelFormat: = ie24RGB): Integer; function AppendImage(const FileName: String): integer; function AppendImage(const FileName: String; LoadOnDemand : boolean; DefaultTopText : = iedtNone; DefaultInfoText : = iedtNone; DefaultBottomText : = iedtFilename; bSelectIt : Boolean = true): integer; Description AppendImage appends a new image at last position in the list and returns the new image position. Note: First overload of AppendImage doesn't create the bitmap. Others load image from a file or a stream. The parameters for the final overload are as follows: Parameter Description Filename A file or folder available on the system, or an HTTP or FTP link to a remote file. You can load a particular frame from a multi-frame image or video by delimiting it with IEM_Path_Index_Delimiter LoadOnDemand If True, the image will not be loaded from disk until it is displayed (i.e. when it is scrolled into view) DefaultTopText Specify the text that is applied to DefaultInfoText Specify the text that is applied to DefaultBottomText Specify the text that is applied to (defaults to the filename) bSelectIt The new image will be selected in the control
Examples ImageEnView1.IO.LoadFromFile( 'C:\MyImage.tif' ); idx := ImageEnMView1.AppendImage; ImageEnMView1.SetImage( idx, ImageEnView1.Bitmap ); // Which is the same as... ImageEnMView1.AppendImage( 'C:\MyImage.tif' ); // Load the fifth image of MyImage.tif ImageEnMView1.AppendImage( 'C:\MyImage.tif' + IEM_Path_Index_Delimiter + 4 ); // Append 256 x 256 bitmap ImageEnMView1.AppendImage( 256, 256, ie24RGB ); // Append a file from the web ImageEnMView1.AppendImage( 'http://www.imageen.com/graphics/imageen.gif' ); // Show ten frames of a video file for I := 0 to 9 do ImageEnMView1.AppendImage( 'D:\Temp\Cement.avi' + IEM_Path_Index_Delimiter + IntToStr( I * 10 )); // Append all pages of a TIFF to the current content iPageCount := EnumTIFFIm( sFileName ); for I := 0 to iPageCount - 1 do ImageEnMView1.AppendImage( sFileName + IEM_Path_Index_Delimiter + IntToStr( I )); See Also - - !!} function TImageEnMView.AppendImage(): integer; begin result := fIEMBitmap.Count; InsertImage( result ); end; function TImageEnMView.AppendImage(Stream: TStream): integer; begin result := fIEMBitmap.Count; InsertImage(Result, Stream); end; function TImageEnMView.AppendImage(Bitmap: TIEBitmap): integer; begin result := fIEMBitmap.Count; InsertImage(Result, Bitmap); end; function TImageEnMView.AppendImage(Bitmap : TBitmap): integer; begin result := fIEMBitmap.Count; InsertImage(Result, Bitmap); end; function TImageEnMView.AppendImage(Width, Height: Integer; PixelFormat: TIEPixelFormat): Integer; begin result := fIEMBitmap.Count; InsertImage(Result, Width, Height, PixelFormat); end; function TImageEnMView.AppendImage(const FileName: String): integer; begin result := fIEMBitmap.Count; InsertImage(result, FileName); end; function TImageEnMView.AppendImage(const FileName: String; LoadOnDemand : boolean; DefaultTopText : TIEImageEnMViewDefaultText = iedtNone; DefaultInfoText : TIEImageEnMViewDefaultText = iedtNone; DefaultBottomText : TIEImageEnMViewDefaultText = iedtFilename; bSelectIt : Boolean = true): integer; begin result := fIEMBitmap.Count; InsertImage(result, FileName, LoadOnDemand, DefaultTopText, DefaultInfoText, DefaultBottomText, bSelectIt); end; {$ifdef IEIncludeDeprecatedInV5} // Deprecated in 6.0.0 (2014-11-11) function TImageEnMView.AppendImage2(Width, Height: Integer; PixelFormat: TIEPixelFormat): Integer; begin result := AppendImage(Width, Height, PixelFormat); end; {$endif} {!! TImageEnMView.AppendSplit Declaration function AppendSplit(SourceGrid: ; cellWidth: Integer; cellHeight: Integer; maxCount: Integer = 0): Integer; Description Splits the source image into cells of the specified size and adds each cell to the TImageEnMView Result is the count of added images. Parameter Description SourceGrid Source bitmap containing cells to split. cellWidth Width of a cell. cellHeight Height of a cell. maxCount Maximum number of cells to add. 0 = all suitable cells.
!!} function TImageEnMView.AppendSplit(SourceGrid: TIEBitmap; cellWidth: Integer; cellHeight: Integer; maxCount: Integer): Integer; var x, y: Integer; idx: Integer; begin result := 0; y := 0; while y < SourceGrid.Height do begin x := 0; while x < SourceGrid.Width do begin idx := AppendImage; SetImageRect( idx, SourceGrid, x, y, x + cellWidth - 1, y + cellHeight - 1 ); inc(result); if (maxCount>0) and (maxCount=result) then exit; inc(x, cellWidth); end; inc(y, cellHeight); end; end; // Delete image idx // doesn't call Update // Return true if image correctly deleted // Disable playing // use bBatchProcessing = True if this is being called by DeleteAllImages function TImageEnMView.DeleteImageNU(idx: integer; bBatchProcessing : Boolean = False): boolean; var psel: integer; begin result := false; SetPlaying(false); if (idx >= 0) and (idx < fIEMBitmap.Count) then begin AbortImageLoading(idx); psel := fSelectedItem; if bBatchProcessing = False then DeselectNU; if assigned(fOnDestroyImage) then fOnDestroyImage(self, idx); if fIEMBitmap.GetImageInfo( idx ).image <> nil then ClearImageCache(idx); fIEMBitmap.DeleteImage( idx ); if bBatchProcessing = False then begin if (psel = idx) and (idx >= fIEMBitmap.Count) then SetSelectedItemNU(fIEMBitmap.Count - 1) else if psel > idx then SetSelectedItemNU(psel - 1) else SetSelectedItemNU(psel); if ( fLockPaint = 0 ) and ( fLockUpdate = 0 ) and assigned( fAnimation ) then fAnimation.DeleteImage(idx); end; CallBitmapChangeEvents; fCheckedCount := -1; result := true; end; end; procedure TImageEnMView.DeleteAllImages(); var idx: integer; begin SetPlaying(false); DeselectNU(); for idx := fIEMBitmap.Count - 1 downto 0 do DeleteImageNU(idx, True); fPriorHSIDX := 0; end; function ComparePointers(Item1, Item2: Pointer): Integer; begin result := NativeInt(Item1) - NativeInt(Item2); end; {!! TImageEnMView.DeleteSelectedImages Declaration procedure DeleteSelectedImages; Description Removes all selected images. !!} procedure TImageEnMView.DeleteSelectedImages; var q: integer; cp: array of integer; begin if DisplayMode = mdSingle then DeleteImageNU(VisibleFrame) else if EnableMultiSelect = False then DeleteImageNU(SelectedImage) else begin MultiSelectSortList; SetLength(cp, fMultiSelectedImages.Count); for q := 0 to fMultiSelectedImages.Count - 1 do cp[q] := integer(fMultiSelectedImages[q]); for q := length(cp) - 1 downto 0 do DeleteImageNU(cp[q]); end; UpdateEx(false, fSelectedImageAlwaysVisible); end; {!! TImageEnMView.DeleteImage Declaration procedure DeleteImage(idx: integer); Description Deletes image, idx (freeing its associated bitmap). !!} procedure TImageEnMView.DeleteImage(idx: integer); begin if DeleteImageNU(idx) then UpdateEx(false, fSelectedImageAlwaysVisible); end; // This method is called whenever the zoom or viewx/y changes. procedure TImageEnMView.ViewChange(c: integer); begin if assigned(fOnViewChange) and fUserAction then fOnViewChange(self, c); end; {!! TImageEnMView.Update Declaration procedure Update; Description Updates the display to show the current content and properties. !!} procedure TImageEnMView.Update; begin if assigned(fAnimation) then fAnimation.ImageCount := ImageCount; UpdateEx(true); end; procedure TImageEnMView.UpdateEx(bUpdateCache: Boolean; bRespositionSelection : Boolean = False); var max_x, max_y, i: integer; lClientWidth, lClientHeight: integer; bb: boolean; begin if (fLockPaint > 0) or (fLockUpdate > 0) then exit; if fUpdating then exit; if fDestroying then exit; if not HandleAllocated then exit; if (ComponentState <> []) and (ComponentState <> [csDesigning]) and (ComponentState <> [csFreeNotification]) then exit; if (GetParentForm(self) = nil) and (ParentWindow = 0) then exit; if not (csDesigning in ComponentState) then begin fUpdating := true; if bUpdateCache then ClearCache; UpdateCoords; for i := 0 to 8 do begin lClientWidth := ClientWidth; lClientHeight := ClientHeight; bb := false; GetMaxViewXY(max_x, max_y); if fViewX > max_x then begin fViewX := max_x; bb := true; end; if fViewY > max_y then begin fViewY := max_y; bb := true; end; if bb then ViewChange(0); try if ((fScrollBars = ssHorizontal) or (fScrollBars = ssBoth)) and not assigned(fAnimation) then begin if (max_x > 0) then begin fRXScroll := (max_x + ClientWidth - 1) / 65536; IESetScrollBar(Handle, SB_HORZ, 0, 65535, trunc(ClientWidth / fRXScroll), trunc(fViewX / fRXScroll), true, fFlatScrollBars); IEEnableScrollBar(Handle, SB_HORZ, ESB_ENABLE_BOTH, fFlatScrollBars); IEShowScrollBar(handle, SB_HORZ, true, fFlatScrollBars); end else if fScrollBarsAlwaysVisible then begin IEEnableScrollBar(Handle, SB_HORZ, ESB_DISABLE_BOTH, fFlatScrollBars); IEShowScrollBar(handle, SB_HORZ, true, fFlatScrollBars); end else IEShowScrollBar(handle, SB_HORZ, false, fFlatScrollBars); end; if (fScrollBars = ssVertical) or (fScrollBars = ssBoth) and not assigned(fAnimation) then begin if (max_y > 0) then begin fRYScroll := (max_y + ClientHeight - 1) / 65536; IESetScrollBar(Handle, SB_VERT, 0, 65535, trunc(ClientHeight / fRYScroll), trunc(fViewY / fRYScroll), true, fFlatScrollBars); IEEnableScrollBar(Handle, SB_VERT, ESB_ENABLE_BOTH, fFlatScrollBars); IEShowScrollBar(handle, SB_VERT, true, fFlatScrollBars); end else if fScrollBarsAlwaysVisible then begin IEEnableScrollBar(Handle, SB_VERT, ESB_DISABLE_BOTH, fFlatScrollBars); IEShowScrollBar(handle, SB_VERT, true, fFlatScrollBars); end else IEShowScrollBar(handle, SB_VERT, false, fFlatScrollBars); end; except end; if (lClientWidth = ClientWidth) and (lClientHeight = ClientHeight) then break; // exit from for loop (no other adjustments necessary) end; if assigned(fAnimation) then begin fAnimation.ViewWidth := ClientWidth; fAnimation.ViewHeight := ClientHeight; fAnimation.CurrentImage := SelectedImage; end; CallBitmapChangeEvents; fUpdating := false; end; if bRespositionSelection then CheckSelectedImageIsVisible; invalidate; redrawwindow(handle, nil, 0, RDW_FRAME or RDW_INVALIDATE or RDW_ALLCHILDREN); end; function TImageEnMView.PaletteChanged(Foreground: Boolean): Boolean; begin {$IFNDEF OCXVERSION} if assigned(application) and assigned(application.mainform) and assigned(application.mainform.canvas) then begin if IEDrawDibRealize(fHDrawDib, application.mainform.canvas.handle, false) > 0 then invalidate; end else invalidate; {$ELSE} invalidate; {$ENDIF} result := true; end; {!! TImageEnMView.Background Declaration property Background: TColor; Description Specifies the background color of the component. Note: This value may be overridden if
is enabled. TImageEnMView Default: clBtnFace TImageEnFolderMView Default: clWindow !!} procedure TImageEnMView.SetBackground(cl: TColor); begin inherited SetBackground(cl); fIEMBitmap.fBackground := cl; Update; end; {!! TImageEnMView.SetImageEx Declaration procedure SetImageEx(idx: Integer; srcImage: TBitmap); Description Sets the image assigned to index, idx. The srcImage bitmap is copied internally; therefore you can free srcImage after calling SetImageEx. SetImageEx doesn't call (the only difference from ). Example ImageEnView1.IO.LoadFromFile('000.tif'); ImageEnMView1.InsertImageEx(0); ImageEnMView1.SetImageEx(0, ImageEnView1.Bitmap); ImageEnMView1.Update; // not needed for SetImage() !!} procedure TImageEnMView.SetImageEx(idx: integer; srcImage: TBitmap); var tbmp: TIEBitmap; begin if IEMBitmap_IsTIEDBMultiBitmap then begin fIEMBitmap.SetImage( idx, srcImage ); exit; end; if srcImage <> nil then begin tbmp := TIEBitmap.Create; try tbmp.EncapsulateTBitmap(srcImage, true); SetIEBitmapEx(idx, tbmp); finally FreeAndNil(tbmp); end; end; end; // SetIEBitmapEx creates a new copy of "srcImage" (then srcImage can be freed) // Doesn't call Update procedure TImageEnMView.SetIEBitmapEx(idx: integer; srcImage: TIEBaseBitmap); var bmp: TIEBitmap; ww, hh: integer; wDummy, hDummy : integer; bDoResample: Boolean; begin if srcImage <> nil then begin if (idx > -1) and (idx < fIEMBitmap.Count) then begin if fIEMBitmap.GetImageInfo( idx ).image <> nil then begin fIEMBitmap.fImageList.Delete(fIEMBitmap.GetImageInfo( idx ).image); ClearImageCache(idx); end; if (fStoreType = ietThumb) and (GetEnableResamplingOnMinor or ( srcImage.Width > ThumbSizeInfo( itsImage ).X ) or ( srcImage.Height > ThumbSizeInfo( itsImage ).Y )) then begin if (srcImage.Width = 0) or (srcImage.Height = 0) then begin ww := ThumbSizeInfo( itsImage ).X; hh := ThumbSizeInfo( itsImage ).Y; end else begin IEGetFitResampleSizeWithAutoCrop(srcImage.width, srcImage.height, ThumbSizeInfo( itsImage ).X, ThumbSizeInfo( itsImage ).Y, wDummy, hDummy, fThumbnailClipping, ww, hh); end; if GetEnableResamplingOnMinor then bDoResample := (srcImage.Width <> ww) or (srcImage.Height <> hh) else bDoResample := (srcImage.Width > ww) or (srcImage.Height > hh); if bDoResample and (srcImage.Width > 0) and (srcImage.Height > 0) then begin bmp := TIEBitmap.Create; try bmp.allocate(ww, hh, ie24RGB); if (srcImage is TIEBitmap) and (srcImage as TIEBitmap).HasAlphaChannel then _IESetAlpha0Color(srcImage as TIEBitmap, CreateRGB(128, 128, 128)); if srcImage.pixelformat = ie1g then begin _SubResample1bitFilteredEx(srcImage, 0, 0, srcImage.width - 1, srcImage.height - 1, bmp) end else begin if srcImage.PixelFormat <> ie24RGB then begin bmp.PixelFormat := srcImage.PixelFormat; _IEBmpStretchEx(srcImage, bmp, nil, nil); end else if (fThumbnailResampleFilter = rfNone) then begin bmp.PixelFormat := srcImage.PixelFormat; _IEBmpStretchEx(srcImage, bmp, nil, nil); end else _ResampleEx(srcImage, bmp, nil, fThumbnailResampleFilter, nil, nil); end; if (srcImage is TIEBitmap) and (srcImage as TIEBitmap).HasAlphaChannel then begin if fThumbnailResampleFilter = rfNone then _Resampleie8g((srcImage as TIEBitmap).AlphaChannel, bmp.AlphaChannel, rfFastLinear) else _Resampleie8g((srcImage as TIEBitmap).AlphaChannel, bmp.AlphaChannel, fThumbnailResampleFilter); bmp.AlphaChannel.Full := (srcImage as TIEBitmap).AlphaChannel.Full; end; fIEMBitmap.GetImageInfo( idx ).image := fIEMBitmap.fImageList.AddIEBitmap(bmp); finally FreeAndNil(bmp); end; end else fIEMBitmap.GetImageInfo( idx ).image := fIEMBitmap.fImageList.AddIEBitmap(srcImage); end else begin fIEMBitmap.GetImageInfo( idx ).image := fIEMBitmap.fImageList.AddIEBitmapNoMap(srcImage); end; fIEMBitmap.fImageList.SetImageOriginalWidth(fIEMBitmap.GetImageInfo( idx ).image, srcImage.Width); fIEMBitmap.fImageList.SetImageOriginalHeight(fIEMBitmap.GetImageInfo( idx ).image, srcImage.Height); end; if idx = fSelectedItem then begin fSelectedBitmap := nil; CallBitmapChangeEvents; end; end; end; {!! TImageEnMView.SetImage Declaration procedure SetImage(idx: Integer; srcImage: ); overload; procedure SetImage(idx: Integer; srcImage: TBitmap); overload; procedure SetImage(idx: Integer; width, height: Integer; PixelFormat: ); overload; Description Sets the image assigned to index, idx. The srcImage bitmap is copied internally; therefore you can free srcImage after calling SetImage. Example ImageEnView1.IO.LoadFromFile('000.tif'); ImageEnMView1.InsertImageEx(0); ImageEnMView1.SetImage(0, ImageEnView1.IEBitmap); See Also - - !!} procedure TImageEnMView.SetImage(idx: Integer; srcImage: TBitmap); begin SetImageEx(idx, srcImage); ClearImageCache(idx); UpdateEx(false); end; procedure TImageEnMView.SetImage(idx: Integer; width, height: Integer; PixelFormat: TIEPixelFormat); var temp: TIEBitmap; begin temp := TIEBitmap.Create(Width, Height, PixelFormat); try SetImage( idx, temp ); finally temp.free; end; end; procedure TImageEnMView.SetImage(idx: integer; srcImage: TIEBaseBitmap); begin if IEMBitmap_IsTIEDBMultiBitmap then begin fIEMBitmap.SetImage( idx, srcImage ); exit; end; if srcImage <> nil then begin SetIEBitmapEx(idx, srcImage); ClearImageCache(idx); UpdateEx(false); end; end; {$ifdef IEIncludeDeprecatedInV6} // Deprecated in 6.2.0 (2015-08-24) procedure TImageEnMView.SetIEBitmap(idx: integer; srcImage: TIEBaseBitmap); begin SetImage( idx, srcImage ); end; {$endif} {!! TImageEnMView.SetImageRect Declaration procedure SetImageRect(idx: Integer; srcImage: TBitmap; x1, y1, x2, y2: Integer); procedure SetImageRect(idx: Integer; srcImage: ; x1, y1, x2, y2: Integer); Description Sets the image assigned to index, idx. The rectangle x1, y1, x2, y2 of srcImage bitmap is copied internally. After calling SetImageRect you can free the srcImage bitmap. !!} // creates a new copy of "srcImage" (then srcImage can be freed) procedure TImageEnMView.SetImageRect(idx: integer; srcImage: TBitmap; x1, y1, x2, y2: integer); begin if idx < fIEMBitmap.Count then begin x1 := imin(srcImage.width - 1, x1); y1 := imin(srcImage.height - 1, y1); x2 := imin(srcImage.width - 1, x2); y2 := imin(srcImage.height - 1, y2); if fIEMBitmap.GetImageInfo( idx ).image <> nil then begin fIEMBitmap.fImageList.Delete(fIEMBitmap.GetImageInfo( idx ).image); ClearImageCache(idx); end; fIEMBitmap.GetImageInfo( idx ).image := fIEMBitmap.fImageList.AddBitmapRect(srcImage, x1, y1, x2 - x1 + 1, y2 - y1 + 1); fIEMBitmap.fImageList.SetImageOriginalWidth(fIEMBitmap.GetImageInfo( idx ).image, srcImage.Width); fIEMBitmap.fImageList.SetImageOriginalHeight(fIEMBitmap.GetImageInfo( idx ).image, srcImage.Height); if idx = fSelectedItem then begin fSelectedBitmap := nil; CallBitmapChangeEvents; end; ClearImageCache(idx); UpdateEx(false); end; end; // creates a new copy of "srcImage" (then srcImage can be freed) procedure TImageEnMView.SetImageRect(idx: integer; srcImage: TIEBitmap; x1, y1, x2, y2: integer); var temp: TIEBitmap; begin temp := TIEBitmap.Create; try temp.Allocate(x2 - x1 + 1, y2 - y1 + 1, srcImage.PixelFormat); srcImage.CopyRectTo(temp, x1, y1, 0, 0, temp.Width, temp.Height, true); if temp.HasAlphaChannel then temp.AlphaChannel.SyncFull(); SetImage( idx, temp ); finally temp.free; end; end; {!! TImageEnMView.ImageAtPos Declaration function ImageAtPos(x, y: Integer; checkBounds: Boolean = true): Integer; Description Use ImageAtPos to determine which image exists at the specified location within the control. The x, y parameters specify the position in "client coordinates". If checkBounds is True, thumbnail bounds are checked to ensure that we are positioned within the thumbnail area (Specifying False is useful for finding the nearest thumbnail). If there is no thumbnail at the specified position, ImageAtPos returns -1. Example // Display the file name in the status bar for the image under the cursor procedure TForm1.ImageEnMView1MouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer); begin // Note: ImageFileName[] will return '' if -1 is passed StatusBar1.SimpleText := ImageEnMView1.ImageFileName[ ImageEnMView1.ImageAtPos(x, y) ]; end; !!} // returns image index at x, y position // -1 no image // Friendly wrapper for ImageAtPosEx function TImageEnMView.ImageAtPos(x, y: integer; checkBounds: Boolean): Integer; begin Result := ImageAtPosEx(x, y, checkBounds, True); end; // ImageAtPos with bRelativeToWindow function TImageEnMView.ImageAtPosEx(x, y: integer; checkBounds: Boolean; bRelativeToWindow : Boolean): integer; var ix, iy: integer; x1, y1, x2, y2: integer; info: TIEImageInfo; begin if fDisplayMode = mdSingle then begin // SINGLE VIEW result := fFrame; end else if assigned(fAnimation) then begin // ANIMATION Result := fAnimation.FindImageAt(x, y); end else begin // GRID if y < CurrentHeaderRowHeight then begin Result := -1; exit; end; if bRelativeToWindow then begin ix := imin( ( x + fViewX - ThumbnailsOrigin.X ) div ThumbSizeInfo( itsOuter ).X, CalcGridWidth() - 1 ); iy := imin( ( y + fViewY - ThumbnailsOrigin.Y ) div ThumbSizeInfo( itsOuter ).Y, CalcGridHeight() - 1 ); end else begin ix := imin( ( x - ThumbnailsOrigin.X ) div ThumbSizeInfo( itsOuter ).X, CalcGridWidth() - 1 ); iy := imin( ( y - ThumbnailsOrigin.Y ) div ThumbSizeInfo( itsOuter ).Y, CalcGridHeight() - 1 ); end; if BiDiModeIsRTL() then ix := CalcGridWidth() - ix - 1; if fCurrentGridWidth = 0 then iy := 0; result := ImageAtGridPos(iy, ix); if result >= ImageCount then begin if iemoRegion in fMultiSelectionOptions then result := ImageCount-1 else result := -1; end; if checkBounds and (result >= 0) then begin // verify if inside the thumbnail rectangle info := fIEMBitmap.GetImageInfo( result ); if bRelativeToWindow then begin x1 := info.X - fViewX; y1 := info.Y - fViewY; end else begin x1 := info.X; y1 := info.Y; end; x2 := x1 + ThumbSizeInfo( itsCell ).X - 1; y2 := y1 + ThumbSizeInfo( itsCell ).Y; if not IEPointInRect(x, y, x1, y1, x2, y2) then result := -1; end; end; end; function TImageEnMView.ImageAtPosWithCheckEvent(x, y: integer; checkBounds: Boolean; bRelativeToWindow : Boolean): integer; begin result := ImageAtPosEx(x, y, checkBounds, bRelativeToWindow); if assigned(fOnImageAtPos) then fOnImageAtPos(self, result, x, y); end; {!! TImageEnMView.ImageAtGridPos Declaration function ImageAtGridPos(row, col: Integer): Integer; Description ImageAtGridPos returns the index of the image at row, col position, e.g. ImageAtGridPos(0, 0) would return the top-left image (i.e. 0). !!} function TImageEnMView.ImageAtGridPos(row, col: integer): integer; begin result := row * CalcGridWidth() + col; end; {!! TImageEnMView.InsertingPoint Declaration function InsertingPoint(x, y: Integer): Integer; Description Returns the index of the image before or after the x, y position. It is useful when an image needs to be inserted at a particular cursor position. Example // this drag/drop event copy all selected images of ImageEnMView1 to ImageEnMView2, starting at X, Y mouse position procedure TForm1.ImageEnMView2DragDrop(Sender, Source: TObject; X, Y: Integer); var i: integer; idx, im: integer; tmpbmp: TBitmap; begin im := ImageEnMView2.InsertingPoint(X, Y); for i := 0 to ImageEnMView1.MultiSelectedImagesCount-1 do begin idx := ImageEnMView1.MultiSelectedImages[i]; tmpbmp := ImageEnMView1.GetBitmap( idx ); ImageEnMView2.InsertImage(im); ImageEnMView2.SetImage(im, tmpbmp); inc(im); ImageEnMView1.ReleaseBitmap( idx ); end; end; !!} // return =fIEMBitmap.Count if after last thumbnail function TImageEnMView.InsertingPoint(x, y: integer): integer; var ix, iy, gw: integer; begin ix := ( x + fViewX - ThumbnailsOrigin.X ) div ThumbSizeInfo( itsOuter ).X; iy := ( y + fViewY - ThumbnailsOrigin.Y ) div ThumbSizeInfo( itsOuter ).Y; gw := CalcGridWidth(); if (gw > 0) and (ix > gw) then ix := gw; result := imin(iy * gw + ix, fIEMBitmap.Count); // not fIEMBitmap.Count-1 !! end; procedure TImageEnMView.MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); var sidx: Integer; lSelectInclusive: boolean; lMultiSelecting: boolean; idx: Integer; begin inherited; fUserAction := true; try if fDoubleClicking then begin fDoubleClicking := false; exit; end; if fResizingTextColIdx > -1 then begin // Text column is being resized fResizingTextColClickX := X; fResizingTextColWidth := CurrentTextColumnWidths( TIEMTextPos( fResizingTextColIdx )); exit; end; {$IFDEF OCXVERSION} SetFocus(); {$ELSE} if CanFocus then Windows.SetFocus(Handle); {$ENDIF} fHSX1 := X; fHSY1 := Y; fHSVX1 := ViewX; fHSVY1 := ViewY; fHSIDX := ImageAtPosWithCheckEvent(x, y, fCheckThumbBoundsOnSelect); fHSIDXSelected := IsSelected(ImageAtPosWithCheckEvent(x, y, True)); fSelectIdxOnMouseUp := -1; if fHSIDXSelected and ((ssCtrl in Shift) = False) and ((ssShift in Shift) = False) then fSelectIdxOnMouseUp := fHSIDX; fLHSIDX := fHSIDX; FLastRegionIdx := ImageAtPosEx(x, y, True, False); fHaveMultiselected := false; fMDown := true; fChangedSel := false; if (assigned(fAnimation) = False) and (iemoSelectOnRightClick in fMultiSelectionOptions) and (Button = mbRight) then begin // Make functionality much closer to Windows Explorer idx := ImageAtPosWithCheckEvent(x, y, True); if (idx >= 0) and (IsSelected(idx) = False) then begin Button := mbLeft; Shift := []; end; end; if assigned(fAnimation) and (Button = mbLeft) then begin // animation mode // show an image clicking on it sidx := fAnimation.FindImageAt(X, Y); if sidx > -1 then begin fAnimation.CurrentImage := sidx; SelectedImage := fAnimation.CurrentImage; end; // start scrollbar slider dragging if fAnimation.ShowScrollbar then begin if fAnimation.IsInsideScrollbarSlider(X, Y) then fAnimationDraggingSlider := true // directly move to the clicked scrollbar position else if fAnimation.IsInsideScrollbar(X, Y) then begin fAnimation.MoveScrollbarSliderTo(X); SelectedImage := fAnimation.CurrentImage; end; end; end else if ((iemoSelectOnMouseUp in fMultiSelectionOptions) = False) and (Button = mbLeft) and (CheckboxAtPos(X, Y) > -1) then begin ClickCheckboxAtPos(X, Y); end else if not (iemoSelectOnMouseUp in fMultiSelectionOptions) and (Button = mbLeft) and (mmiSelect in fMouseInteract) then begin // select on mouse down sidx := ImageAtPosWithCheckEvent(x, y, fCheckThumbBoundsOnSelect); if CheckSelectionChangingAllowed = False then begin // Do nothing end else if (ssShift in Shift) and fEnableMultiSelect then begin sidx := fPriorHSIDX; if sidx < 0 then sidx := 0; lSelectInclusive := fSelectInclusive; lMultiSelecting := fMultiSelecting; fMultiSelecting := false; fSelectInclusive := true; DeselectNU; SetSelectedItemNU(sidx); fMultiSelecting := lMultiSelecting; SelectAtPos(X, Y, [ssShift]); fSelectInclusive := lSelectInclusive; fHaveMultiselected := true; end else if not IsSelected(sidx) then begin fPriorHSIDX := sidx; SelectAtPos(X, Y, Shift); end else begin fPriorHSIDX := sidx; if (ssCtrl in Shift) and (iemoOptimizeForDragging in fMultiSelectionOptions) and (MultiSelectedImagesCount > 1) then UnselectImage(sidx); end; end; finally fUserAction := false; DoAfterEvent(ieaeMouseDown); end; end; function TImageEnMView.GetHintStr(idx : Integer) : string; procedure _AddLine(sText : string); begin if sText <> '' then begin if Result = '' then Result := sText else Result := Result + #13#10 + sText; end; end; procedure _AddLineEx(ACaption : TMsgLanguageWords; sText : string); begin sText := ReplaceIEMConst(sText, idx); if sText <> '' then _AddLine( iemsg(ACaption) + ': ' + sText ); end; var sFilename: WideString; begin Result := ''; sFilename := ImageFilename[idx]; if sFilename = '' then begin _AddLine( ImageTopText[idx] ); _AddLine( ImageInfoText[idx] ); _AddLine( ImageBottomText[idx] ); exit; // invalid file end; if GetImageType(idx) = ieftFolder then begin _AddLineEx(IEMSG_Folder, sFilename ); end else begin _AddLineEx(IEMSG_FILE, GetDisplayName( sFileName )); _AddLineEx(IEMSG_Folder, IEM_FilePath); _AddLineEx(IEMSG_Dimensions, IEM_ImageDimensions); _AddLineEx(IEMSG_Type, IEM_FileType); _AddLineEx(IEMSG_SIZE, IEM_FileSize); end; _AddLineEx(IEMSG_Created, IEM_FileCreateDate); _AddLineEx(IEMSG_Modified, IEM_FileEditDate); end; procedure TImageEnMView.MouseMove(Shift: TShiftState; X, Y: Integer); const Scroll_Area_Size = 20; Auto_Scroll_Amount = 10; Mouse_Move_Threshold = 10; Proportional_Scroll_Divisor = 3; Drag_Scroll_Area = 20; Column_Split_Width = 5; var lSelectInclusive: boolean; lMultiSelecting: boolean; idx: integer; iNewX, iNewY: integer; iRgnIdx: integer; AutoScrollProp: integer; sCurrentHint: string; bCanSelect: Boolean; iMaxWidth: Integer; Itt: TIEMTextPos; begin inherited; sCurrentHint := Hint; fUserAction := true; fLastMouseMoveX := X; fLastMouseMoveY := Y; if fResizingTextColClickX < 0 then fResizingTextColIdx := -1; try if assigned(fAnimation) then begin // animation mode if fAnimation.ShowScrollbar then begin // change mouse cursor (hand when inside the scrollbar slider, default otherwise) if fAnimation.IsInsideScrollbarSlider(X, Y) then Cursor := crHandPoint else Cursor := crDefault; // dragging scrollbar slider if MouseCapture and fAnimationDraggingSlider then begin fAnimation.MoveScrollbarSliderTo(X); SelectedImage := fAnimation.CurrentImage; end; end; end else begin bCanSelect := (fHSIDXSelected = False) or not (iemoOptimizeForDragging in fMultiSelectionOptions); // default mode if MouseCapture and ( fResizingTextColIdx = -1 ) then begin if (mmiSelect in fMouseInteract) and fEnableMultiSelect then begin idx := ImageAtPosEx(fViewX + x, fViewY + y, False, False); iRgnIdx := ImageAtPosEx(fViewX + x, fViewY + y, True, False); if bCanSelect and (CheckSelectionChangingAllowed = False) then bCanSelect := False; if bCanSelect then if ((idx <> fLHSIDX) and (idx <> -1)) or ((iemoRegion in fMultiSelectionOptions) and (iRgnIdx <> FLastRegionIdx)) then begin fLHSIDX := idx; FLastRegionIdx := iRgnIdx; idx := fHSIDX; if idx < 0 then idx := 0; lSelectInclusive := fSelectInclusive; lMultiSelecting := fMultiSelecting; fMultiSelecting := (ssCtrl in Shift); fSelectInclusive := true; if not fMultiSelecting then DeselectNU(); SetSelectedItemNU(idx); fMultiSelecting := lMultiSelecting; SelectAtPos(X, Y, [ssShift]); fSelectInclusive := lSelectInclusive; fHaveMultiselected := true; end; // Automatically scroll selection if (mmiScroll in fMouseInteract) = False then begin iNewX := fViewX; iNewY := fViewY; AutoScrollProp := Auto_Scroll_Amount; if Y < 0 then AutoScrollProp := imax(Abs(Y) div Proportional_Scroll_Divisor, AutoScrollProp) else AutoScrollProp := imax(imax(0, Y-ClientHeight) div 2, AutoScrollProp); if X < 0 then AutoScrollProp := imax(Abs(X) div Proportional_Scroll_Divisor, AutoScrollProp) else AutoScrollProp := imax(imax(0, X-ClientWidth) div 2, AutoScrollProp); if (Abs(fHSY1 - Y) > Mouse_Move_Threshold) and (Y < Scroll_Area_Size) and (fViewY > 0) then Dec(iNewY, AutoScrollProp) else if (Abs(fHSY1 - Y) > Mouse_Move_Threshold) and (Y > ClientHeight - Scroll_Area_Size) and (ClientHeight < fVHeight) and (fViewY < fVHeight) then Inc(iNewY, AutoScrollProp); if (Abs(fHSX1 - X) > Mouse_Move_Threshold) and (X < Scroll_Area_Size) and (fViewX > 0) then Dec(iNewX, AutoScrollProp) else if (Abs(fHSX1 - X) > Mouse_Move_Threshold) and (X > ClientWidth - Scroll_Area_Size) and (ClientWidth < fVWidth) and (fViewX < fVWidth) then Inc(iNewX, AutoScrollProp); if (iNewX <> fViewX) or (iNewY <> fViewY) then begin SetViewXY(iNewX, iNewY); ViewChange(0); PostMessage(Handle, IEM_AUTOSCROLL, 0, 0); if fTrackMouseSelection = False then Paint(); end; end; if fTrackMouseSelection and bCanSelect then begin fDrawMouseSelection := true; Paint(); end; end; if mmiScroll in fMouseInteract then begin if ((X - fHSx1)<>0) or ((Y - fHSy1)<>0) then begin SetViewXY(fHSVX1 - (X - fHSx1), fHSVY1 - (Y - fHSy1)); ViewChange(0); end; end; end // If MouseCapture... else if fShowThumbnailHint and (DisplayMode <> mdSingle) then begin idx := ImageAtPosEx(fViewX + x, fViewY + y, True, False); sCurrentHint := GetHintStr(idx); end; // DRAW CHECKBOX IF HOVERING OVER THE MOUSE if fHoverCheckLastPos.X = -1 then fHoverCheckLastPos := Point(X, Y); if (fCheckboxes = iecbShowOnHover) and (fLockPaint <= 0) and ((abs(fHoverCheckLastPos.X - X) > Mouse_Move_Threshold) or (abs(fHoverCheckLastPos.Y - Y) > Mouse_Move_Threshold)) then begin idx := ImageAtPosEx(fViewX + x, fViewY + y, True, False); if idx <> fHoverCheckLastIdx then begin if fHoverCheckLastIdx > -1 then _UpdateImage(fHoverCheckLastIdx, True); fHoverCheckLastIdx := idx; DrawCheckbox(Canvas, idx, True, True); end; end; // RESIZING OF TEXT COLUMNS IN COLUMNS STYLE if ( fResizingTextColIdx > -1 ) and ( fResizingTextColClickX > -1 ) then begin // Lock the width of any columns to the left if ( TIEMTextPos( fResizingTextColIdx ) in [ iemtpBottom, iemtpInfo ]) then fTextColumnWidths[ iemtpTop ] := CurrentTextColumnWidths( iemtpTop ); if ( TIEMTextPos( fResizingTextColIdx ) = iemtpInfo ) then fTextColumnWidths[ iemtpBottom ] := CurrentTextColumnWidths( iemtpBottom ); // Make any columns to the right auto if ( TIEMTextPos( fResizingTextColIdx ) in [ iemtpTop, iemtpBottom ]) then fTextColumnWidths[ iemtpInfo ] := -1; if ( TIEMTextPos( fResizingTextColIdx ) = iemtpTop ) then fTextColumnWidths[ iemtpBottom ] := -1; iMaxWidth := ClientWidth - trunc(fThumbWidth * fZoom / 100.0) - 2 * fHorizBorder; if fResizingTextColIdx > ord( iemtpTop ) then for itt := iemtpTop to TIEMTextPos( fResizingTextColIdx - 1 ) do Dec( iMaxWidth, fTextColumnWidths[ itt ]); fTextColumnWidths[ TIEMTextPos( fResizingTextColIdx )] := imin( fResizingTextColWidth + x - fResizingTextColClickX, iMaxWidth ); if fTextColumnWidths[ TIEMTextPos( fResizingTextColIdx )] < 0 then fTextColumnWidths[ TIEMTextPos( fResizingTextColIdx )] := 0; Invalidate; end else if y < CurrentHeaderRowHeight then begin for Itt := Low( fTextColsCurrentRight ) to High( fTextColsCurrentRight ) do if ( fTextColsCurrentRight[ itt ] > 0 ) and ( abs( x - fTextColsCurrentRight[ itt ] ) < Column_Split_Width ) and (( x < ThumbSizeInfo( itsCell ).X ) or ( fTextBlockWidth > -1 ) or ( CurrentTextColumnWidths( iemtpInfo ) = 0 )) then // if auto-sized to client width, can't drag rightmost column begin fResizingTextColIdx := ord( Itt ); Break; end; if fResizingTextColIdx > -1 then Cursor := crHSplit end; end; // If Animation else if (sCurrentHint <> Hint) then begin Application.CancelHint; Hint := sCurrentHint; end; finally fUserAction := false; if ( fResizingTextColIdx = -1 ) and ( Cursor = crHSplit ) then Cursor := crDefault; end; end; procedure TImageEnMView.MouseUp(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); var idx: Integer; bCanSelect: Boolean; Itt: TIEMTextPos; begin inherited; fUserAction := true; try if fResizingTextColIdx > -1 then begin // Text column was being resized fResizingTextColClickX := -1; exit; end; if fTrackMouseSelection then begin fDrawMouseSelection := false; Paint(); end; if not fMDown then exit; fMDown := false; if fDragging then exit; if fPlaying then exit; if (assigned(fAnimation) = False) and (iemoSelectOnRightClick in fMultiSelectionOptions) and (Button = mbRight) then begin // Make functionality much closer to Windows Explorer idx := ImageAtPosWithCheckEvent(x, y, True); if (idx >= 0) and (IsSelected(idx) = False) then begin Button := mbLeft; Shift := []; end; end; if Button = mbLeft then begin if assigned(fAnimation) then begin // animation mode fAnimationDraggingSlider := false; end else begin if (iemoSelectOnMouseUp in fMultiSelectionOptions) and (CheckboxAtPos(X, Y) > -1) then begin ClickCheckboxAtPos(X, Y); end else if (iemoSelectOnMouseUp in fMultiSelectionOptions) and (not fHaveMultiselected) and (mmiSelect in fMouseInteract) then begin // we select on "mouse up" if CheckSelectionChangingAllowed then SelectAtPos(X, Y, Shift); end; if not (iemoSelectOnMouseUp in fMultiSelectionOptions) and (fChangedSel = False) and (CheckboxAtPos(X, Y) = -1) then begin bCanSelect := (fHSIDXSelected = False) or not (iemoOptimizeForDragging in fMultiSelectionOptions); if bCanSelect and (CheckSelectionChangingAllowed = False) then begin // Do nothing end else // when we select on "mouse down", there is one case where we still need to select on mouse up if bCanSelect then SelectAtPos(X, Y, Shift) else if fSelectIdxOnMouseUp > -1 then begin DeselectNU; SelectedImage := fSelectIdxOnMouseUp; end; end; if (mmiScroll in fMouseInteract) then SetViewXY(fHSVX1 - (X - fHSx1), fHSVY1 - (Y - fHSy1)); if y < CurrentHeaderRowHeight then begin // Clicked a header cell? for Itt := Low( fTextColsCurrentRight ) to High( fTextColsCurrentRight ) do if x < fTextColsCurrentRight[ itt ] then begin ClickColumnsHeaderRowCell( itt ); Break; end; end; end; end; finally fUserAction := false; DoAfterEvent(ieaeMouseUp); end; end; procedure TImageEnMView.SelectAtPos(X, Y: integer; Shift: TShiftState); var idx, q, col, row: integer; lMultiSelecting: boolean; row1, row2, col1, col2: integer; x1, y1, x2, y2: integer; incx, incy: integer; begin // find the image where user has clicked (put in fSelectedItem) lMultiSelecting := fMultiSelecting; if (ssCtrl in Shift) or (ssShift in Shift) then fMultiSelecting := true; if (iemoRegion in fMultiSelectionOptions) and ((fHSX1 <> X) or (fHSY1 <> Y)) then begin if not fMultiSelecting then DeselectNU(); x1 := imin(fHSVX1 + fHSX1, ViewX + X); y1 := imin(fHSVY1 + fHSY1, ViewY + Y); x2 := imax(fHSVX1 + fHSX1, ViewX + X); y2 := imax(fHSVY1 + fHSY1, ViewY + Y); // Check minimum bounds x1 := imax(x1, 0); y1 := imax(y1, 0); row := y1; while row <= y2 do begin incy := 0; col := x1; while col <= x2 do begin q := ImageAtPosWithCheckEvent(col, row, True, False); if (q <> -1) and (fMultiSelectedImages.IndexOf(pointer(q)) = -1) then SetSelectedItemNU(q); incx := 0; if q <> -1 then begin incx := ImageX[q] + ThumbSizeInfo( itsOuter ).X; incy := ImageY[q] + ThumbSizeInfo( itsOuter ).Y; end; col := imax(col+1, incx); end; row := imax(row+1, incy); end; if fVisibleSelection then UpdateEx(false); CallBitmapChangeEvents; end else begin idx := ImageAtPosWithCheckEvent(x, y, fCheckThumbBoundsOnSelect); if (idx >= 0) then begin if fEnableMultiSelect and ((idx <> fSelectedItem) or fMultiSelecting) then begin if ssShift in Shift then begin // SHIFT pressed, select range if iemoRegionOnShift in fMultiSelectionOptions then begin row1 := ImageRow[fSelectedItem]; row2 := ImageRow[idx]; col1 := ImageCol[fSelectedItem]; col2 := ImageCol[idx]; if row1 > row2 then iswap(row1, row2); if col1 > col2 then iswap(col1, col2); for row := row1 to row2 do for col := col1 to col2 do begin q := ImageAtGridPos(row, col); if (q <> fSelectedItem) and (q <> idx) and (fMultiSelectedImages.IndexOf(pointer(q)) = -1) then SetSelectedItemNU(q); end; end else begin if fSelectedItem < idx then begin for q := fSelectedItem + 1 to idx - 1 do if fMultiSelectedImages.IndexOf(pointer(q)) = -1 then SetSelectedItemNU(q); end else begin for q := fSelectedItem - 1 downto idx + 1 do if fMultiSelectedImages.IndexOf(pointer(q)) = -1 then SetSelectedItemNU(q); end; end; end; end; SetSelectedItemNU(idx); if fVisibleSelection then UpdateEx(false); CallBitmapChangeEvents; end; end; fMultiSelecting := lMultiSelecting; end; {!! TImageEnMView.VisibleSelection Declaration property VisibleSelection: boolean; Description When enabled the selected frame is marked. Otherwise selected and unselected frames look identical. !!} procedure TImageEnMView.SetVisibleSelection(v: boolean); begin fVisibleSelection := v; Update; end; {!! TImageEnMView.Checkboxes Declaration property Checkboxes: ; Description Displays a checkbox in each thumbnail box to provide an alternative method for users to select files (as opposed to multiple selection). Notes: - Use to return the number of checked items - Read/write the checked status of each file using - Set checked status en masse using or - Change the position and style of checkboxes with and - Access the event, , to determine when the user clicks a checkbox Demo Demos\Multi\Checkboxes\Checkboxes.dpr Example // Copy all checked files to D:\Dest\ for I := 0 to ImageEnMView1.ImageCount - 1 do if ImageEnMView1.Checked[I] then WindowsCopy(Handle, ImageEnMView1.ImageFilename[I], 'D:\Dest\', True, True); !!} procedure TImageEnMView.SetCheckboxes(v: TIEMCheckboxType); // NPC: 25/09/13 begin if fCheckboxes <> v then begin fCheckboxes := v; Invalidate; end; end; {!! TImageEnMView.CheckboxPos Declaration property CheckboxPos : ; Description Specify the corner of the thumbnail where the checkbox is displayed. See Also - Demo Demos\Multi\Checkboxes\Checkboxes.dpr Example // Show checkboxes on bottom left when the user hovers over the thumbnail ImageEnMView1.Checkboxes := iecbShowOnHover; ImageEnMView1.CheckboxPos := iecpBottomLeft; !!} procedure TImageEnMView.SetCheckboxPos(v: TIEMCheckboxPos); // NPC: 23/06/14 begin if fCheckboxPos <> v then begin fCheckboxPos := v; Invalidate; end; end; {!! TImageEnMView.CheckedCount Declaration function CheckedCount : Integer; Description Returns the number of items that have been checked (if have been enabled). Demo Demos\Multi\Checkboxes\Checkboxes.dpr Example // Note: Use OnClick, not OnCheckboxClick if need to read CheckedCount procedure TfMain.ImageEnMView1Click(Sender: TObject); begin // Display the current count of checked items in the status bar Statusbar1.SimpleText := 'Checked: ' + IntToStr(ImageEnMView1.CheckedCount); end; See Also - !!} function TImageEnMView.CheckedCount : Integer; // NPC: 25/09/13 var i: Integer; begin if fCheckedCount < 0 then begin fCheckedCount := 0; for i := 0 to ImageCount - 1 do if Checked[i] then inc(fCheckedCount); end; Result := fCheckedCount; end; {!! TImageEnMView.Checked Declaration property Checked[index : Integer] : Boolean; Description Specifies the checked status for the item of the specified index (if have been enabled). Example // Copy all checked files to D:\Dest\ for I := 0 to ImageEnMView1.ImageCount - 1 do if ImageEnMView1.Checked[I] then WindowsCopy(Handle, ImageEnMView1.ImageFilename[I], 'D:\Dest\', True, True); See Also - !!} function TImageEnMView.GetChecked(index: integer): Boolean; // NPC: 25/09/13 begin result := False; if (index >= 0) and (index < fIEMBitmap.Count) then result := fIEMBitmap.GetImageInfo( index ).Checked; end; procedure TImageEnMView.SetChecked(index: integer; v : Boolean); // NPC: 25/09/13 var bOldChecked: Boolean; begin if (index >= 0) and (index < fIEMBitmap.Count) then begin bOldChecked := fIEMBitmap.GetImageInfo( index ).Checked; if bOldChecked <> v then begin fIEMBitmap.GetImageInfo( index ).Checked := v; if fCheckedCount > -1 then begin if v then inc(fCheckedCount) else dec(fCheckedCount); end; DrawCheckbox(Canvas, Index, True, True); end; end; end; {!! TImageEnMView.SetCheckboxParams Declaration procedure SetCheckboxParams(iHorzMargin, iVertMargin : Integer; CustomCheckedImage : TBitmap = nil; CustomUncheckedImage : TBitmap = nil); Description Specifies the position and style of checkboxes (if have been enabled). Parameter Description iHorzMargin The position from the left (iecpTopLeft or iecpBottomLeft) or right (iecpTopRight or iecpBottomRight) of the thumbnail where the checkbox is positioned. Default: 4 iVertMargin The position from the top (iecpTopLeft or iecpTopRight) or bottom (iecpBottomLeft or iecpBottomRight) of the thumbnail where the checkbox is positioned. Default: 4 CustomCheckedImage If specified, it is the image that will be shown as the "checked" box. If nil the Windows standard checkbox image is used CustomUncheckedImage If specified, it is the image that will be shown as the "unchecked" box. If nil the Windows standard checkbox image is used
See Also -
Example // Load custom checkbox images from file and position them at the very top left CheckBmp := TBitmap.create; UncheckBmp := TBitmap.create; try CheckBmp.LoadFromFile('C:\Images\Checked.bmp'); UncheckBmp.LoadFromFile('C:\Images\Unchecked.bmp'); ImageEnMView1.SetCheckboxParams(0, 0, CheckBmp, UncheckBmp); ImageEnMView1.CheckboxPos := iecpTopLeft; ImageEnMView1.Checkboxes := iecbAlways; finally CheckBmp.free; UncheckBmp.free; end; !!} procedure TImageEnMView.SetCheckboxParams(iHorzMargin, iVertMargin : Integer; CustomCheckedImage : TBitmap = nil; CustomUncheckedImage : TBitmap = nil); // NPC: 25/09/13 begin fCheckboxMargins := Point(iHorzMargin, iVertMargin); if Assigned(CustomCheckedImage) = False then FreeAndNil(fCheckedBitmap) // default thumbnail will be assigned at draw else begin if fCheckedBitmap = nil then fCheckedBitmap := TBitmap.create; fCheckedBitmap.assign(CustomCheckedImage) end; if Assigned(CustomUncheckedImage) = False then FreeAndNil(fUncheckedBitmap) // default thumbnail will be assigned at draw else begin if fUncheckedBitmap = nil then fUncheckedBitmap := TBitmap.create; fUncheckedBitmap.assign(CustomUncheckedImage) end; Invalidate; end; {!! TImageEnMView.CheckAll Declaration procedure CheckAll; Description Marks the checkbox status for all files to "Checked" (if have been enabled). !!} procedure TImageEnMView.CheckAll; var I: Integer; begin LockPaint; try for I := 0 to ImageCount - 1 do Checked[i] := True; finally NPUnLockPaint; Invalidate; end; end; {!! TImageEnMView.UncheckAll Declaration procedure UncheckAll; Description Marks the checkbox status for all files to "Unchecked" (if have been enabled). !!} procedure TImageEnMView.UncheckAll; var I: Integer; begin LockPaint; try for I := 0 to ImageCount - 1 do Checked[i] := False; finally NPUnLockPaint; Invalidate; end; end; function TImageEnMView.ThumbToCheckboxRect(ThumbRect : TRect; bRelativeToView : Boolean = False) : TRect; var x1, y1 : integer; begin if fCheckboxPos in [iecpTopLeft, iecpBottomLeft] then // Left Aligned x1 := ThumbRect.Left + fCheckboxMargins.X else // Right aligned x1 := ThumbRect.Right - fCheckedBitmap.Width - fCheckboxMargins.X; if fCheckboxPos in [iecpTopLeft, iecpTopRight] then // Top Aligned y1 := ThumbRect.Top + fCheckboxMargins.Y else // Bottom aligned y1 := ThumbRect.Bottom - fCheckedBitmap.Height - fCheckboxMargins.Y; if bRelativeToView then begin x1 := x1 - ViewX; y1 := y1 - ViewY; end; Result := Rect(x1, y1, x1 + fCheckedBitmap.Width, y1 + fCheckedBitmap.Height); end; procedure DrawCheckBoxToBitmap(Handle: THandle; DestBitmap: TBitmap; bChecked: Boolean); var {$IFDEF IEHASTHEMING} // From Delphi 7 h: HTHEME; {$EndIf} r: TRect; s: TSize; begin {$IFDEF IEHASTHEMING} // From Delphi 7 if UseThemes then begin h := OpenThemeData(Handle, 'BUTTON'); if h <> 0 then try GetThemePartSize(h, DestBitmap.Canvas.Handle, BP_CHECKBOX, CBS_CHECKEDNORMAL, nil, TS_DRAW, s); DestBitmap.Width := s.cx; DestBitmap.Height := s.cy; r := Rect(0, 0, s.cx, s.cy); if bChecked then DrawThemeBackground(h, DestBitmap.Canvas.Handle, BP_CHECKBOX, CBS_CHECKEDNORMAL, r, nil) else DrawThemeBackground(h, DestBitmap.Canvas.Handle, BP_CHECKBOX, CBS_UNCHECKEDNORMAL, r, nil); finally CloseThemeData(h); end; end else {$EndIf} begin s.cx := GetSystemMetrics(SM_CXMENUCHECK); s.cy := GetSystemMetrics(SM_CYMENUCHECK); DestBitmap.Width := s.cx; DestBitmap.Height := s.cy; r := Rect(0, 0, s.cx, s.cy); if bChecked then DrawFrameControl(DestBitmap.Canvas.Handle, r, DFC_BUTTON, DFCS_CHECKED) else DrawFrameControl(DestBitmap.Canvas.Handle, r, DFC_BUTTON, DFCS_BUTTONCHECK); end; end; procedure TImageEnMView.DrawCheckbox(ACanvas : TCanvas; Index : Integer; IsSelected : Boolean; bRelativeToView : Boolean = False); var ThumbRect: TRect; begin if Index > -1 then begin ThumbRect := Rect(ImageX[index], ImageY[index], ImageX[index] + ThumbSizeInfo( itsCell ).X, ImageY[index] + ThumbSizeInfo( itsCell ).Y ); DrawCheckbox(Canvas, Index, ThumbRect, IsSelected, True); end; end; procedure TImageEnMView.DrawCheckbox(ACanvas : TCanvas; Index : Integer; ThumbRect : TRect; IsSelected : Boolean; bRelativeToView : Boolean = False); var CbxRect: TRect; begin if (fCheckboxes = iecbNone) or (fLockPaint > 0) then exit; if fCheckedBitmap = nil then begin fCheckedBitmap := TBitmap.create; DrawCheckBoxToBitmap(Handle, fCheckedBitmap, True); end; if fUncheckedBitmap = nil then begin fUncheckedBitmap := TBitmap.create; DrawCheckBoxToBitmap(Handle, fUncheckedBitmap, False); end; CbxRect := ThumbToCheckboxRect(ThumbRect, bRelativeToView); if bRelativeToView then begin // check if off-screen if (CbxRect.Right < 0) or (CbxRect.Left > ClientWidth) or (CbxRect.Bottom < 0) or (CbxRect.Top > ClientHeight) then exit; end; if Checked[index] then ACanvas.Draw(CbxRect.Left, CbxRect.Top, fCheckedBitmap) else if IsSelected or (fCheckboxes = iecbAlways) then ACanvas.Draw(CbxRect.Left, CbxRect.Top, fUncheckedBitmap); end; // If x, y is within a checkbox of a thumbnail its index is returned. Otherwise -1 function TImageEnMView.CheckboxAtPos(X, Y : Integer) : Integer; var ThumbRect, CbxRect: TRect; idx: Integer; begin Result := -1; if (fCheckboxes = iecbNone) or (fCheckedBitmap = nil) then exit; idx := ImageAtPos(X, Y); if idx > -1 then begin ThumbRect := Rect( ImageX[idx], ImageY[idx], ImageX[idx] + ThumbSizeInfo( itsCell ).X, ImageY[idx] + ThumbSizeInfo( itsCell ).Y ); CbxRect := ThumbToCheckboxRect(ThumbRect); if IEPointInRect(ViewX + x, ViewY + y, CbxRect) then Result := idx end; end; procedure TImageEnMView.ClickCheckboxAtPos(X, Y : Integer); var idx: Integer; bNewChecked: Boolean; begin idx := CheckboxAtPos(X, Y); if idx > -1 then begin bNewChecked := NOT Checked[idx]; if assigned(fOnCheckboxClick) then OnCheckboxClick(Self, idx, bNewChecked); Checked[idx] := bNewChecked; end; end; {!! TImageEnMView.SelectionWidth Declaration property SelectionWidth: integer; Description Specifies the width (in pixels) of the border around selected frames. Notes: - If the control does not have focus, the selection width will be - This value must be less than and . See Also - - - !!} procedure TImageEnMView.SetSelectionBorderWidth(v: integer); begin fSelectionBorderWidth := v; Update; end; {!! TImageEnMView.SelectionWidthNoFocus Declaration property SelectionWidthNoFocus: integer; Description Specifies the width of the border around selected frames when the component doesn't have focus. If the value is -1, it defaults to Default: -1 See Also - - - - !!} procedure TImageEnMView.SetSelectionBorderWidthNoFocus(v: integer); begin fSelectionBorderWidthNoFocus := v; Update; end; {!! TImageEnMView.SelectionColor Declaration property SelectionColor: TColor; Description Specifies the border color of selected cells. Note: This value may be overridden if is enabled. See Also - - - !!} procedure TImageEnMView.SetThumbnailsSelectedBorderColor(v: TColor); begin fThumbnailsSelectedBorderColor := v; Update; end; {!! TImageEnMView.BeginSelectImages Declaration procedure BeginSelectImages; Description Call BeginSelectImages and to select multiple images without refreshing the component's state. Generally this will speed up the selection process. Example // select the first 100 images ImageEnMView1.BeginSelectImages; for i := 0 to 99 do ImageEnMView1.SelectedImage := i; ImageEnMView1.EndSelectImages; !!} procedure TImageEnMView.BeginSelectImages; begin DeselectNU; fSelectImages := true; fMultiSelecting := true; end; {!! TImageEnMView.EndSelectImages Declaration procedure EndSelectImages; Description Call and EndSelectImages to select multiple images without refreshing the component's state. Generally this will speed up the selection process. Example // select the first 100 images ImageEnMView1.BeginSelectImages; for i := 0 to 99 do ImageEnMView1.SelectedImage := i; ImageEnMView1.EndSelectImages; !!} procedure TImageEnMView.EndSelectImages; begin fSelectImages := false; fMultiSelecting := false; if fMultiSelectedImages.Count > 0 then begin fSelectedItem := integer(fMultiSelectedImages[fMultiSelectedImages.Count - 1]); // select last selected image fSelectedBitmap := nil; fIEMBitmap.SetActiveImage( fSelectedItem ); end; CallBitmapChangeEvents; UpdateEx(false); end; {!! TImageEnMView.SelectedImage Declaration property SelectedImage: integer; Description Get or set the currently selected image (which will be drawn with a colored border. You can get the bitmap of selected image using or . See Also - !!} procedure TImageEnMView.SetSelectedItem(v: integer); begin if fPlaying then exit; if (not fMultiSelecting) and (v = fSelectedItem) then exit; if (v < fIEMBitmap.Count) and (v >= 0) then begin SetSelectedItemNU(v); fPriorHSIDX := v; if not fSelectImages then UpdateEx(false, fSelectedImageAlwaysVisible); end; end; procedure TImageEnMView.SetMouseWheelParams(v: TIEMouseWheelParams); begin fMouseWheelParams.Assign( v ); end; procedure TImageEnMView.SetMouseWheelParamsAlt(v: TIEMouseWheelParams); begin fMouseWheelParamsAlt.Assign( v ); end; {!! TImageEnMView.SelectedImageAlwaysVisible Declaration property SelectedImageAlwaysVisible: Boolean; (Read/Write) Description Ensures that the selected cell is always visible when set using or it changes due to appending or deleting images. Default: True See Also - !!} procedure TImageEnMView.SetSelectedImageAlwaysVisible(v: boolean); begin fSelectedImageAlwaysVisible := v; if fSelectedImageAlwaysVisible then CheckSelectedImageIsVisible; end; // doesn't call Update // indexes which aren't inside bounds are ignored procedure TImageEnMView.SetSelectedItemNU(v: integer); var i, q: integer; begin fChangedSel := false; if fPlaying then exit; if (v < fIEMBitmap.Count) and (v >= 0) then begin if fSelectedItem >= 0 then begin if fSelectedBitmap <> nil then fIEMBitmap.fImageList.ReleaseBitmap(fSelectedBitmap, true); end; if fEnableMultiSelect then begin if not fMultiSelecting then begin for i := 0 to fMultiSelectedImages.Count-1 do DoImageDeselect( integer(fMultiSelectedImages[i]) ); fMultiSelectedImages.clear; fChangedSel := true; end else begin if not fSelectImages then begin q := fMultiSelectedImages.IndexOf(pointer(v)); if (q > -1) and (not (iemoLeaveOneSelected in fMultiSelectionOptions) or (fMultiSelectedImages.Count > 1))then begin // item already selected, unselect when fMultiSelecting is True DoImageDeselect( v ); fMultiSelectedImages.Delete(q); fChangedSel := true; if not fSelectInclusive then begin fSelectedItem := -1; EXIT; // EXIT POINT!! end; end; end; end; fMultiSelectedImages.Add(pointer(v)); fChangedSel := true; end; if fSelectImages then begin // inside BeginSelectImages...EndSelectimages the SelectedItem doesn't change (also fSelectedBitmap doesn't change) fSelectedItem := -1; fChangedSel := true; end else begin fSelectedItem := v; fChangedSel := true; fIEMBitmap.SetActiveImage( v ); fSelectedBitmap := nil; CallBitmapChangeEvents; DoImageSelect( fSelectedItem ); end; end; end; {!! TImageEnMView.Deselect Declaration procedure Deselect; Description Remove selection from all selected images. !!} procedure TImageEnMView.DeSelect; begin DeselectNU; UpdateEx(false); end; // doesn't call Update procedure TImageEnMView.DeselectNU; var i: Integer; begin if ( fSelectedItem >= 0 ) and ( fSelectedItem < ImageCount ) then begin fIEMBitmap.fImageList.ReleaseBitmapByImage(fIEMBitmap.GetImageInfo( fSelectedItem ).image, true); end; if fEnableMultiSelect then begin for i := 0 to fMultiSelectedImages.Count-1 do DoImageDeselect( integer(fMultiSelectedImages[i]) ); fMultiSelectedImages.Clear(); end else DoImageDeselect( fSelectedItem ); fSelectedItem := -1; end; {!! TImageEnMView.UnselectImage Declaration procedure UnselectImage(idx: Integer); Description Remove selection from the specified image (if multiselection is enabled). !!} procedure TImageEnMView.UnselectImage(idx: integer); begin if (idx >= 0) and (idx < ImageCount) and IsSelected(Idx) then begin if idx = fSelectedItem then begin fIEMBitmap.fImageList.ReleaseBitmapByImage( fIEMBitmap.GetImageInfo( fSelectedItem ).image, true ); ClearImageCache(fSelectedItem); fMultiSelectedImages.Remove(pointer(idx)); fSelectedItem := -1; end else begin fMultiSelectedImages.Remove(pointer(idx)); end; DoImageDeselect( fSelectedItem ); end; UpdateEx(false); end; // Select image without affecting existing selection procedure TImageEnMView.SelectImage(idx: integer); begin if (idx >= 0) and (idx < ImageCount) and (IsSelected(idx) = False) then begin fSelectImages := true; fMultiSelecting := true; SelectedImage := idx; fSelectImages := false; fMultiSelecting := false; fSelectedItem := idx; fSelectedBitmap := nil; fIEMBitmap.SetActiveImage( idx ); CallBitmapChangeEvents; end; UpdateEx(false); end; // Selects an image if not selected, otherwise deselects. Does not change selection status of other files procedure TImageEnMView.ToggleSelectImage(idx: integer); begin if (idx >= 0) and (idx < ImageCount) then begin if IsSelected(idx) then UnselectImage(idx) else SelectImage(idx); end; end; {!! TImageEnMView.CopyToIEBitmap Declaration procedure CopyToIEBitmap(idx: Integer; bmp: ); Description Copies the specified image, idx, to the destination object. Note: If is not ietNormal then the returned bmp will not be full resolution Example // Show the selected image in a TImageEnView procedure TMainForm.ImageEnMView1ImageSelect(Sender: TObject; idx: Integer); begin ImageEnMView1.CopyToIEBitmap( idx, ImageEnView1.IEBitmap ); ImageEnVeiw1.Update; end; !!} procedure TImageEnMView.CopyToIEBitmap(idx: integer; bmp: TIEBitmap); begin fThreadCS.Enter(); try with fIEMBitmap.GetImageInfo( idx ) do begin // transform hbi to TBitmap object if image = nil then ObtainImageNow(idx); if image <> nil then begin // image present fIEMBitmap.fImageList.CopyToIEBitmap(image, bmp); end; end; finally fThreadCS.Leave(); end; end; {!! TImageEnMView.GetBitmap Declaration function GetBitmap(idx: Integer): TBitmap; Description Creates a TBitmap object from the image at index, idx. Any changes you make to the bitmap will be visible after you call the method. You will need to call to free the TBitmap object. See also: . Demo Demos\Multi\Multiview_PrintFrame\Multiview.dpr Example // Save the fifth image to file bmp := ImageEnMView1.GetBitmap(4); bmp.SaveToFile('alfa.bmp'); ImageEnMView1.ReleaseBitmap(4); !!} function TImageEnMView.GetBitmap(idx: integer): TBitmap; begin fThreadCS.Enter(); result := nil; try with fIEMBitmap.GetImageInfo( idx ) do begin // transform hbi to TBitmap object if image = nil then ObtainImageNow(idx); if image <> nil then begin // image present result := fIEMBitmap.fImageList.GetBitmap(image).VclBitmap; end; end; finally fThreadCS.Leave(); end; end; {!! TImageEnMView.GetTIEBitmap Declaration function GetTIEBitmap(idx: Integer): ; Description Creates a object from the image at index, idx. Any changes you make to the bitmap will be visible after you call the method. You will need to call to free the object. Example // Save the fifth image to file bmp := ImageEnMView1.GetTIEBitmap(4); // Note: bmp must be TIEBitmap type bmp.Write('D:\alfa.png'); ImageEnMView1.ReleaseBitmap(4, False); // Add copyright text to all images for i := 0 to ImageEnMView1.ImageCount - 1 do begin bmp := ImageEnMView1.GetTIEBitmap( i ); with TImageEnProc.CreateFromBitmap( bmp ) do begin ConvertTo24Bit(); TextOut(Align_Text_Horz_Center, Align_Text_Near_Bottom, 'Copyright Skynet', 'Arial', 25, clRed, [fsBold], 0, True); Free; end; ImageEnMView1.ReleaseBitmap( i, True ); ImageEnMView1.Update(); end; !!} function TImageEnMView.GetTIEBitmap(idx: integer): TIEBitmap; begin fThreadCS.Enter(); try result := nil; with fIEMBitmap.GetImageInfo( idx ) do begin // transform hbi to TBitmap object if image = nil then ObtainImageNow( idx ); if image <> nil then begin // image present result := fIEMBitmap.fImageList.GetBitmap(image); end; end; finally fThreadCS.Leave(); end; end; {!! TImageEnMView.ReleaseBitmap Declaration procedure ReleaseBitmap(idx: Integer; saveChanges: Boolean = true); Description Releases the bitmap created with or method. Parameter Description idx The image index to release. saveChanges If true (default) the bitmap will be written in the cache.
Example // Save the fifth image to file bmp := ImageEnMView1.GetTIEBitmap(4); // Note: bmp must be TIEBitmap type bmp.Write('D:\alfa.png'); ImageEnMView1.ReleaseBitmap(4, False); // Add copyright text to all images for i := 0 to ImageEnMView1.ImageCount - 1 do begin bmp := ImageEnMView1.GetTIEBitmap( i ); with TImageEnProc.CreateFromBitmap( bmp ) do begin ConvertTo24Bit(); TextOut(Align_Text_Horz_Center, Align_Text_Near_Bottom, 'Copyright Skynet', 'Arial', 25, clRed, [fsBold], 0, True); Free; end; ImageEnMView1.ReleaseBitmap( i, True ); ImageEnMView1.Update(); end; !!} procedure TImageEnMView.ReleaseBitmap(idx: Integer; saveChanges: Boolean); begin fIEMBitmap.ReleaseBitmap( idx, saveChanges ); ClearImageCache(idx); end; procedure TImageEnMView.ClearOnDemandIOList; var i: Integer; begin for i := 0 to fMultiOnDemands.Count-1 do begin TImageEnIO(fMultiOnDemands[i]).Free; fMultiOnDemands[i] := nil; end; fMultiOnDemands.Clear; end; function TImageEnMView.GetOnDemandIO(const filename: WideString; var FrameIndex: Integer): TImageEnIO; var p: Integer; realname: WideString; begin result := nil; p := Pos(WideString(IEM_Path_Index_Delimiter), filename); // here the '::' must exist realname := copy(filename, 1, p-1); FrameIndex := StrToIntDef(Copy(filename, p+2, length(filename)), 0); // search for already created on the same file for p := 0 to fMultiOnDemands.Count-1 do if TImageEnIO(fMultiOnDemands[p]).Params.FileName = realname then begin result := TImageEnIO(fMultiOnDemands[p]); break; end; if result=nil then begin // create a new one result := TImageEnIO.Create(self); result.Params.FileName := realname; fMultiOnDemands.Add( result ); end; end; procedure TImageEnMView.LoadMultiOnDemand(io: TImageEnIO; frameindex: Integer; var dt: Double); var FType : TIOFileType; FileName: WideString; begin FileName := io.Params.FileName; // it is important that we don't pass io.Params.FileName as parameter FType := IEExtToFileFormat(string(IEExtractFileExtW(FileName))); if FType = ioUnknown then FType := FindFileFormat(FileName, ffContentOnly); dt := 0.0; if (FType <> ioUnknown) and (FType <> ioAVI) and (FType <> ioWMV) and (FType <> ioMPEG) then begin io.Params.GIF_ImageIndex := frameindex; io.Params.TIFF_ImageIndex := frameindex; io.Params.DCX_ImageIndex := frameindex; io.LoadFromFileAuto(FileName); if FType = ioGIF then dt := io.Params.GIF_DelayTime * 10; end else begin {$ifdef IEINCLUDEDIRECTSHOW} if not io.IsOpenMediaFile then io.OpenMediaFile(FileName); io.LoadFromMediaFile(frameindex); dt := io.Params.MEDIAFILE_FrameDelayTime * 10; {$else} if FType = ioAVI then begin if not io.IsOpenAVI then io.OpenAVIFile(FileName); io.LoadFromAVI(frameindex); dt := io.Params.AVI_FrameDelayTime; end; {$endif} end; end; function TImageEnMView.IsOnDemand(info: TIEImageInfo): Boolean; begin Result := False; if info.Filename <> '' then Result := True else if info.ID > -1 then Result := assigned( fOnImageIDRequest ) or assigned( fOnImageIDRequestEx ) or fIEMBitmap.InternalLoadImageByID_Assigned(); end; function IsMetaFile(const Filename: Widestring) : boolean; begin result := ( IEExtractFileExtW( Filename ) = '.emf' ) or ( IEExtractFileExtW( Filename ) = '.wmf' ); end; // Make sure that at index "idx" there is a valid image (load from FileName or request it using ID). // Returns true if the image load is ok, false otherwise function TImageEnMView.ObtainImageNow(idx: integer): boolean; var info: TIEImageInfo; bmp: TBitmap; iebmp: TIEBitmap; io: TImageEnIO; bMultiOnDemand: Boolean; frameindex: Integer; // used reading on demand multi pages dt: Double; ASource: TIESourceType; IOParams: TIOParams; begin fThreadCS.Enter(); try result := true; bmp := nil; IOParams := nil; info := fIEMBitmap.GetImageInfo( idx ); ASource := info.SourceType; if (info.ID > -1) and fIEMBitmap.InternalLoadImageByID_Assigned() then try // Internal request by ID iebmp := nil; IOParams := TIOParams.Create; _SetLoadParams(Self, IOParams); fIEMBitmap.InternalLoadImageByID( self, idx, info.ID, iebmp, IOParams ); // updates params of encapsulated TImageEnMIO object StripOffIOParams( Self, IOParams ); GetImageEnMIO.Params[ idx ].Assign( IOParams ); // GetImageEnMIO creates TImageEnMIO if it doesn't exist // set the image SetIEBitmapEx( idx, iebmp ); ImageOriginalWidth [ idx ] := IOParams.OriginalWidth; ImageOriginalHeight[ idx ] := IOParams.OriginalHeight; if IOParams.EXIF_DateTimeOriginal2 > 0 then info.CreateDate := IOParams.EXIF_DateTimeOriginal2; if assigned( fOnImageLoaded ) then fOnImageLoaded( self, idx ); except result := false; end else if (info.ID > -1) and assigned(fOnImageIDRequest) then begin // request by ID - BMP bmp := nil; fOnImageIDRequest( self, idx, info.ID, bmp ); SetImageEx( idx, bmp ); end else if (info.ID > -1) and assigned(fOnImageIDRequestEx) then begin // request by ID -IEBmp iebmp := nil; fOnImageIDRequestEx( self, idx, info.ID, iebmp ); SetIEBitmapEx( idx, iebmp ); end else if info.Filename <> '' then begin // load from File bMultiOnDemand := Pos(WideString(IEM_Path_Index_Delimiter), WideString(info.Filename)) > 0; // this is the special syntax '::' to load multipages on demand, use ObtainImageNow if bMultiOnDemand then io := GetOnDemandIO(info.Filename, frameindex) else io := fImageEnIO; iebmp := TIEBitmap.Create; try io.Background := info.Background; io.AttachedIEBitmap := iebmp; io.OnProgress := fOnIOProgress; _SetLoadParams(Self, io.Params); if assigned(fImageEnMIO) then io.AutoAdjustDPI := fImageEnMIO.AutoAdjustDPI; try if fEnableLoadExplorerThumbnails and ( fStoreType in [ ietThumb, ietFastThumb ]) and ( not ( ietxOnlyShowIcons in fThumbnailOptionsEx )) and ( ASource <> iestFolderIcon ) {$IFDEF VIDEO_THUMBNAILS} and ExtractExplorerThumbnail( info.Filename, iebmp, ThumbSizeInfo( itsImage ).X, ThumbSizeInfo( itsImage ).Y ) {$ENDIF} then begin if ieixWantParams in fIOOptionsEx then io.ParamsFromFile( info.Filename, True ); io.Aborting := False; // Image is valid, even if params are unavailable end else if ietxOnlyShowIcons in fThumbnailOptionsEx then begin DoWrongImage(iebmp, idx, ASource); if ieixWantParams in fIOOptionsEx then io.ParamsFromFile( info.Filename, True ); io.Aborting := False; // Image is valid, even if params are unavailable end else if bMultiOnDemand then begin // Has user aborted loading if MIO.Aborting then io.Aborting := true else LoadMultiOnDemand(io, frameindex, dt); info.DTime := dt; end else {$IFDEF VIDEO_THUMBNAILS} if ( not fEnableLoadExplorerThumbnails ) and ( fStoreType in [ ietThumb, ietFastThumb ]) and UseThumbnailFromExplorer(info.Filename) then io.Aborting := not ExtractExplorerThumbnail( info.Filename, iebmp, ThumbSizeInfo( itsImage ).X, ThumbSizeInfo( itsImage ).Y ) else {$ENDIF} if ( fStoreType in [ ietThumb, ietFastThumb ]) and IsMetaFile( info.Filename ) then io.ImportMetafile(info.Filename, ThumbSizeInfo( itsImage ).X, -1, true) else begin if ieixLoadOnlyByFileExt in fIOOptionsEx then io.LoadFromFile( info.Filename, False ) else io.LoadFromFileAuto( info.Filename ); if (iebmp.Width < 2) and (iebmp.Height < 2) then io.Aborting := true; end; except io.Aborting := true; end; if io.Aborting then begin DoWrongImage(iebmp, idx, ASource); result := false; end; // updates params of encapsulated TImageEnMIO object StripOffIOParams(self, io.Params); GetImageEnMIO.Params[idx].Assign(io.Params); // GetImageEnMIO creates TImageEnMIO if it doesn't exist // set the image info.Background := io.Background; info.SourceType := ASource; SetIEBitmapEx( idx, iebmp ); ImageOriginalWidth [ idx ] := io.Params.OriginalWidth; ImageOriginalHeight[ idx ] := io.Params.OriginalHeight; if io.Params.EXIF_DateTimeOriginal2 > 0 then info.CreateDate := io.Params.EXIF_DateTimeOriginal2; if assigned( fOnImageLoaded ) then fOnImageLoaded( self, idx ); finally io.AttachedIEBitmap := nil; FreeAndNil(iebmp); end; end; finally FreeAndNil( IOParams ); fThreadCS.Leave(); end; end; // remove available threads or threads that want to load a no more visible image procedure FreeUselessThreads(mview: TImageEnMView); var i: integer; begin i := 0; with mview do while i < fThreadPoolIO.Count do begin if TImageEnIO(fThreadPoolIO[i]).Tag = -1 then begin // finished thread TImageEnIO(fThreadPoolIO[i]).IEBitmap.Free; TImageEnIO(fThreadPoolIO[i]).IEBitmap := nil; TImageEnIO(fThreadPoolIO[i]).AttachedIEBitmap := nil; TImageEnIO(fThreadPoolIO[i]).Free; fThreadPoolIO.delete(i); end else if (TImageEnIO(fThreadPoolIO[i]).Tag >= 0) and (not IsVisible(TImageEnIO(fThreadPoolIO[i]).Tag)) and (not IsLookAhead(TImageEnIO(fThreadPoolIO[i]).Tag)) then begin // invisible image TImageEnIO(fThreadPoolIO[i]).Tag := -2; // -2 controlled abort TImageEnIO(fThreadPoolIO[i]).Aborting := true; inc(i); end else inc(i); end; end; procedure FreeInvisibleRequests(mview: TImageEnMView); var i: integer; begin i := 0; with mview do if MaintainInvisibleImages <> -1 then while i < fThreadRequests.Count do begin if (not IsVisible(integer(fThreadRequests[i]))) and (not IsLookAhead(integer(fThreadRequests[i]))) then fThreadRequests.delete(i) else inc(i); end; end; // -1 = not found, >-1 item index in fThreadRequests function TImageEnMView.IsRequested(idx: Integer): Integer; var i: Integer; begin result := -1; fThreadCS.Enter(); try for i := 0 to fThreadRequests.Count - 1 do if integer(fThreadRequests[i]) = idx then begin result := i; break; end; finally fThreadCS.Leave(); end; end; // return false if info.ID > -1 and assigned OnImageIDRequest. Works only with info.Filename // priority: -1 = lowest priority, 0..inf priority position function TImageEnMView.ObtainImageThreaded(idx: integer; priority: Integer): boolean; var info: TIEImageInfo; i: integer; begin result := false; info := fIEMBitmap.GetImageInfo( idx ); // Is it the special syntax '::' to load multipages on demand? Use ObtainImageNow instead if (info.Filename <> '') and (Pos(WideString(IEM_Path_Index_Delimiter), WideString(info.Filename)) > 0) then exit; // It is a folder icon? No advantage in threading if info.SourceType = iestFolderIcon then exit; try fThreadCS.Enter(); if info.image <> nil then begin result := true; exit; end; // free no more visible requests FreeInvisibleRequests(self); if priority > -1 then priority := imax(0, imin(priority, fThreadRequests.Count-1)); // check if already requested i := IsRequested(idx); if i > -1 then begin // already requested if priority > -1 then fThreadRequests.Move(i, priority); result := true; exit; end; // check if already processing it for i := 0 to fThreadPoolIO.Count - 1 do if TImageEnIO(fThreadPoolIO[i]).Tag = idx then begin // already in progress result := true; exit; end; // free available threads FreeUseLessThreads(self); if ( info.ID > -1 ) and ( assigned( fOnImageIDRequest ) or assigned( fOnImageIDRequestEx ) or fIEMBitmap.InternalLoadImageByID_Assigned() ) then begin // request by ID, it is better to use ObtainImageNow exit; end else if info.Filename <> '' then begin // Load from 'Name'. // Add this request to the requests list. if priority > -1 then fThreadRequests.Insert(priority, pointer(idx)) else fThreadRequests.Add(pointer(idx)); result := true; exit; end; finally Windows.SetEvent(fThreadStarter.resumeEvent); fThreadCS.Leave(); end; end; {$IFDEF UNITTESTING} function TImageEnMView.UnitTesting_ObtainImageThreaded(idx: integer): boolean; begin Result := ObtainImageThreaded( idx, -1 ); end; {$ENDIF} procedure _DoubleIconSize(ABitmap: TIEBitmap); begin _IEResampleIEBitmap2(ABitmap, rfNearest, ABitmap.Width * 2, ABitmap.Width * 2, nil, nil); end; function FileOrDirExists(const FileName: string): Boolean; var Code: Integer; begin Code := GetFileAttributes(PChar(FileName)); Result := Code <> -1; end; procedure TImageEnMView.DoWrongImage(OutBitmap: TIEBitmap; idx: integer; var ASourceType : TIESourceType); var OBitmap: TIEDibBitmap; cv: TCanvas; Handled: boolean; ww, hh: integer; iImgWidth, iImgHeight: Integer; begin Handled := false; iImgHeight := ThumbSizeInfo( itsImage ).Y; iImgWidth := ThumbSizeInfo( itsImage ).X; if (ASourceType <> iestFolderIcon) and assigned(fOnWrongImage) and ( not ( ietxOnlyShowIcons in fThumbnailOptionsEx )) then begin OutBitmap.Allocate(iImgWidth, iImgHeight, ie24RGB); fOnWrongImage(self, OutBitmap, idx, Handled); if Handled then ASourceType := iestCustomImage; end; if not Handled then begin // Note: For performance reasons ASourceType may not be iestFolderIcon even for folders if ASourceType <> iestFolderIcon then ASourceType := iestFileIcon; {$ifdef VIDEO_THUMBNAILS} if SameText( ImageFilename[idx], IEF_Drives_Folder ) then begin IEGetMyComputerIcon( OutBitmap ); if fEnableImageCaching then fIconList.SaveToCache( OutBitmap, citIconOnly, ImageFilename[idx], False ); end else {$endif} if ( (ASourceType = iestFolderIcon) or (ietxShowIconForUnknownFormat in fThumbnailOptionsEx) ) and FileOrDirExists( ImageFilename[idx] ) then begin // LOAD SHELL ICON if fIconList.RetrieveFromCache(citIconOnly, ImageFilename[idx], ASourceType = iestFolderIcon, OutBitmap, True) then begin { OutBitmap now valid } end else {$IFDEF VIDEO_THUMBNAILS} if IEIsWindowsVistaOrNewer and (fIconSize in [ieicStretchHD, ieicStretchAll]) then begin IEGetJumboFileIcon(ImageFileName[idx], OutBitmap); if assigned( fOnImageOut ) then fOnImageOut( Self, idx, OutBitmap ); if fEnableImageCaching then fIconList.SaveToCache(OutBitmap, citIconOnly, ImageFilename[idx], ASourceType = iestFolderIcon); end else {$ENDIF} begin IEGetFileIcon(ImageFileName[idx], OutBitmap); if fIconSize <> ieicStandardSize then _DoubleIconSize(OutBitmap); if assigned( fOnImageOut ) then fOnImageOut( Self, idx, OutBitmap ); if fEnableImageCaching then fIconList.SaveToCache(OutBitmap, citIconOnly, ImageFilename[idx], ASourceType = iestFolderIcon); end; end else if ietxEnableInternalIcons in fThumbnailOptionsEx then begin // LOAD INTERNAL ICON if ( (ietxShowIconForUnknownFormat in fThumbnailOptionsEx) = False ) and FileOrDirExists( ImageFilename[idx] ) then begin // "Default" icon if fDefaultFileIcon = nil then fDefaultFileIcon := TIEBitmap.Create; if ( fDefaultFileIcon.Width < iImgWidth ) or ( fDefaultFileIcon.Height < iImgHeight ) then fDefaultFileIcon.LoadFromResource( HInstance, IMVRES_DEFAULT_IMAGE, RT_RCDATA, ioPNG ); OutBitmap.assign(fDefaultFileIcon); end else begin // "Broken" icon if fMissingFileIcon = nil then fMissingFileIcon := TIEBitmap.create; if fMissingFileIcon.IsEmpty then fMissingFileIcon.LoadFromResource( HInstance, IMVRES_BROKEN_IMAGE, RT_RCDATA, ioPNG ); OutBitmap.assign(fMissingFileIcon); end end else begin // JUST SHOW A QUESTION MARK OBitmap := TIEDibBitmap.Create; OBitmap.AllocateBits(iImgWidth, iImgHeight, 24); cv := TCanvas.Create; cv.Handle := OBitmap.HDC; cv.Brush.Color := clWhite; cv.Brush.Style := bsSolid; cv.FillRect(rect(0, 0, OBitmap.Width, OBitmap.Height)); cv.Font.Name := 'Arial'; cv.Font.Size := ThumbSizeInfo( itsCell ).Y; cv.Font.Style := [fsBold]; ww := cv.TextWidth('?'); hh := cv.TextHeight('?'); cv.Font.Color := clGray; cv.Brush.Style := bsClear; cv.TextOut((integer(OBitmap.Width) - ww) div 2 + 3, (integer(OBitmap.Height) - hh) div 2 + 3, '?'); cv.Font.Color := clBlue; cv.TextOut((integer(OBitmap.Width) - ww) div 2, (integer(OBitmap.Height) - hh) div 2, '?'); OutBitmap.CopyFromTDibBitmap(OBitmap); FreeAndNil(cv); FreeAndNil(OBitmap); end; end; end; procedure TImageEnMView.ThreadFinish(Sender: TObject); var io: TImageEnIO; idx, ww, hh: integer; bmp: TIEBitmap; wDummy, hDummy : Integer; ASourceType : TIESourceType; bDoResample: Boolean; begin io := Sender as TImageEnIO; ASourceType := iestDefault; if io.IEBitmap.Width = 0 then io.Aborting := True; // Deal with formats that do not require an image (meta-data only) // prepare the thumbnail in this thread (instead of in SetIEBitmapEx that must be in monothread mode) if (csDestroying in ComponentState) or (csDestroying in io.ComponentState) or (io.IEBitmap = nil) then begin fThreadCS.Enter(); try io.Tag := -1; Windows.SetEvent(fThreadStarter.resumeEvent); finally fThreadCS.Leave(); end; exit; end; if ( ietxOnlyShowIcons in fThumbnailOptionsEx ) or io.Aborting then begin fThreadCS.Enter(); try DoWrongImage(io.IEBitmap, io.Tag, ASourceType); finally fThreadCS.Leave(); end; end; if (fStoreType = ietThumb) and (GetEnableResamplingOnMinor or ( io.IEBitmap.Width > ThumbSizeInfo( itsImage ).X ) or ( io.IEBitmap.Height > ThumbSizeInfo( itsImage ).Y )) then begin if (io.IEBitmap.width = 0) or (io.IEBitmap.height = 0) then begin ww := ThumbSizeInfo( itsImage ).X; hh := ThumbSizeInfo( itsImage ).Y; end else begin IEGetFitResampleSizeWithAutoCrop( io.IEBitmap.width, io.IEBitmap.height, ThumbSizeInfo( itsImage ).X, ThumbSizeInfo( itsImage ).Y, wDummy, hDummy, fThumbnailClipping, ww, hh ); end; if GetEnableResamplingOnMinor then bDoResample := (io.IEBitmap.Width <> ww) or (io.IEBitmap.Height <> hh) else bDoResample := (io.IEBitmap.Width > ww) or (io.IEBitmap.Height > hh); if bDoResample then begin bmp := TIEBitmap.Create; bmp.allocate(ww, hh, ie24RGB); if io.IEBitmap.PixelFormat = ie1g then begin _SubResample1bitFilteredEx(io.IEBitmap, 0, 0, io.IEBitmap.width - 1, io.IEBitmap.height - 1, bmp) end else begin if (io.IEBitmap.PixelFormat <> ie24RGB) and (fThumbnailResampleFilter <> rfNone) then io.IEBitmap.PixelFormat := ie24RGB; if fThumbnailResampleFilter = rfNone then begin bmp.PixelFormat := io.IEBitmap.PixelFormat; // _IEBmpStretchEx supports multiple pixelformats, but input and output must have the same pixelformat _IEBmpStretchEx(io.IEBitmap, bmp, nil, nil); end else _ResampleEx(io.IEBitmap, bmp, nil, fThumbnailResampleFilter, nil, nil) end; if io.IEBitmap.HasAlphaChannel then begin if fThumbnailResampleFilter = rfNone then _Resampleie8g(io.IEBitmap.AlphaChannel, bmp.AlphaChannel, rfFastLinear) else _Resampleie8g(io.IEBitmap.AlphaChannel, bmp.AlphaChannel, fThumbnailResampleFilter); bmp.AlphaChannel.Full := io.IEBitmap.AlphaChannel.Full; end; end else bmp := io.IEBitmap; end else bmp := io.IEBitmap; fThreadCS.Enter(); try idx := io.Tag; if idx >= 0 then begin StripOffIOParams(self, io.Params); GetImageEnMIO.Params[idx].Assign(io.Params); fIEMBitmap.GetImageInfo( idx ).Background := io.Background; if fIEMBitmap.GetImageInfo( idx ).SourceType <> iestFolderIcon then fIEMBitmap.GetImageInfo( idx ).SourceType := ASourceType; SetIEBitmapEx(idx, bmp); ImageOriginalWidth[idx] := io.Params.OriginalWidth; ImageOriginalHeight[idx] := io.Params.OriginalHeight; if io.Params.EXIF_DateTimeOriginal2 > 0 then ImageCreateDate[idx] := io.Params.EXIF_DateTimeOriginal2; if assigned( fOnImageLoaded ) then fOnImageLoaded( self, idx ); end; if assigned(bmp) and (bmp <> io.IEBitmap) then FreeAndNil(bmp); io.Tag := -1; Windows.SetEvent(fThreadStarter.resumeEvent); finally fThreadCS.Leave(); invalidate(); end; end; constructor TIEStarter.Create; begin resumeEvent := Windows.CreateEvent(nil, false, false, nil); inherited Create(false); // create Not suspended end; destructor TIEStarter.Destroy; begin inherited; Windows.CloseHandle(resumeEvent); end; procedure TIEStarter.Execute; var info: TIEImageInfo; bmp: TIEBitmap; io: TImageEnIO; idx: integer; begin Windows.WaitForSingleObject(resumeEvent, INFINITE); while not Terminated do begin mview.fThreadCS.Enter(); try FreeUseLessThreads(mview); FreeInvisibleRequests(mview); while (not Terminated) and (mview.fThreadRequests.Count > 0) and (mview.fThreadPoolIO.Count < mview.fThreadPoolSize) do try idx := integer(mview.fThreadRequests[0]); bmp := TIEBitmap.Create; io := TImageEnIO.Create(nil); io.Tag := idx; mview.fThreadRequests.Delete(0); mview.fThreadPoolIO.add(io); io.AttachedIEBitmap := bmp; info := mview.fIEMBitmap.GetImageInfo( idx ); io.Background := info.Background; _SetLoadParams(mview, io.Params); io.OnFinishWork := mview.ThreadFinish; io.AsyncMode := true; if mview.fEnableLoadExplorerThumbnails and ( mview.fStoreType in [ ietThumb, ietFastThumb ]) and ( not ( ietxOnlyShowIcons in mview.fThumbnailOptionsEx )) {$IFDEF VIDEO_THUMBNAILS} and ExtractExplorerThumbnail( info.Filename, bmp, mview.ThumbSizeInfo( itsImage ).X, mview.ThumbSizeInfo( itsImage ).Y ) {$ENDIF} then begin if ieixWantParams in mview.fIOOptionsEx then io.ParamsFromFile( info.Filename, True ) else mview.ThreadFinish(io) end else if ietxOnlyShowIcons in mview.fThumbnailOptionsEx then begin if ieixWantParams in mview.fIOOptionsEx then io.ParamsFromFile( info.Filename, True ) else mview.ThreadFinish(io); end else {$IFDEF VIDEO_THUMBNAILS} if ( not mview.fEnableLoadExplorerThumbnails ) and ( mview.fStoreType in [ ietThumb, ietFastThumb ]) and UseThumbnailFromExplorer(info.Filename) then begin io.Aborting := not ExtractExplorerThumbnail( info.Filename, bmp, mview.ThumbSizeInfo( itsImage ).X, mview.ThumbSizeInfo( itsImage ).Y ); mview.ThreadFinish(io); end else {$ENDIF} if ( mview.fStoreType in [ ietThumb, ietFastThumb ]) and IsMetaFile( info.Filename ) then io.ImportMetafile(info.Filename, mview.ThumbSizeInfo( itsImage ).X, -1, true) else if ieixLoadOnlyByFileExt in mview.fIOOptionsEx then io.LoadFromFile( info.Filename, False ) else io.LoadFromFileAuto( info.Filename ); except // Unexpected loading exception end; finally mview.fThreadCS.Leave(); end; if (not Terminated) and (mview.fThreadRequests.Count = 0) and (mview.fThreadPoolIO.Count=0) then Windows.WaitForSingleObject(resumeEvent, INFINITE); sleep(0); // allow other threads to execute end; end; {!! TImageEnMView.TextMargin Declaration property TextMargin : integer; Description Specifies the offset from the border that the text appears: - Left and right side for all text types (or top and bottom if
is iemsFlatAndWide) - From the top for - From the bottom for Note: Setting TextMargin will automatically adjust and Default: 0 See Also - - !!} procedure TImageEnMView.SetTextMargin(v: integer); begin fTextMargin := v; // Update fTopTextHeight and fBottomTextHeight TopTextFontChange( nil ); BottomTextFontChange( nil ); Update; end; // If we are in Column mode return the height of the header area // Note: Uses InfoTextFont for header text function TImageEnMView.CurrentHeaderRowHeight : Integer; begin Result := 0; if fInfoTextHeight = CALCULATE_NOW then UpdateInfoTextHeight( True ); if ( fInfoTextHeight > 0 ) and ( fStyle = iemsColumns ) then Result := fUpperGap + fInfoTextHeight + fBottomGap + 2; end; // If the style is set to iemsFlatAndWide then there is a text block on the RHS // This function returns the width of that block, or 0 if style is not iemsFlatAndWide or iemsColumns function TImageEnMView.CurrentTextBlockWidth() : integer; var iMaxWidth: Integer; begin if ( fStyle in [ iemsFlatAndWide, iemsColumns ]) = False then Result := 0 else begin Result := fTextBlockWidth; iMaxWidth := ClientWidth - trunc(fThumbWidth * fZoom / 100.0) - 2 * fHorizBorder; if fTextBlockWidth < 0 then begin if fStyle = iemsColumns then Result := CurrentTextColumnWidths( iemtpTop ) + CurrentTextColumnWidths( iemtpBottom ) + CurrentTextColumnWidths( iemtpInfo ) else if fCurrentGridWidth = 1 then Result := iMaxWidth else Result := 3 * trunc(fThumbWidth * fZoom / 100.0 ); end; if Result > iMaxWidth then Result := iMaxWidth; end; end; {!! TImageEnMView.TextBlockWidth Declaration property TextBlockWidth : integer; Description If is set to iemsFlatAndWide or iemsColumns then all text is shown on the right-hand side of the thumbnail. iemsFlatAndWide: iemsColumns: TextBlockWidth specifies the width of the text block (Default: -1). If set to -1 then the value is automatic: - If Style is iemsColumns then the width of all columns will match the width of the control (or the width of all column if custom widths have been set) - If there is only one column ( = 1) it will match the width of the control - If there are multiple columns it will be three times the width of the thumbnail Note: The actual TextBlockWidth will be automatically adjusted to ensure it fits within the display area Example // Display detail thumbnails to the width of the control ImageEnMView1.LockUpdate; ImageEnMView1.Style := iemsFlatAndWide; ImageEnMView1.GridWidth := 1; ImageEnMView1.TextBlockWidth := -1; ImageEnMView1.UnlockUpdate; // Display detail thumbnails 300 pixels wide ImageEnMView1.LockUpdate; ImageEnMView1.Style := iemsFlatAndWide; ImageEnMView1.GridWidth := -1; ImageEnMView1.TextBlockWidth := 300 - ImageEnMView1.ThumbWidth; ImageEnMView1.UnlockUpdate; // Display columns to the width of the control ImageEnMView1.LockUpdate; ImageEnMView1.Style := iemsColumns; ImageEnMView1.TextBlockWidth := -1; ImageEnMView1.UnlockUpdate; // Display columns 300 pixels wide ImageEnMView1.LockUpdate; ImageEnMView1.Style := iemsColumns; ImageEnMView1.TextBlockWidth := 300 - ImageEnMView1.ThumbWidth; ImageEnMView1.UnlockUpdate; !!} procedure TImageEnMView.SetTextBlockWidth(v: integer); begin fTextBlockWidth := v; Update; end; {!! TImageEnMView.BottomGap Declaration property BottomGap: integer; Description Specifies the distance between the thumbnail image and its bottom border. You can use BottomGap to reserve space for painting, e.g. custom text (with ). Compatibility Notes In older versions, BottomGap would be internally increased to allow space for bottom text. This does not occur from v6.22. To maintain consistent styling, an BottomGap of more than twelve is assumed to include text space (i.e. If BottomGap <= 12: ActualGap = BottomGap + Text_Height. If BottomGap > 12: ActualGap = BottomGap Only). See Also - - !!} procedure TImageEnMView.SetBottomGap(v: integer); begin fBottomGap := v; fIconList.Clear(); Update; end; {!! TImageEnMView.UpperGap Declaration property UpperGap: integer; Description Specifies the distance between the thumbnail image and its top border. You can use UpperGap to reserve space for painting, e.g. custom text (with ). Compatibility Notes In older versions, UpperGap would be internally increased to allow space for top text. This does not occur from v6.22. To maintain consistent styling, an UpperGap of more than twelve is assumed to include text space (i.e. If UpperGap <= 12: ActualGap = UpperGap + Text_Height. If UpperGap > 12: ActualGap = UpperGap Only). See Also - - !!} procedure TImageEnMView.SetUpperGap(v: integer); begin fUpperGap := v; fIconList.Clear(); Update; end; {!! TImageEnMView.SideGap Declaration property SideGap: integer; Description Specifies the distance between the thumbnail image and the borders on the left and right. Note: Generally you will not need to use SideGap if you have enabled soft shadows which already include their own spacing. See Also - - !!} procedure TImageEnMView.SetSideGap(v: integer); begin fSideGap := v; fIconList.Clear(); Update; end; {!! TImageEnMView.Bitmap Declaration property Bitmap: TBitmap; Description The currently selected image as a TBitmap object. See Also - - !!} function TImageEnMView.GetFBitmap: TBitmap; begin result := nil; if fSelectedItem >= 0 then begin if fSelectedBitmap = nil then fSelectedBitmap := GetTIEBitmap(fSelectedItem); if assigned(fSelectedBitmap) then result := fSelectedBitmap.VclBitmap; end; end; {!! TImageEnMView.IEBitmap Declaration property IEBitmap: ; Description The currently selected image as object. See Also - - !!} function TImageEnMView.GetIEBitmap: TIEBitmap; begin if fSelectedItem >= 0 then begin if fSelectedBitmap = nil then fSelectedBitmap := GetTIEBitmap(fSelectedItem); result := fSelectedBitmap; end else result := nil; end; procedure TImageEnMView.SetMouseInteract(v: TIEMMouseInteract); begin if v <> fMouseInteract then fMouseInteract := v; end; procedure TImageEnMView.SetKeyInteract(v: TIEMKeyInteract); begin if v <> fKeyInteract then fKeyInteract := v; end; {!! TImageEnMView.ThumbnailOptionsEx Declaration property ThumbnailOptionsEx: ; Description Controls some advanced options for the display of icons and thumbnails. Default: [ietxShowIconForUnknownFormat, ietxShowIconWhileLoading, ietxEnableInternalIcons, ietxStretchSmallImages]; Note: You will need to update the display after changing ThumbnailOptionsEx, e.g. by calling ImageEnMView1.; !!} procedure TImageEnMView.SetThumbnailOptionsEx(v: TIEMThumbnailOptionsEx); begin fThumbnailOptionsEx := v; end; {!! TImageEnMView.IOOptionsEx Declaration property IOOptionsEx: ; Description Controls some advanced options for loading. Default: []; Note: You will need to update the display after changing IOOptionsEx, e.g. by calling ImageEnMView1.; !!} procedure TImageEnMView.SetIOOptionsEx(v: TIEMIOOptionsEx); begin fIOOptionsEx := v; end; function TImageEnMView.ReplaceIEMConst(const DefaultText : TIEImageEnMViewDefaultText; idx : Integer) : WideString; function ConcatAndIns(const Value1, Value2: string; const sDelimiter: string = ', '): string; begin if (Value1 <> '') and (Value2 <> '') then Result := Value1 + sDelimiter + Value2 else Result := Value1 + Value2; end; function _FileSize : string; begin Result := ''; if ImageFileSize[idx] > 0 then Result := String(IEBytesToStr2(ImageFileSize[idx])); end; function _FileCreateDate(bIncludeTime : Boolean = False) : string; var ADateTime: TDateTime; begin ADateTime := ImageCreateDate[idx]; if ADateTime < 1 then Result := '' else if bIncludeTime then Result := DateTimeToStr(ADateTime) else Result := DateToStr(ADateTime) end; function _FileEditDate(bIncludeTime : Boolean = False) : string; var ADateTime: TDateTime; begin ADateTime := ImageEditDate[idx]; if ADateTime < 1 then Result := '' else if bIncludeTime then Result := DateTimeToStr(ADateTime) else Result := DateToStr(ADateTime) end; var sDims: string; begin Result := ''; if DefaultText = iedtNone then begin { // } end else if DefaultText = iedtFilename then Result := GetDisplayName( ImageFileName[ idx ], True ) else if DefaultText = iedtFilenameNoExt then Result := IEExtractFilenameWithoutExt( GetDisplayName( ImageFilename[idx], True )) else if DefaultText = iedtFilePath then Result := IEExtractFilePathW(ImageFilename[idx]) else if DefaultText = iedtImageDimensions then begin if ImageOriginalWidth[idx] > 0 then Result := IntToStr(ImageOriginalWidth[idx]) + ' x ' + IntToStr(ImageOriginalHeight[idx]); // REMOVED 6.2.2: 1bit or 24bit only: + ' x ' + IntToStr(ImageBitCount[idx]) + 'bit'; end else if DefaultText = iedtImageDimAndSize then begin sDims := ''; if ImageOriginalWidth[idx] > 0 then sDims := IntToStr(ImageOriginalWidth[idx]) + ' x ' + IntToStr(ImageOriginalHeight[idx]); Result := ConcatAndIns(sDims, _FileSize, ', '); end else if DefaultText = iedtFileSize then Result := _FileSize else if DefaultText = iedtFileCreateDate then Result := _FileCreateDate else if DefaultText = iedtFileCreateDateTime then Result := _FileCreateDate(True) else if DefaultText = iedtFileCreateDateAndSize then Result := ConcatAndIns(_FileCreateDate, _FileSize, ', ') else if DefaultText = iedtFileEditDate then Result := _FileEditDate else if DefaultText = iedtFileEditDateTime then Result := _FileEditDate(True) else if DefaultText = iedtFileEditDateAndSize then Result := ConcatAndIns(_FileEditDate, _FileSize, ', ') else if DefaultText = iedtFileType then Result := GetImageFileType(idx) else if DefaultText = iedtFileExt then Result := Uppercase( IEExtractFileExtS( GetDisplayName( ImageFilename[idx], True ) , False )); end; function TImageEnMView.ReplaceIEMConst(const ws : WideString; idx : Integer) : WideString; var DefaultText : TIEImageEnMViewDefaultText; begin Result := ws; DefaultText := ConstToIEMDefaultText( ws ); if DefaultText <> iedtNone then Result := ReplaceIEMConst( DefaultText, idx ) else if Pos( IEM_ImageDict, Uppercase( Result )) = 1 then try // Text is $IEM_IMAGEDICT$"Key" // Remove const Delete( Result, 1, Length( IEM_ImageDict )); // Remove quotes if Result[ 1 ] = '"' then Delete( Result, 1, 1 ); if Result[ Length( Result ) ] = '"' then Delete( Result, Length( Result ), 1 ); Result := fIEMBitmap.ImageDictionary[ idx ].GetString( Result ); except // Key not found Result := ''; end; end; // info.image can be nil procedure TImageEnMView.DrawImage(DestBitmap: TBitmap; info: TIEImageInfo; IsSelected: boolean; Index: integer); const Rounded_Corner_Size = 4; var ActThumbWidth, ActThumbHeight, ActTextBlockWidth: integer; x1, y1: integer; ActUpperGap, ActBottomGap: integer; ith: integer; // infotext height bFirstTextShown: Boolean; sTopText, sInfoText, sBottomText: WideString; iOverrideThumbWidth: Integer; // special handling of thumbnail size to output at width of only the displayed text function _GetText(const Text: WideString; Position : TIEMTextPos; DefaultText: TIEImageEnMViewDefaultText) : WideString; begin Result := ReplaceIEMConst( Text, Index ); if Result = '' then Result := ReplaceIEMConst( DefaultText, Index ); if assigned( fOnGetText ) then begin fOnGetText( Self, Index, Position, Result ); Result := ReplaceIEMConst( Result, Index ); end; end; // bCalculateOnly: Returns only the width of the cell with this text function _OutputText(wsText: WideString; aFont: TFont; Position : TIEMTextPos; bCalculateOnly: Boolean = False) : Integer; const Text_Horz_Spacing = 2; var tw, th: integer; iTextMaxWidth: Integer; iTextLeft, iTextTop: Integer; aBackgroundStyle: TBrushStyle; aBGColor: TColor; aTruncSide: TIEMTruncSide; iBlockHeight: Integer; iTextOffset: Integer; fontColor: TColor; begin Result := 0; // NO TEXT? if wsText = '' then exit; DestBitmap.Canvas.Font.Assign( aFont ); aBackgroundStyle := fTextBackgroundStyle; aBGColor := GetThemeColor( ietpThumbCellBackground, fTextBackgroundColor ); aTruncSide := fTextTruncSide; if ( bCalculateOnly = False ) and assigned(fOnGetTextEx) then begin fOnGetTextEx(Self, Index, Position, wsText, DestBitmap.Canvas.Font, aBackgroundStyle, aBGColor, aTruncSide); if wsText = '' then exit; end; if Enabled = False then fontColor := GetThemeColor( ietpThumbCellFontDisabled, Text_Color_When_Disabled ) else if IsSelected then fontColor := GetThemeColor( ietpThumbCellFontSelected, fSelectedFontColor ) else fontColor := GetThemeColor( ietpThumbCellFont, aFont.Color ); if fontColor <> clNone_ then DestBitmap.Canvas.Font.Color := fontColor; DestBitmap.Canvas.Brush.Style := aBackgroundStyle; if aBackgroundStyle <> bsClear then DestBitmap.Canvas.Brush.Color := aBGColor; // Truncate wide text if CurrentTextBlockWidth = 0 then // Text not on RHS iTextMaxWidth := ActThumbWidth - 2 * fTextMargin - Text_Horz_Spacing else if fStyle = iemsColumns then begin iTextMaxWidth := CurrentTextColumnWidths( Position ) - fTextMargin; if bFirstTextShown = False then dec( iTextMaxWidth, fTextMargin ); // need leading gap too end else iTextMaxWidth := CurrentTextBlockWidth - 2 * fTextMargin; if iTextMaxWidth <= 0 then exit; wsText := IETruncateStr(wsText, aTruncSide, DestBitmap.Canvas, iTextMaxWidth); tw := IETextWidthW( DestBitmap.Canvas, wsText ); th := IETextHeightW( DestBitmap.Canvas, wsText ); // iemsFlat and iemsACD if CurrentTextBlockWidth = 0 then // Text not on RHS begin iTextLeft := 1 + x1 + (ActThumbWidth - tw - 2) div 2; case Position of iemtpTop : iTextTop := y1 + fTextMargin; iemtpInfo : iTextTop := y1 + ActThumbHeight - ActBottomGap - ith; else { iemtpBottom } iTextTop := y1 + ActThumbHeight - th - 1 - fTextMargin; end; end else if fStyle = iemsColumns then begin iTextLeft := x1 + ActThumbWidth - ActTextBlockWidth; if bFirstTextShown = False then Inc( iTextLeft, fTextMargin ); // need leading gap too if Position in [ iemtpBottom, iemtpInfo ] then inc( iTextLeft, CurrentTextColumnWidths( iemtpTop )); if Position in [ iemtpInfo ] then inc( iTextLeft, CurrentTextColumnWidths( iemtpBottom )); iTextTop := y1 + ( ActThumbHeight - th ) div 2; end else // iemsFlatAndWide begin iTextLeft := x1 + ActThumbWidth + fTextMargin - ActTextBlockWidth; iBlockHeight := ( ActThumbHeight - 2 * fTextMargin ) div 3; iTextOffset := ( iBlockHeight - th ) div 2; // Overlapping existing text? Reduce number of text blocks if ( iTextOffset < 0 ) and ( Position <> iemtpBottom ) then begin iBlockHeight := ( ActThumbHeight - 2 * fTextMargin ) div 2; iTextOffset := ( iBlockHeight - th ) div 2; if ( iTextOffset < 0 ) and ( Position = iemtpTop ) then begin iBlockHeight := ( ActThumbHeight - 2 * fTextMargin ) div 1; iTextOffset := ( iBlockHeight - th ) div 2; end; end; // Still overlapping? Hide text if ( iTextOffset < 0 ) then begin if bFirstTextShown then exit else iTextOffset := 0; end; case Position of iemtpTop : iTextTop := y1 + fTextMargin + iTextOffset; iemtpInfo : iTextTop := y1 + fTextMargin + iBlockHeight + iTextOffset; else { iemtpBottom } if bFirstTextShown = False then iTextTop := y1 + ( ActThumbHeight - th ) div 2 // Vertically center it else iTextTop := y1 + fTextMargin + 2 * iBlockHeight + iTextOffset; end; end; if bCalculateOnly then Result := iTextLeft + tw + fSideGap - x1 else begin TextOutW(DestBitmap.Canvas.Handle, iTextLeft, iTextTop, @wsText[1], length(wsText)); if fStyle = iemsACD then IEDraw3DRect(DestBitmap.Canvas, iTextLeft - 2, iTextTop, iTextLeft + tw + 1, iTextTop + th, clGray, clWhite); end; bFirstTextShown := True; end; // Return the minimum width of the thumbnail cell, if we cut it after the text function _GetMinimumThumbWidth(): integer; var iWidth, iTotalWidth: Integer; begin Result := 0; iTotalWidth := 0; iWidth := _OutputText( sTopText, TopTextFont, iemtpTop, True ); if iWidth > iTotalWidth then iTotalWidth := iWidth; iWidth := _OutputText( sInfoText, InfoTextFont, iemtpInfo, True ); if iWidth > iTotalWidth then iTotalWidth := iWidth; iWidth := _OutputText( sBottomText, BottomTextFont, iemtpBottom, True ); if iWidth > iTotalWidth then iTotalWidth := iWidth; if ( iTotalWidth > 0 ) and ( iTotalWidth < ActThumbWidth ) then Result := iTotalWidth; end; var w, ww, hh, iw, ih, t1: integer; cx1, cy1: integer; iDrawImgW, iDrawImgH : integer; pix, alpha: pbyte; iebmp, ietmp: TIEBitmap; filt: TResampleFilter; backgroundColor: TColor; ThumbRect: TRect; ox, oy: Integer; iec: TIECanvas; iSoftShadowSize : Integer; iFinalww, iFinalhh : Integer; iThumbClipPercent: Integer; bStretchSmallImages : Boolean; bDoubleIconSize: Boolean; bAddSoftShadow: Boolean; borderWidth : integer; begin try fThreadCS.Enter(); if fTopTextHeight = CALCULATE_NOW then UpdateTopTextHeight( True ); if fInfoTextHeight = CALCULATE_NOW then UpdateInfoTextHeight( True ); if fBottomTextHeight = CALCULATE_NOW then UpdateBottomTextHeight( True ); if CurrentTextBlockWidth > 0 then // Text is on RHS of thumbnail begin ActUpperGap := (fUpperGap + fBottomGap ) div 2; ActBottomGap := ActUpperGap; end else if fShowText then begin {$ifdef IEIncludeDeprecatedInV6} // Legacy Handling - Prior to v6.2.2 UpperGap was enlarged to handle text height if fUpperGap > 12 then ActUpperGap := fUpperGap else {$endif} ActUpperGap := fUpperGap + fTopTextHeight; {$ifdef IEIncludeDeprecatedInV6} // Legacy Handling - Prior to v6.2.2 BottomGap was enlarged to handle text height if fBottomGap > 12 then ActBottomGap := fBottomGap else {$endif} ActBottomGap := fBottomGap + fBottomTextHeight end else begin ActUpperGap := fUpperGap; ActBottomGap := fBottomGap; end; ActThumbWidth := ThumbSizeInfo( itsCell ).X; ActThumbHeight := ThumbSizeInfo( itsCell ).Y; iOverrideThumbWidth := 0; ActTextBlockWidth := CurrentTextBlockWidth; x1 := info.X - fViewX; y1 := info.Y - fViewY; if assigned(fOnBeforeImageDraw) then fOnBeforeImageDraw(self, Index, x1, y1, DestBitmap.Canvas); if assigned(fThumbnailFrame) and assigned(fThumbnailFrameSelected) then begin ThumbRect := fThumbnailFrameRect; if IsSelected then fThumbnailFrameSelected.RenderToTBitmapEx(DestBitmap, x1, y1, ActThumbWidth - ActTextBlockWidth, ActThumbHeight, 0, 0, fThumbnailFrameSelected.Width, fThumbnailFrameSelected.Height) else fThumbnailFrame.RenderToTBitmapEx(DestBitmap, x1, y1, ActThumbWidth - ActTextBlockWidth, ActThumbHeight, 0, 0, fThumbnailFrame.Width, fThumbnailFrame.Height); ActThumbWidth := ThumbRect.Right - ThumbRect.Left; ActThumbHeight := ThumbRect.Bottom - ThumbRect.Top; inc(x1, ThumbRect.Left); inc(y1, ThumbRect.Top); end; if assigned(fOnBeforeImageDrawEx) then begin ThumbRect.Left := 0; ThumbRect.Top := 0; ThumbRect.Right := ActThumbWidth; ThumbRect.Bottom := ActThumbHeight; fOnBeforeImageDrawEx(self, Index, x1, y1, DestBitmap, ThumbRect); ActThumbWidth := ThumbRect.Right - ThumbRect.Left; ActThumbHeight := ThumbRect.Bottom - ThumbRect.Top; inc(x1, ThumbRect.Left); inc(y1, ThumbRect.Top); end; ith := 0; if fShowText and ( CurrentTextBlockWidth = 0 ) then ith := fInfoTextHeight; iDrawImgH := ActThumbHeight - ActBottomGap - ActUpperGap - ith; iDrawImgW := ActThumbWidth - ActTextBlockWidth - 2 * fSideGap; cx1 := 0; cy1 := 0; ww := 0; hh := 0; if fShowText then begin bFirstTextShown := False; // TOP TEXT sTopText := _GetText(info.TopText, iemtpTop, fDefaultTopText ); // INFO TEXT sInfoText := _GetText(info.InfoText, iemtpInfo, fDefaultInfoText ); // BOTTOM sBottomText := _GetText(info.BottomText, iemtpBottom, fDefaultBottomText ); if fModernStyling and ( fStyle = iemsFlatAndWide ) and ( fThumbnailsBorderWidth = 0 ) then iOverrideThumbWidth := _GetMinimumThumbWidth(); end; if fFillThumbnail then begin // Image is background if fDrawImageBackground then backgroundColor := info.Background else // Normal (Unselected) if IsSelected = False then backgroundColor := GetThemeColor( ietpThumbCellBackground, fThumbnailsBackground ) else // Selected if Enabled then backgroundColor := GetThemeColor( ietpThumbCellBackgroundSelected, fThumbnailsBackgroundSelected ) else // Control Disabled backgroundColor := GetThemeColor( ietpThumbCellBackgroundDisabledSelected, Thumbnail_Background_When_Disabled ); if iOverrideThumbWidth = 0 then iOverrideThumbWidth := ActThumbWidth; if fThumbnailsBorderCurved and ( fThumbnailsBackgroundStyle = iebsSolid ) then begin DestBitmap.Canvas.Pen.Style := psClear; DestBitmap.Canvas.Brush.Color := backgroundColor; DestBitmap.Canvas.Brush.Style := bsSolid; DestBitmap.Canvas.RoundRect( x1, y1, x1 + iOverrideThumbWidth + 1, y1 +ActThumbHeight + 1, Rounded_Corner_Size, Rounded_Corner_Size ); DestBitmap.Canvas.Pen.Style := psSolid; end else IEDrawBackground([], DestBitmap.Canvas, DestBitmap, fThumbnailsBackgroundStyle, backgroundColor, x1, y1, iOverrideThumbWidth, ActThumbHeight, x1, y1, x1 + iOverrideThumbWidth, y1 + ActThumbHeight, fChessboardSize, fChessboardBrushStyle, fChessboardColor2Customized, GetThemeColor( ietpControlBackgroundGradientEnd, fGradientEndColor ), nil, iewoNormal, nil); end; // paint the image if (info.cacheImage = nil) and (info.image <> nil) then begin // cache empty iw := fIEMBitmap.fImageList.GetImageWidth(info.image); ih := fIEMBitmap.fImageList.GetImageHeight(info.image); if (iw < 1) or (ih < 1) then pix := nil else pix := fIEMBitmap.fImageList.GetImageBits(info.image); alpha := fIEMBitmap.fImageList.GetAlphaBits(info.image); iSoftShadowSize := 0; bAddSoftShadow := False; if fSoftShadow.Enabled then case info.SourceType of iestFolderIcon : bAddSoftShadow := ietxShowShadowForFolders in fThumbnailOptionsEx; iestFileIcon : bAddSoftShadow := ietxShowShadowForIcons in fThumbnailOptionsEx; else bAddSoftShadow := True; end; if bAddSoftShadow then iSoftShadowSize := IESoftShadowSize(fSoftShadow.Radius, fSoftShadow.OffsetX, fSoftShadow.OffsetY); if ( iSoftShadowSize > ActThumbHeight div 2 ) and ( ActThumbHeight < 50 ) then // No soft shadow for very small images iSoftShadowSize := 0; iThumbClipPercent := 0; if (fThumbnailClipping > 0) and (info.SourceType in [iestDefault, iestCustomImage]) then iThumbClipPercent := fThumbnailClipping; IEGetFitResampleSizeWithAutoCrop(iw, ih, iDrawImgW - iSoftShadowSize, iDrawImgH - iSoftShadowSize, iFinalww, iFinalhh, iThumbClipPercent, ww, hh); bStretchSmallImages := False; bDoubleIconSize := False; if (info.SourceType in [iestFileIcon, iestFolderIcon]) = False then bStretchSmallImages := GetEnableResamplingOnMinor else if IEIsWindowsVistaOrNewer and (fIconSize in [ieicStretchHD, ieicStretchAll]) then begin if ((iw > 32) and (ih > 32)) // HD Icon? or (fIconSize = ieicStretchAll) then // Always stretch bStretchSmallImages := True else bDoubleIconSize := ( iw * 2 < ww ) and ( ih * 2 < hh ) ; end; if (bStretchSmallImages = False) and (iw < iDrawImgW - iSoftShadowSize) and (ih < iDrawImgH - iSoftShadowSize) then begin ww := iw; hh := ih; iFinalww := iw; iFinalhh := ih; end; if pix <> nil then begin ietmp := TIEBitmap.Create; ietmp.EncapsulateMemory(pix, iw, ih, fIEMBitmap.fImageList.GetImagePixelFormat(info.image), false); if alpha <> nil then begin ietmp.AlphaChannel.EncapsulateMemory(alpha, iw, ih, ie8g, true); ietmp.AlphaChannel.Full := false; end; if ietmp.PixelFormat = ie8p then CopyMemory(ietmp.PaletteBuffer, fIEMBitmap.fImageList.GetImagePalette(info.image), 256*SizeOf(TRGB)); if assigned( fOnImageOut ) then begin fOnImageOut( Self, Index, ietmp ); // Note: skip edge case: bStretchSmallImages = False if ( ietmp.Width <> iw ) or ( ietmp.Height <> ih ) then IEGetFitResampleSizeWithAutoCrop(ietmp.Width, ietmp.Height, iDrawImgW - iSoftShadowSize, iDrawImgH - iSoftShadowSize, iFinalww, iFinalhh, iThumbClipPercent, ww, hh); end; iebmp := TIEBitmap.Create; iebmp.Location := ieMemory; if (ietmp.PixelFormat = ie1g) and ((ww < iw) or (hh < ih)) then begin filt := rfFastLinear; iebmp.Allocate(ww, hh, ie24RGB); end else begin filt := fThumbnailDisplayFilter; iebmp.Allocate(ww, hh, ietmp.PixelFormat); end; // Draw Wang and ImageEn annotations? if fAnnotationsVisible and (fStoreType <> ietThumb) then begin iebmp.Assign( ietmp ); if GetImageEnMIO.Params[ Index ].ImageEnAnnot.IsEmpty = False then GetImageEnMIO.Params[ Index ].ImageEnAnnot.DrawToBitmap( iebmp, True ); {$ifdef IEINCLUDEIMAGINGANNOT} if GetImageEnMIO.Params[ Index ].ImagingAnnot.ObjectsCount > 0 then GetImageEnMIO.Params[ Index ].ImagingAnnot.DrawToBitmap( iebmp, True ); {$endif} _IEResampleIEBitmap2(iebmp, filt, ww, hh, nil, nil); end else _IEResampleIEBitmap(ietmp, iebmp, filt, nil, nil); if (iFinalww <> iebmp.Width) or (iFinalhh <> iebmp.Height) then begin iebmp.Resize(iFinalww, iFinalhh, 0, 255, iehCenter, ievCenter); ww := iebmp.Width; hh := iebmp.Height; end else if bDoubleIconSize then begin _DoubleIconSize(iebmp); ww := iebmp.Width; hh := iebmp.Height; end; if fThumbsRounded > 0 then begin t1 := imin(ActThumbWidth - ActTextBlockWidth, ActThumbHeight) div fThumbsRounded; _IERoundImage(iebmp, t1, t1, nil, nil); end; // draw shadow if iSoftShadowSize > 0 then begin // deflate ww and hh to correct thumb size ww := ww + iSoftShadowSize; hh := hh + iSoftShadowSize; with info.internalrect do begin ox := (ww - iebmp.Width) div 2; oy := (hh - iebmp.Height) div 2; Left := ox; Top := oy; Right := trunc(iebmp.Width + ox) + 1; Bottom := trunc(iebmp.Height + oy) + 1; end; // APPLY SHADOW _IEAddSoftShadow(iebmp, fSoftShadow.Radius, fSoftShadow.OffsetX, fSoftShadow.OffsetY, fSoftShadow.Intensity, true, fSoftShadow.ShadowColor, nil, nil); end else begin info.internalrect := Rect(0, 0, ww, hh); end; cx1 := x1 + (abs(ActThumbWidth - iebmp.Width) - ActTextBlockWidth) div 2; cy1 := y1 + ActUpperGap + (abs(iDrawImgH - iebmp.Height)) div 2; iebmp.RenderToTBitmapEx(DestBitmap, cx1, cy1, ww, hh, 0, 0, iebmp.Width, iebmp.Height, fEnableAlphaChannel, 255, filt, ielNormal); if fEnableImageCaching then begin info.cacheImage := fCacheList.AddIEBitmap( iebmp ); fCacheList.SetImageOriginalWidth ( info.cacheImage, fIEMBitmap.fImageList.GetImageOriginalWidth ( info.image )); fCacheList.SetImageOriginalHeight( info.cacheImage, fIEMBitmap.fImageList.GetImageOriginalHeight( info.image )); if fImageCacheReusage = iecrStrict then fCacheList.SetImageIdentifier( info.cacheImage, IntToStr( Index ) + '/' +info.Filename ) else fCacheList.SetImageIdentifier( info.cacheImage, info.Filename ); if StoreType = ietFastThumb then begin fIEMBitmap.fImageList.Delete(info.image); info.image := nil; end; end; FreeAndNil(ietmp); FreeAndNil(iebmp); end; end else if info.cacheImage <> nil then begin // use cached image ww := fCacheList.GetImageWidth(info.cacheImage); hh := fCacheList.GetImageHeight(info.cacheImage); cx1 := x1 + abs(ActThumbWidth - ww - ActTextBlockWidth) div 2; cy1 := y1 + ActUpperGap + abs(iDrawImgH - hh) div 2; pix := fCacheList.GetImageBits(info.cacheImage); alpha := fCacheList.GetAlphaBits(info.cacheImage); ietmp := TIEBitmap.Create; ietmp.EncapsulateMemory(pix, ww, hh, fCacheList.GetImagePixelFormat(info.cacheImage), false); if ietmp.PixelFormat = ie8p then CopyMemory(ietmp.PaletteBuffer, fCacheList.GetImagePalette(info.cacheImage), 256*SizeOf(TRGB)); if alpha <> nil then begin ietmp.AlphaChannel.EncapsulateMemory(alpha, ww, hh, ie8g, true); ietmp.AlphaChannel.Full := false; end; ietmp.RenderToTBitmapEx(DestBitmap, cx1, cy1, ww, hh, 0, 0, ietmp.Width, ietmp.Height); FreeAndNil(ietmp); end else if ( ietxEnableInternalIcons in fThumbnailOptionsEx ) and ((( ietxShowIconWhileLoading in fThumbnailOptionsEx ) = False ) or // Don't show load icons ( ImageFilename[ Index ] = '' )) then // Don't have a file begin // Load embedded "Default" icon if fDefaultFileIcon = nil then fDefaultFileIcon := TIEBitmap.Create; if ( fDefaultFileIcon.Width <> iDrawImgW ) or ( fDefaultFileIcon.Height <> iDrawImgH ) then begin // Load our "Default" icon from the application resource and resize it fDefaultFileIcon.LoadFromResource( HInstance, 1000, RT_RCDATA, ioPNG ); IEGetFitResampleSize( fDefaultFileIcon.Width, fDefaultFileIcon.Height, iDrawImgW, iDrawImgH, ww, hh ); _IEResampleIEBitmap2( fDefaultFileIcon, fThumbnailDisplayFilter, ww, hh, nil, nil ); end; cx1 := x1 + abs(ActThumbWidth - ActTextBlockWidth - fDefaultFileIcon.width) div 2; cy1 := y1 + ActUpperGap + abs(iDrawImgH - fDefaultFileIcon.height) div 2; ww := fDefaultFileIcon.Width; hh := fDefaultFileIcon.Height; fDefaultFileIcon.RenderToTBitmapEx(DestBitmap, cx1, cy1, ww, hh, 0, 0, fDefaultFileIcon.Width, fDefaultFileIcon.Height); end else if ( ImageFilename[ Index ] <> '' ) and ( ietxShowIconWhileLoading in fThumbnailOptionsEx ) then begin // display shell icon while we are loading if fIconList.RetrieveFromCache(citFullDraw, ImageFilename[Index], info.SourceType = iestFolderIcon, ietmp, False) then begin // Ietmp now points to a valid icon image (DON'T FREE) cx1 := x1 + abs(ActThumbWidth - ActTextBlockWidth - ietmp.width) div 2; cy1 := y1 + ActUpperGap + abs(iDrawImgH - ietmp.height) div 2; ww := ietmp.Width; hh := ietmp.Height; ietmp.RenderToTBitmapEx(DestBitmap, cx1, cy1, ww, hh, 0, 0, ietmp.Width, ietmp.Height); end else begin ietmp := TIEBitmap.Create; // Create icon image if info.SourceType = iestFolderIcon then bStretchSmallImages := IEIsWindowsVistaOrNewer and (fIconSize in [ieicStretchHD, ieicStretchAll]) else bStretchSmallImages := IEIsWindowsVistaOrNewer and (fIconSize = ieicStretchAll); IEGetFileIcon(ImageFilename[Index], ietmp); if (bStretchSmallImages = False) and (fIconSize <> ieicStandardSize) then _DoubleIconSize(ietmp); if assigned( fOnImageOut ) then fOnImageOut( Self, Index, ietmp ); iSoftShadowSize := 0; if fSoftShadow.Enabled and (info.SourceType <> iestFolderIcon) then iSoftShadowSize := IESoftShadowSize(fSoftShadow.Radius, fSoftShadow.OffsetX, fSoftShadow.OffsetY); if ( iSoftShadowSize > ActThumbHeight div 2 ) and ( ActThumbHeight < 50 ) then // No soft shadow for very small images iSoftShadowSize := 0; IEGetFitResampleSize(ietmp.Width, ietmp.Height, iDrawImgW - iSoftShadowSize, iDrawImgH - iSoftShadowSize, ww, hh); if (bStretchSmallImages = False) and ((ietmp.Width < iDrawImgW - iSoftShadowSize) or (ietmp.Height < iDrawImgH - iSoftShadowSize)) then begin ww := ietmp.Width; hh := ietmp.Height; end; _IEResampleIEBitmap2(ietmp, fThumbnailDisplayFilter, ww, hh, nil, nil); if iSoftShadowSize > 0 then begin // deflate ww and hh to correct thumb size ww := ww + iSoftShadowSize; hh := hh + iSoftShadowSize; // APPLY SHADOW _IEAddSoftShadow(ietmp, fSoftShadow.Radius, fSoftShadow.OffsetX, fSoftShadow.OffsetY, fSoftShadow.Intensity, true, fSoftShadow.ShadowColor, nil, nil); end; cx1 := x1 + (abs(ActThumbWidth - ww) - ActTextBlockWidth) div 2; cy1 := y1 + ActUpperGap + (abs(iDrawImgH - hh)) div 2; // Now save it to our cache for next time if fEnableImageCaching then fIconList.SaveToCache(ietmp, citFullDraw, ImageFilename[Index], info.SourceType = iestFolderIcon); ietmp.RenderToTBitmapEx(DestBitmap, cx1, cy1, ww, hh, 0, 0, ietmp.Width, ietmp.Height); FreeAndNil(ietmp); end; end; if ((info.image <> nil) or (info.cacheImage <> nil)) and (( cx1 <> 0 ) and (cy1 <> 0 )) then // 6.2.2 if info.image is not nil, but image is invalid (pix = nil) then we blank out areas of grid begin if fThumbnailsInternalBorder and not (info.SourceType in [iestFileIcon, iestFolderIcon]) then begin DestBitmap.Canvas.Pen.Color := fThumbnailsInternalBorderColor; DestBitmap.Canvas.Pen.Width := 1; DestBitmap.Canvas.Pen.Style := psSolid; DestBitmap.Canvas.Brush.Style := bsClear; with info.internalrect do DestBitmap.Canvas.Rectangle(cx1 + Left, cy1 + Top, cx1 + Right, cy1 + Bottom); end; { // REMOVED 7.0.0 // draw sides background (the area of the thumbnail where hte image is not painted) if fFillThumbnail then with DestBitmap.canvas do begin Brush.Color := backgroundColor; if iOverrideThumbWidth = 0 then iOverrideThumbWidth := ActThumbWidth; Brush.Style := bsSolid; FillRect(rect(x1, y1, cx1, y1 + ActThumbHeight)); // left FillRect(rect(cx1 + ww, y1, x1 + iOverrideThumbWidth, y1 + ActThumbHeight)); // right FillRect(rect(cx1, y1, cx1 + ww, cy1)); // up FillRect(rect(cx1, cy1 + hh, cx1 + ww, y1 + ActThumbHeight)); // bottom end; } end; // Draw top, bottom, info texts if fShowText then begin bFirstTextShown := False; // TOP TEXT _OutputText( sTopText, TopTextFont, iemtpTop ); // INFO TEXT _OutputText( sInfoText, InfoTextFont, iemtpInfo ); // BOTTOM _OutputText( sBottomText, BottomTextFont, iemtpBottom ); end; // iemsACD style if fStyle = iemsACD then IEDraw3DRect(DestBitmap.Canvas, cx1, cy1, cx1 + ww - 1, cy1 + hh - 1, clGray, clWhite); // 3D rect around the image // Draw Checkbox DrawCheckbox(DestBitmap.Canvas, Index, Rect(x1, y1, x1 + ActThumbWidth, y1 + ActThumbHeight), IsSelected); // call OnImageDraw if assigned(fOnImageDraw) then fOnImageDraw(self, Index, x1, y1, DestBitmap.Canvas); // call OnImageDraw2 if assigned(fOnImageDraw2) then fOnImageDraw2(self, Index, x1, y1, Rect(cx1, cy1, cx1+ww, cy1+hh), DestBitmap.Canvas); // THUMBNAIL BORDER if IsSelected and Focused and ( fSelectionBorderWidth > -1 ) then borderWidth := fSelectionBorderWidth else if IsSelected and ( fSelectionBorderWidthNoFocus > -1 ) then borderWidth := fSelectionBorderWidthNoFocus else borderWidth := fThumbnailsBorderWidth; if ( borderWidth > 0 ) {$ifndef OCXVERSION}and (not assigned(fOnBeforeImageDrawEx)){$endif} and ((fThumbnailFrame=nil) or (fThumbnailFrameSelected=nil)) then begin iec := TIECanvas.Create(DestBitmap.Canvas, true, true); // TIECanvas used to anti-alias the result look for -1 if Enabled = False then iec.Pen.Color := GetThemeColor( ietpThumbCellBorderDisabled, Thumbnail_Border_When_Disabled ) else if IsSelected then iec.Pen.Color := GetThemeColor( ietpThumbCellBorderSelected, fThumbnailsSelectedBorderColor ) else iec.Pen.Color := GetThemeColor( ietpThumbCellBorder, fThumbnailsBorderColor ); iec.Brush.Style := bsClear; if iOverrideThumbWidth = 0 then iOverrideThumbWidth := ActThumbWidth; if fThumbnailsBorderCurved then begin iec.Pen.Width := borderWidth; if borderWidth > 0 then iec.RoundRect(x1 - borderWidth div 2, y1 - borderWidth div 2, x1 + iOverrideThumbWidth + borderWidth div 2, y1 + ActThumbHeight + borderWidth div 2, Rounded_Corner_Size, Rounded_Corner_Size); end else begin iec.Pen.Width := 1; for w := 1 to borderWidth do iec.Rectangle(x1 - w, y1 - w, x1 + iOverrideThumbWidth + w, y1 + ActThumbHeight + w); end; iec.Free; end; finally fThreadCS.Leave(); end; end; // Return a description (Caption for column header) for a default text type function IEMDefaultTextToStr(DefaultText: TIEImageEnMViewDefaultText): string; begin case DefaultText of iedtFilename, iedtFilenameNoExt : Result := iemsg( IEMsg_Filename ); iedtFilePath : Result := iemsg( IEMsg_Path ); iedtImageDimensions : Result := iemsg( IEMsg_ImageSize ); iedtImageDimAndSize : Result := iemsg( IEMsg_ImageProperties ); iedtFileSize : Result := iemsg( IEMsg_FileSize ); iedtFileCreateDate, iedtFileCreateDateTime, iedtFileCreateDateAndSize : Result := iemsg( IEMsg_CreateDate ); iedtFileEditDate, iedtFileEditDateTime, iedtFileEditDateAndSize : Result := iemsg( IEMsg_EditDate ); iedtFileType, iedtFileExt : Result := iemsg( IEMsg_FileType ); // Handle custom captions else { iedtNone } Result := iemsg( IEMsg_Caption ); end; end; // Used when fStyle is iemsColumns to draw a header (fixed) row at the top of the window procedure TImageEnMView.DrawColumnsHeaderRow(DestBitmap: TBitmap); var ActThumbWidth, ActThumbHeight, ActTextBlockWidth: integer; bFirstTextShown: Boolean; iHeadHeight: Integer; procedure _OutputText(DefaultText: TIEImageEnMViewDefaultText; Position : TIEMTextPos); var th: integer; iTextMaxWidth: Integer; iTextLeft, iTextTop: Integer; aBackgroundStyle: TBrushStyle; aBGColor: TColor; aTruncSide: TIEMTruncSide; wsText: WideString; begin wsText := IEMDefaultTextToStr( DefaultText ); if assigned( fOnGetText ) then fOnGetText( Self, -1, Position, wsText ); // NO TEXT??? if wsText = '' then begin fTextColsCurrentRight[ Position ] := 0; exit; end; DestBitmap.Canvas.Font.Assign( InfoTextFont ); // InfoTextFont used for all header captions aBackgroundStyle := fTextBackgroundStyle; aBGColor := GetThemeColor( ietpThumbCellBackground, fTextBackgroundColor ); aTruncSide := fTextTruncSide; if assigned(fOnGetTextEx) then begin fOnGetTextEx(Self, -1, Position, wsText, DestBitmap.Canvas.Font, aBackgroundStyle, aBGColor, aTruncSide); if wsText = '' then exit; end; iTextLeft := ActThumbWidth - ActTextBlockWidth; if Enabled = False then DestBitmap.Canvas.Font.Color := Text_Color_When_Disabled; DestBitmap.Canvas.Brush.Style := aBackgroundStyle; if aBackgroundStyle <> bsClear then DestBitmap.Canvas.Brush.Color := aBGColor; // Truncate wide text iTextMaxWidth := CurrentTextColumnWidths( Position ) - fTextMargin; if bFirstTextShown = False then dec( iTextMaxWidth, fTextMargin ); // need leading gap too if iTextMaxWidth <= 0 then begin fTextColsCurrentRight[ Position ] := iTextLeft; exit; end; wsText := IETruncateStr(wsText, aTruncSide, DestBitmap.Canvas, iTextMaxWidth); th := IETextHeightW( DestBitmap.Canvas, wsText ); if bFirstTextShown = False then Inc( iTextLeft, fTextMargin ); // need leading gap too if Position in [ iemtpBottom, iemtpInfo ] then inc( iTextLeft, CurrentTextColumnWidths( iemtpTop )); if Position in [ iemtpInfo ] then inc( iTextLeft, CurrentTextColumnWidths( iemtpBottom )); iTextTop := ( ActThumbHeight - th ) div 2; // For TImageEnFolderMView, draw a chevron to indicate sort order DrawColumnsHeaderRowCell( DestBitmap.Canvas, Rect( iTextLeft, 0, iTextLeft + iTextMaxWidth, ActThumbHeight ), Position ); TextOutW(DestBitmap.Canvas.Handle, iTextLeft, iTextTop, @wsText[1], length(wsText)); bFirstTextShown := True; fTextColsCurrentRight[ Position ] := iTextLeft + iTextMaxWidth; end; begin iHeadHeight := CurrentHeaderRowHeight; if iHeadHeight = 0 then exit; ActThumbWidth := ThumbSizeInfo( itsCell ).X; ActThumbHeight := iHeadHeight; ActTextBlockWidth := CurrentTextBlockWidth; if fFillThumbnail then IEDrawBackground([], DestBitmap.Canvas, DestBitmap, fBackgroundStyle, GetThemeColor( ietpControlBackground, Background ), 0, 0, ActThumbWidth, ActThumbHeight, 0, 0, ActThumbWidth, ActThumbHeight, fChessboardSize, fChessboardBrushStyle, fChessboardColor2Customized, GetThemeColor( ietpControlBackgroundGradientEnd, fGradientEndColor ), nil, iewoNormal, nil); if fShowText then begin bFirstTextShown := False; // TOP TEXT _OutputText( fDefaultTopText, iemtpTop ); // INFO TEXT _OutputText( fDefaultInfoText, iemtpInfo ); // BOTTOM _OutputText( fDefaultBottomText, iemtpBottom ); end; end; {!! TImageEnMView.IsVisible Declaration function IsVisible(idx: Integer): Boolean; Description Returns True if image, idx, is currently visible (i.e. not scrolled out of view). Note: The result may not be valid if the control is not visible. Call Update() prior to IsVisible if you need to calculate for a non-visible control. See Also - !!} function TImageEnMView.IsVisible(idx: integer): boolean; var x1, y1: integer; info: TIEImageInfo; begin info := fIEMBitmap.GetImageInfo( idx ); x1 := info.X - fViewX; y1 := info.Y - fViewY; result := _RectXRect(0, 0, width - 1, height - 1, x1, y1, x1 + ThumbSizeInfo( itsCell ).X - 1, y1 + ThumbSizeInfo( itsCell ).Y - 1); end; function TImageEnMView.IsLookAhead(idx: Integer): Boolean; begin result := fLookAheadList.IndexOf(pointer(idx)) > -1; end; procedure TImageEnMView.PaintBackgroundTo(DestBitmap: TBitmap); begin // draw global background IEDrawBackground([], DestBitmap.Canvas, DestBitmap, fBackgroundStyle, GetThemeColor( ietpControlBackground, fBackground ), 0, 0, ClientWidth, ClientHeight, 0, 0, 0, 0, fChessboardSize, fChessboardBrushStyle, fChessboardColor2Customized, GetThemeColor( ietpControlBackgroundGradientEnd, fGradientEndColor ), nil, iewoNormal, nil); // draw wallpaper if assigned(fWallpaper.Graphic) then case fWallpaperStyle of iewoNormal : DestBitmap.Canvas.Draw(0, 0, fWallpaper.Graphic); iewoStretch : DestBitmap.Canvas.StretchDraw(rect(0, 0, ClientWidth, ClientHeight), fWallpaper.Graphic); iewoTile : TileBitmapOntoCanvas( DestBitmap.Canvas, ClientWidth, ClientHeight, fWallpaper.Graphic ); end; end; {!! TImageEnMView.PaintTo Declaration procedure PaintTo(Canvas: TBitmap); virtual; Description Output the current view to a bitmap !!} procedure TImageEnMView.PaintTo(DestBitmap: TBitmap); var q, ne, nn, e: integer; info: TIEImageInfo; reloop: boolean; xsel: boolean; // true if display as selected firstvisible, lastvisible: Integer; oldalldisplayed: Boolean; displayPriority: Integer; begin PaintBackgroundTo(DestBitmap); displayPriority := 0; repeat reloop := false; if (fDisplayMode = mdSingle) and (fIEMBitmap.Count > 0) then ne := 1 // one image at the time else ne := fIEMBitmap.Count; if fPlaying or (fDisplayMode = mdSingle) then begin if fFrame >= fIEMBitmap.Count then fFrame := fIEMBitmap.Count - 1; if fFrame < 0 then fFrame := 0; q := fFrame; end else q := 0; oldalldisplayed := fAllDisplayed; fAllDisplayed := true; firstvisible := -1; lastvisible := fIEMBitmap.Count-1; for nn := 0 to ne - 1 do begin if assigned(fOnDrawProgress) and (ne > 1) then fOnDrawProgress(Self, trunc(nn / ne * 100), q); info := fIEMBitmap.GetImageInfo( q ); // check that the image is visible if IsVisible(q) then begin if firstvisible = -1 then firstvisible := q; // try to obtain the image if not available if (info.image = nil) and (info.cacheImage = nil) then begin oldalldisplayed := false; if (fSelectedItem = q) or (fThreadPoolSize = 0) or (ObtainImageThreaded(q, displayPriority) = false) then begin if (not ObtainImageNow(q)) and ( ieixRemoveCorrupted in fIOOptionsEx ) then begin // remove corrupted image and re-loop DeleteImageNU(nn); reloop := true; break; end; end; end; // if fSelectedItem <> q then begin xsel := false; if fEnableMultiSelect then begin e := fMultiSelectedImages.IndexOf(pointer(q)); xsel := e > -1; end; end else xsel := true; xsel := xsel and (fVisibleSelection) and (fDisplayMode = mdGrid); if (info.image = nil) and (info.cacheImage = nil) then fAllDisplayed := false; DrawImage( DestBitmap, info, xsel, q ); inc(displayPriority); end else begin if (firstvisible<>-1) and (lastvisible=fIEMBitmap.Count-1) then lastvisible := q-1; end; inc(q); if q = fIEMBitmap.Count then q := 0; end; until not reloop; DrawColumnsHeaderRow( DestBitmap ); // lookahead if (fLookAhead>0) and (fThreadPoolSize>0) then begin if (lastvisible + 1 < fIEMBitmap.Count) then begin nn := fLookAhead; fLookAheadList.Clear; if lastvisible+nn>=fIEMBitmap.Count then nn := fIEMBitmap.Count-1-lastvisible; for q := lastvisible+1 to lastvisible+nn do begin info := fIEMBitmap.GetImageInfo( q ); if (info.image = nil) and (info.cacheImage = nil) then begin fLookAheadList.Add(pointer(q)); ObtainImageThreaded(q, -1); end; end; end; end; // discard invisible images if fMaintainInvisibleImages >- 1 then begin nn := imax(fLookAhead, fMaintainInvisibleImages); for q := 0 to fIEMBitmap.Count-1 do if (q < firstvisible - nn) or (q > lastvisible + nn) then begin info := fIEMBitmap.GetImageInfo( q ); if IsOnDemand(info) and (info.image <> nil) then begin fIEMBitmap.fImageList.Delete(info.image); info.image := nil; end; end; end; // draw done if assigned(fOnDrawProgress) and (ne > 1) then fOnDrawProgress(Self, 100, 0); if fAllDisplayed and not oldalldisplayed and assigned(fOnAllDisplayed) then fOnAllDisplayed(self); end; {!! TImageEnMView.ReloadImage Declaration procedure ReloadImage(idx: Integer); Description Reloads the image at index, idx. Works only images loaded on demand (i.e. where you have set or ). !!} procedure TImageEnMView.ReloadImage(idx: Integer); var info: TIEImageInfo; begin info := fIEMBitmap.GetImageInfo( idx ); if IsOnDemand(info) and (info.image<>nil) then begin fIEMBitmap.fImageList.Delete(info.image); info.image := nil; if info.cacheImage <> nil then begin fcacheList.Delete(info.cacheImage); info.cacheImage := nil; end; end; UpdateEx(false); end; {!! TImageEnMView.DisplayMode Declaration property DisplayMode: ; Description View Method Frame View To display a single frame of a multi-frame image (e.g. TIFF or AVI) set DisplayMode to mdSingle Thumbnail View To display a vertically scrollable thumbnail grid set DisplayMode to mdGrid, and to -1 Single Row Set DisplayMode to mdGrid, and to 0 Single Column Set DisplayMode to mdGrid, and to 1
Note: Animation display modes are also available using Demo Demos\Multi\Multiview\Multiview.dpr !!} procedure TImageEnMView.SetDisplayMode(v: TIEMDisplayMode); begin if fShowThumbnailHint then Hint := ''; if fPlaying then fSaveDM := v else begin fDisplayMode := v; Update; end; end; {!! TImageEnMView.GridWidth Declaration property GridWidth: integer; Description GridWidth is the number of images per row. This property is active only when is mdGrid. Valid GridWidth values are: Value Description -1 Automatically adjust column count to match the component width (standard usage) 0 Only one row >0 GridWidth images per row, e.g. set to 1 for a single vertical column
You can center the thumbnail column(s) using
See Also - !!} procedure TImageEnMView.SetGridWidth(v: integer); begin fGridWidth := v; fCurrentGridWidth := v; Update; end; {!! TImageEnMView.Playing Declaration property Playing: boolean; Description Enable Playing to display each image consecutively for its time. During playback, property is set to mdSingle and the method is called. If is enabled then the animation will replay continuously !!} procedure TImageEnMView.SetPlaying(v: boolean); begin if v = fPlaying then exit; if v then begin fSaveDM := fDisplayMode; fSaveSel := fSelectedItem; Deselect; end; fPlaying := v; PlayFrame; if not fPlaying then begin SetDisplayMode(fSaveDM); SetSelectedItem(fSaveSel); end; end; {!! TImageEnMView.CenterFrame Declaration procedure CenterFrame; Description Scrolls the view (by calling ) to display the current frame at a central position in the view. Note: This method uses to determine the current frame, whereas uses . !!} // show the image indexed by VisibleFrame, put it at the center (when applicable) procedure TImageEnMView.CenterFrame; var info: TIEImageInfo; x, y: integer; begin if fSelectedItem >= 0 then begin info := fIEMBitmap.GetImageInfo( fFrame ); X := info.X - (( ClientWidth - ThumbSizeInfo( itsCell ).X ) div 2 ); Y := info.Y - (( ClientHeight - ThumbSizeInfo( itsCell ).Y ) div 2 ); SetViewXY(X, Y); end; end; procedure TImageEnMView.PlayFrame; var info: TIEImageInfo; rr: TRect; iInterval: Integer; bShowFrame : Boolean; begin if fTimerInProgress then exit; if csDestroying in ComponentState then exit; bShowFrame := True; fTimerInProgress := true; // remove timer if fPlayTimer <> 0 then begin KillTimer(self.handle, 1); fPlayTimer := 0; end; if fPlaying then begin if fDisplayMode <> mdSingle then begin fDisplayMode := mdSingle; Update; end; if fFrame >= fIEMBitmap.Count then fFrame := fIEMBitmap.Count - 1; if fFrame < 0 then exit; info := fIEMBitmap.GetImageInfo( fFrame ); // show current frame if assigned(fOnPlayFrame) then fOnPlayFrame(self, fFrame, bShowFrame); if bShowFrame then begin Paint; rr := rect(0, 0, clientwidth, clientheight); ValidateRect(self.handle, @rr); // cancel invalidate executed by CenterSelected end; // another loop // prepare for next frame if fFrame = fIEMBitmap.Count - 1 then begin fFrame := 0; CallBitmapChangeEvents; if not fPlayLoop then begin fPlaying := false; fTimerInProgress := false; exit; // EXIT! end; end else inc(fFrame); if bShowFrame = False then begin // Skip this frame PostMessage(Self.Handle, WM_TIMER, 0, 0); end else begin // run timer iInterval := round(info.DTime); if (iInterval < 1) and (IEExtractFileExtW(info.Filename) = '.gif') then iInterval := Default_GIF_Animation_Delay_MS else if iInterval < 10 then iInterval := 10; // compatibility with pre-v5.0.7 versions fPlayTimer := SetTimer(self.handle, 1, iInterval, nil); end; end; fTimerInProgress := false; end; procedure TImageEnMView.WMTimer(var Message: TWMTimer); begin PlayFrame; end; // look at fLastImOp function TImageEnMView.GetLastOp(): integer; begin result := fLastImOp; end; // look at fLastImIdx function TImageEnMView.GetLastOpIdx(): integer; begin result := fLastImIdx; end; // look at fLastImP1 function TImageEnMView.GetLastOpP1(): integer; begin result := fLastImP1; end; // look at fLastImGroup function TImageEnMView.GetLastOpGroup(): TIEArrayOfInteger; begin result := fLastImGroup; end; // erase fLastImOp (in old versions this was done by GetLastOp) procedure TImageEnMView.CallBitmapChangeEvents; begin inherited; fLastImOp := IEM_OP_NONE; end; procedure TImageEnMView.SetLastImOp(LastImOp: integer; // last operation of insert(1)/delete(2)/move(3)/swap(4) (0=no op) LastImIdx: integer; // index of processed image by fLastImOp LastImP1: Integer); // param 1 begin fLastImOp := LastImOp ; fLastImIdx := LastImIdx ; fLastImP1 := LastImP1 ; SetLength(fLastImGroup, 0); end; procedure TImageEnMView.SetLastImOp(LastImOp: integer; // last operation of insert(1)/delete(2)/move(3)/swap(4) (0=no op) LastImIdx: integer; // index of processed image by fLastImOp LastImP1: Integer; // param 1 LastImGroup: TIEArrayOfInteger); begin SetLastImOp(LastImOp, LastImIdx, LastImP1); fLastImGroup := LastImGroup; end; {!! TImageEnMView.Clear Declaration procedure Clear; Description Removes all images from the TImageEnMView and releases any associated memory. !!} // recreate temp file (you can change the DefTEMPPATH and call Clear to make changes active) procedure TImageEnMView.Clear; begin Reset( True ); end; // Same as Clear, but doesn't clear the image list procedure TImageEnMView.Reset(bClear: Boolean = False); begin Deselect; ClearThreadsAndRequests; if bClear then begin DeleteAllImages(); GetImageEnMIO.ParamsList.Clear; fIEMBitmap.Clear; end; ClearOnDemandIOList; ClearCache(); FreeAndNil(fCacheList); fCacheList := TIEVirtualImageList.Create('ICACHE', GetImageCacheUseDisk); fIconList.Clear(); Update; end; {!! TImageEnMView.LockPaint Declaration procedure LockPaint; Description Increments the lock paint counter. While is greater than zero all painting is disabled. Use to unlock. Example // Disable painting of component ImageEnMView1.LockPaint; try ... Perform activities, e.g. appending many files finally // Re-enable painting and refresh view ImageEnMView1.UnlockPaint; end; !!} // increases fLockPaint procedure TImageEnMView.LockPaint; begin inc(fLockPaint); end; {!! TImageEnMView.UnlockPaint Declaration function UnlockPaint: integer; Description Decrement the lock paint counter (use after calling ). If the lock count is zero, then is called to refresh the view. Returns the lock count. Example // Disable painting of component ImageEnMView1.LockPaint; try ... Perform activities, e.g. appending many files finally // Re-enable painting and refresh view ImageEnMView1.UnlockPaint; end; !!} // decreases fLockPaint // ret. current value (after the decrement) function TImageEnMView.UnLockPaint: integer; begin if fLockPaint > 0 then dec(fLockPaint); if fLockPaint = 0 then begin if assigned(fAnimation) then fAnimation.ImageCount := ImageCount; UpdateEx(true, fSelectedImageAlwaysVisible); end; result := fLockPaint; end; // Decreases fLockPaint // ret current value (after the decrement) // doesn't call Update if fLockpaint=0 function TImageEnMView.NPUnLockPaint: integer; begin if fLockPaint > 0 then dec(fLockPaint); result := fLockPaint; end; {!! TImageEnMView.LockUpdate Declaration procedure LockUpdate; Description Increments the lock update counter. While is greater than zero all component updating is disabled. Use to unlock. Example // Disable updating of component ImageEnMView1.LockUpdate; try ... Perform activities, e.g. appending many files finally // Re-enable Updating and refresh view ImageEnMView1.UnlockUpdate; end; !!} // increases fLockUpdate procedure TImageEnMView.LockUpdate; begin inc(fLockUpdate); if IEMBitmap_IsTIEDBMultiBitmap and ( fIEMBitmap.fOwner = Self ) then fIEMBitmap.LockUpdate; end; {!! TImageEnMView.UnLockUpdate Declaration function UnlockUpdate: integer; Description Decrement the lock update counter (use after calling ). If the lock count is zero, then is called to refresh the view. Returns the lock count. Example // Disable updating of component ImageEnMView1.LockUpdate; try ... Perform activities, e.g. appending many files finally // Re-enable updating and call update ImageEnMView1.UnlockUpdate; end; !!} // decreases fLockUpdate // ret. current value (after the decrement) function TImageEnMView.UnLockUpdate: integer; begin Result := UnLockUpdateEx; end; function TImageEnMView.UnLockUpdateEx: integer; begin if fLockUpdate > 0 then dec(fLockUpdate); if fLockUpdate = 0 then begin if assigned(fAnimation) then fAnimation.ImageCount := ImageCount; if IEMBitmap_IsTIEDBMultiBitmap and ( fIEMBitmap.fOwner = Self ) then begin fIEMBitmap.UnlockUpdate; if fIEMBitmap.LockUpdateCount <> 0 then UpdateEx(true, fSelectedImageAlwaysVisible); // Because UnlockUpdate will call TImageEnMView.Update anyway end else UpdateEx(true, fSelectedImageAlwaysVisible); end; result := fLockUpdate; end; {!! TImageEnMView.GetImageVisibility Declaration function GetImageVisibility(idx: Integer): Integer; Description Returns 0 if image, idx, is not visible, 1 if it's partially visible, or 2 if it's fully visible (i.e. not scrolled out of view). Note: The result may not be valid if the control is not visible. Call Update() prior to IsVisible if you need to calculate for a non-visible control. See Also - !!} function TImageEnMView.GetImageVisibility(idx: integer): integer; var x1, y1: integer; info: TIEImageInfo; begin result := 0; if (idx >= 0) and (idx < fIEMBitmap.Count) then begin info := fIEMBitmap.GetImageInfo( idx ); x1 := info.X - fViewX; y1 := info.Y - fViewY; result := _RectPRect(0, 0, clientwidth - 1, clientheight - 1, x1, y1, x1 + ThumbSizeInfo( itsCell ).X - 1, y1 + ThumbSizeInfo( itsCell ).Y - 1); end; end; {!! TImageEnMView.UpdateImage Declaration procedure UpdateImage(idx: Integer); Description Redraw the image, idx. Whenever an image (Bitmap) within a TImageEnMView changes, you must update the component with or . Example // Draw a rectangle on the fourth image var bmp: TBitmap; begin bmp := ImageEnMView1.GetBitmap(3); bmp.canvas.rectangle(0, 0, 10, 10); ImageEnMView1.ReleaseBitmap(3); UpdateImage(3); end; !!} procedure TImageEnMView.UpdateImage(idx: integer); begin _UpdateImage(idx, False); end; procedure TImageEnMView._UpdateImage(idx: integer; bInvalidateOnly : Boolean); var rc: TRect; x1, y1: integer; info: TIEImageInfo; begin if (idx >= 0) and (idx < fIEMBitmap.Count) then begin if bInvalidateOnly = False then begin ClearImageCache(idx); UpdateEx(false); end; ValidateRect(self.handle, nil); if assigned(fAnimation) then fAnimation.RestartAnimation(); info := fIEMBitmap.GetImageInfo( idx ); x1 := info.X - fViewX; y1 := info.Y - fViewY; rc := Rect( x1, y1, x1 + ThumbSizeInfo( itsCell ).X, y1 + ThumbSizeInfo( itsCell ).Y ); InvalidateRect(self.handle, @rc, false); end; end; procedure TImageEnMView.CMWantSpecialKey(var Msg: TCMWantSpecialKey); begin inherited; case msg.CharCode of VK_LEFT, VK_RIGHT, VK_UP, VK_DOWN, VK_PRIOR, VK_NEXT, VK_HOME, VK_END: msg.Result := 1; end; end; {!! TImageEnMView.CenterSelected Declaration procedure CenterSelected; Description Scrolls the view (by calling ) to display the currently selected image at a central position in the view. Note: This method uses to determine the selection, whereas uses . Example ImageEnMView1.SelectedImage := 10; ImageEnMView1.CenterSelected; !!} procedure TImageEnMView.CenterSelected; var info: TIEImageInfo; x, y: integer; begin if fSelectedItem >= 0 then begin info := fIEMBitmap.GetImageInfo( fSelectedItem ); X := info.X - (( ClientWidth - ThumbSizeInfo( itsCell ).X ) div 2 ); Y := info.Y - (( ClientHeight - ThumbSizeInfo( itsCell ).Y ) div 2 ); SetViewXY(X, Y); end; end; {!! TImageEnMView.SelectSeek Declaration procedure SelectSeek(pos: ); Description Moves the selection by the method specified by pos. SelectSeek will scroll the view, where necessary, to ensure the newly selected image is visible. Example // This code loads "film.avi" and select the first image ImageEnMView1.MIO.LoadFromFile('film.avi'); ImageEnMView1.SelectSeek(iskFirst); !!} procedure TImageEnMView.SelectSeek(pos: TIESeek); var info: TIEImageInfo; gw, gh: integer; begin if fIEMBitmap.Count = 0 then exit; fHoverCheckLastPos.X := -1; fHoverCheckLastIdx := -1; gw := CalcGridWidth(); gh := (ClientHeight - fVertBorder) div ThumbSizeInfo( itsOuter ).Y; if BiDiModeIsRTL() then case pos of iskLeft : pos := iskRight; iskRight : pos := iskLeft; end; case pos of iskLeft, iskPrior: if fSelectedItem >= 0 then begin SetSelectedItem(fSelectedItem - 1); if (fSelectedItem >= 0) and (GetImageVisibility(fSelectedItem) <> 2) then begin info := fIEMBitmap.GetImageInfo( fSelectedItem ); SetViewXY(info.X - fHorizBorder, info.Y - fVertBorder); end; end; iskRight, iskNext: if fSelectedItem >= -1 then begin SetSelectedItem(fSelectedItem + 1); if (fSelectedItem >= 0) and (GetImageVisibility(fSelectedItem) <> 2) then begin info := fIEMBitmap.GetImageInfo( fSelectedItem ); SetViewXY( info.X - clientwidth + ThumbSizeInfo( itsOuter ).X, info.Y - clientheight + ThumbSizeInfo( itsOuter ).Y ); end; end; iskUp: if fSelectedItem >= 0 then begin if fCurrentGridWidth = 0 then // one row of infinite columns SetSelectedItem(fSelectedItem - 1) else begin // more rows of "gw" columns if fSelectedItem - gw >= 0 then SetSelectedItem(fSelectedItem - gw); end; if (fSelectedItem >= 0) and (GetImageVisibility(fSelectedItem) <> 2) then begin info := fIEMBitmap.GetImageInfo( fSelectedItem ); SetViewY(info.Y - fVertBorder); if GetImageVisibility(fSelectedItem) <> 2 then SetViewX(info.X - fHorizBorder); end; end; iskDown: if fSelectedItem >= -1 then begin if fCurrentGridWidth = 0 then // one row of infinite columns SetSelectedItem(fSelectedItem + 1) else begin // more row of gw columns if fSelectedItem + gw < fIEMBitmap.Count then SetSelectedItem(fSelectedItem + gw); end; if (fSelectedItem >= 0) and (GetImageVisibility(fSelectedItem) <> 2) then begin info := fIEMBitmap.GetImageInfo( fSelectedItem ); SetViewY(info.Y - clientheight + ThumbSizeInfo( itsOuter ).Y); if GetImageVisibility(fSelectedItem) <> 2 then SetViewX( info.X - clientwidth + ThumbSizeInfo( itsOuter ).X ); end; end; iskFirst: begin SetSelectedItem(0); if (fSelectedItem >= 0) and (GetImageVisibility(fSelectedItem) <> 2) then SetViewXY(0, 0); end; iskLast: begin SetSelectedItem(fIEMBitmap.Count - 1); if (fSelectedItem >= 0) and (GetImageVisibility(fSelectedItem) <> 2) then begin info := fIEMBitmap.GetImageInfo( fSelectedItem ); SetViewY(info.Y - clientheight + ThumbSizeInfo( itsOuter ).Y); if GetImageVisibility(fSelectedItem) <> 2 then SetViewX( info.X - clientwidth + ThumbSizeInfo( itsOuter ).X ); end; end; iskPagDown: if fSelectedItem >= -1 then begin SetSelectedItem( imin(fSelectedItem + gw * gh , fIEMBitmap.Count-1) ); if (fSelectedItem >= 0) and (GetImageVisibility(fSelectedItem) <> 2) then begin info := fIEMBitmap.GetImageInfo( fSelectedItem ); SetViewY(info.Y - clientheight + ThumbSizeInfo( itsOuter ).Y); if GetImageVisibility(fSelectedItem) <> 2 then SetViewX( info.X - clientwidth + ThumbSizeInfo( itsOuter ).X ); end; end; iskPagUp: if fSelectedItem >= 0 then begin SetSelectedItem( imax(fSelectedItem - gw * gh , 0) ); if (fSelectedItem >= 0) and (GetImageVisibility(fSelectedItem) <> 2) then begin info := fIEMBitmap.GetImageInfo( fSelectedItem ); SetViewY(info.Y - fVertBorder); if GetImageVisibility(fSelectedItem) <> 2 then SetViewX(info.X - fHorizBorder); end; end; end; end; procedure TImageEnMView.KeyDown(var Key: Word; Shift: TShiftState); var lMultiSelecting: boolean; lSelectInclusive: boolean; begin inherited; fUserAction := true; try if fPlaying then exit; if mkiMoveSelected in fKeyInteract then begin if assigned(fAnimation) then begin // in animation behavior if (Key = VK_LEFT) or (Key = VK_UP) then SelectedImage := SelectedImage - 1 else if (Key = VK_RIGHT) or (Key = VK_DOWN) then SelectedImage := SelectedImage + 1 end else if CheckSelectionChangingAllowed then begin // default behavior lMultiSelecting := fMultiSelecting; lSelectInclusive := fSelectInclusive; if fEnableMultiSelect and ((ssCtrl in Shift) or (ssShift in Shift)) then begin fMultiSelecting := true; fSelectInclusive := true; end; try case Key of VK_LEFT: begin SelectSeek(iskLeft); ViewChange(0); end; VK_RIGHT: begin SelectSeek(iskRight); ViewChange(0); end; VK_UP: begin SelectSeek(iskUp); ViewChange(0); end; VK_DOWN: begin SelectSeek(iskDown); ViewChange(0); end; VK_PRIOR: begin SelectSeek(iskPagUp); ViewChange(0); end; VK_NEXT: begin SelectSeek(iskPagDown); ViewChange(0); end; VK_HOME: begin SelectSeek(iskFirst); ViewChange(0); end; VK_END: begin SelectSeek(iskLast); ViewChange(0); end; else exit; end; finally fMultiSelecting := lMultiSelecting; fSelectInclusive := lSelectInclusive; end; if fEnableMultiSelect and (Shift = []) then fPriorHSIDX := fSelectedItem; UpdateEx(false); end; end; finally fUserAction := false; DoAfterEvent(ieaeKeyDown); end; end; procedure TImageEnMView.KeyUp(var Key: Word; Shift: TShiftState); begin inherited; DoAfterEvent(ieaeKeyUp); end; procedure TImageEnMView.WMKillFocus(var Msg: TWMKillFocus); begin inherited; invalidate; end; procedure TImageEnMView.WMSetFocus(var Msg: TWMSetFocus); begin inherited; invalidate; end; {!! TImageEnMView.MouseInteract Declaration property MouseInteract: ; Description Specifies the effect of mouse actions upon the component. !!} function TImageEnMView.GetMouseInteract: TIEMMouseInteract; begin result := fMouseInteract; end; {!! TImageEnMView.KeyInteract Declaration property KeyInteract: Description Specifies which keyboard activities the component will handle automatically. !!} function TImageEnMView.GetKeyInteract: TIEMKeyInteract; begin result := fKeyInteract; end; {!! TImageEnMView.DrawImageBackground Declaration property DrawImageBackground: boolean; Description If enabled, the background color of the thumbnail will be set to that of the current image. Otherwise it is set to . !!} procedure TImageEnMView.SetDrawImageBackground(v: boolean); begin fDrawImageBackground := v; Update; end; {!! TImageEnMView.ScrollBarsAlwaysVisible Declaration property ScrollBarsAlwaysVisible: Boolean; Description When enabled, the scrollbars specified by will always be displayed even when not required. !!} function TImageEnMView.GetScrollBarsAlwaysVisible: boolean; begin result := fScrollBarsAlwaysVisible; end; procedure TImageEnMView.SetScrollBarsAlwaysVisible(v: boolean); begin fScrollBarsAlwaysVisible := v; Update; end; {!! TImageEnMView.SetImageFromFile Declaration function SetImageFromFile(idx: Integer; const FileName: WideString; SourceImageIndex: Integer = 0; FileFormat: = ioUnknown): Boolean; Description Loads an image from a file and assigns it to the TImageEnMView at index, idx. Use SourceImageIndex to specify the image index if the source file is a multi-frame file (such as a TIFF or AVI). Specify a FileFormat for the file if the extension does not match its type. Example idx := ImageEnMView1.AppendImage; ImageEnMView1.SetImageFromFile(idx, 'D:\myfile.jpg'); See Also - - !!} function TImageEnMView.SetImageFromFile(idx: integer; const FileName: WideString; SourceImageIndex: Integer = 0; FileFormat: TIOFileType = ioUnknown): boolean; var ms: TMemoryStream; FileExt: string; begin if IEGetURLTypeW(FileName) <> ieurlUNKNOWN then begin // LOAD FROM URL ms := TMemoryStream.Create; try Result := IEGetFromURL(FileName, ms, IEGlobalSettings().ProxyAddress, IEGlobalSettings().ProxyUser, IEGlobalSettings().ProxyPassword, nil, nil, @GetImageEnMIO.Aborting, FileExt); if Result then begin ms.Position := 0; Result := SetImageFromStreamOrFile( Idx, ms, '', SourceImageIndex, FileFormat ); end; finally FreeAndNil(ms); end; end else begin // LOAD FROM FILE result := SetImageFromStreamOrFile( idx, nil, FileName, SourceImageIndex, FileFormat ); end; if assigned(fAnimation) then fAnimation.RestartAnimation(); end; {!! TImageEnMView.SetImageFromStream Declaration function SetImageFromStream(idx: Integer; Stream: TStream; SourceImageIndex: Integer = 0; FileFormat: = ioUnknown): Boolean; Description Loads an image from a stream and assigns it to the TImageEnMView at index, idx. Use SourceImageIndex to specify the image index if the source file is a multi-frame file (such as a TIFF or AVI). If FileFormat is ioUnknown the content will be examined to detect the image type. Example idx := ImageEnMView1.AppendImage; ImageEnMView1.SetImageFromStream(idx, stream); See Also - - !!} function TImageEnMView.SetImageFromStream(idx: integer; Stream: TStream; SourceImageIndex: Integer = 0; FileFormat: TIOFileType = ioUnknown): boolean; begin result := SetImageFromStreamOrFile( idx, Stream, '', SourceImageIndex, FileFormat ); if assigned(fAnimation) then fAnimation.RestartAnimation(); end; function TImageEnMView.SetImageFromStreamOrFile(idx: integer; Stream: TStream; const FileName: WideString; SourceImageIndex: Integer; FileFormat: TIOFileType): boolean; var bmp: TIEBitmap; info: TIEImageInfo; ASourceType : TIESourceType; begin if IEMBitmap_IsTIEDBMultiBitmap then begin result := fIEMBitmap.SetImageFromStreamOrFile( idx, Stream, Filename, SourceImageIndex, FileFormat ); exit; end; result := False; if idx >= fIEMBitmap.Count then exit; info := fIEMBitmap.GetImageInfo( idx ); ASourceType := info.SourceType; bmp := TIEBitmap.Create; try fImageEnIO.Background := info.Background; fImageEnIO.AttachedIEBitmap := bmp; fImageEnIO.OnProgress := fOnIOProgress; fImageEnIO.AutoAdjustDPI := MIO.AutoAdjustDPI; fImageEnIO.Params.ImageIndex := SourceImageIndex; _SetLoadParams(Self, fImageEnIO.Params); try if Stream <> nil then fImageEnIO.LoadFromStream(Stream, FileFormat) else if ( fStoreType in [ ietThumb, ietFastThumb ]) and IsMetaFile( Filename ) then fImageEnIO.ImportMetafile( Filename, ThumbSizeInfo( itsImage ).X, -1, true ) else {$IFDEF VIDEO_THUMBNAILS} if ( fStoreType in [ ietThumb, ietFastThumb ]) and UseThumbnailFromExplorer(FileName) then fImageEnIO.LoadThumbnailFromExplorer( FileName, ThumbSizeInfo( itsImage ).X, ThumbSizeInfo( itsImage ).Y ) else {$ENDIF} begin if FileFormat = ioUnknown then FileFormat := FindFileFormat( FileName, ffFallbackToExtension ); fImageEnIO.LoadFromFile(FileName, FileFormat); if ( not fImageEnIO.Aborting ) and ( ImageFileName[ idx ] = '' ) then ImageFileName[ idx ] := FileName; end; except fImageEnIO.Aborting := true; end; if fImageEnIO.Aborting then DoWrongImage(bmp, idx, ASourceType); result := not fImageEnIO.Aborting; // updates params of encapsulated TImageEnMIO object StripOffIOParams(self, fImageEnIO.Params); GetImageEnMIO.Params[idx].Assign(fImageEnIO.Params); // GetImageEnMIO creates TImageEnMIO if it doesn't exist info.Background := fImageEnIO.Background; info.SourceType := ASourceType; SetIEBitmapEx(idx, bmp); ImageOriginalWidth [idx] := fImageEnIO.Params.OriginalWidth; ImageOriginalHeight[idx] := fImageEnIO.Params.OriginalHeight; if fImageEnIO.Params.EXIF_DateTimeOriginal2 > 0 then ImageCreateDate[idx] := fImageEnIO.Params.EXIF_DateTimeOriginal2; if assigned( fOnImageLoaded ) then fOnImageLoaded( self, idx ); finally fImageEnIO.attachediebitmap := nil; FreeAndNil(bmp); end; ClearImageCache(idx); UpdateEx(false); end; {!! TImageEnMView.GetImageToFile Declaration procedure GetImageToFile(idx: Integer; const FileName: WideString); Description Saves the image at index, idx, to file. The file format is determined by the file extension. Parameter Description idx The image index (0=first image) FileName The destination path and file name
Example // Separate the pages of a multipage TIFF ImageEnMView1.MIO.LoadFromFile('multipage.tif'); ImageEnMView1.GetImageToFile(0, 'page1.tif'); ImageEnMView1.GetImageToFile(1, 'page2.tif'); // Save the first image to a JPEG file (at 80% quality) ImageEnMView1.MIO.Params[0].JPEG_Quality := 80; ImageEnMView1.GetImageToFile(0, 'D:\MyImage.jpg'); !!} procedure TImageEnMView.GetImageToFile(idx: Integer; const FileName: WideString); var bmp: TIEBitmap; begin fImageEnIO.Params.Assign( GetImageEnMIO.Params[idx] ); bmp := GetTIEBitmap(idx); try fImageEnIO.AttachedIEBitmap := bmp; fImageEnIO.SaveToFile(FileName); finally fImageEnIO.AttachedIEBitmap := nil; ReleaseBitmap(idx, false); end; end; {!! TImageEnMView.GetImageToStream Declaration procedure GetImageToStream(idx: Integer; Stream: TStream; ImageFormat:
); Description Saves the image at index, idx, to a stream. Parameter Description idx The image index (Where 0 is the first image) Stream The destination stream ImageFormat The output file format (e.g. ioTiff or ioJpeg)
Example // Save the first image to a stream in JPEG format (at 80% quality) ImageEnMView1.MIO.Params[0].JPEG_Quality := 80; ImageEnMView1.GetImageToFile(0, MyStream, ioJPEG); !!} procedure TImageEnMView.GetImageToStream(idx: Integer; Stream: TStream; ImageFormat: TIOFileType); var bmp: TIEBitmap; begin fImageEnIO.Params.Assign( GetImageEnMIO.Params[idx] ); bmp := GetTIEBitmap(idx); try fImageEnIO.AttachedIEBitmap := bmp; fImageEnIO.SaveToStream(Stream, ImageFormat); finally fImageEnIO.AttachedIEBitmap := nil; ReleaseBitmap(idx, false); end; end; {!! TImageEnMView.PrepareSpaceFor Declaration procedure PrepareSpaceFor(Width, Height: Integer; Bitcount: Integer; ImageCount: Integer); Description Allocates enough space within the temporary file for ImageCount> images of size Width * Height * BitCount. Use this method to improve performance only when you plan to add many images of the same size. !!} procedure TImageEnMView.PrepareSpaceFor(Width, Height: integer; Bitcount: integer; ImageCount: integer); begin fIEMBitmap.PrepareSpaceFor(Width, Height, Bitcount, ImageCount); end; {!! TImageEnMView.ImageCacheSize Declaration property ImageCacheSize: Integer; Description Specifies the number of images to be stored in memory, rather than in a memory mapped file. For example, if you know that a TImageEnMView will only contain 20 images then the ImageCacheSize could be set to 20 to disable all memory mapping. Default: 10 See Also -
- - !!} function TImageEnMView.GetImageCacheSize : integer; begin Result := fIEMBitmap.ImageCacheSize; end; procedure TImageEnMView.SetImageCacheSize(v: integer); begin fIEMBitmap.ImageCacheSize := v; end; {!! TImageEnMView.ImageCacheUseDisk Declaration property ImageCacheUseDisk: Boolean; Description When enabled, a disk file is used to cache the images and view. Otherwise only system memory is used. Disabling this option is useful if you have low disk space or don't want ImageEn to write to disk. Warning: Setting this property will also call Default: True See Also - - - !!} function TImageEnMView.GetImageCacheUseDisk : boolean; begin Result := fIEMBitmap.ImageCacheUseDisk; end; procedure TImageEnMView.SetImageCacheUseDisk(v: boolean); begin if fIEMBitmap.ImageCacheUseDisk <> v then begin fIEMBitmap.ImageCacheUseDisk := v; Clear; end; end; {!! TImageEnMView.VisibleFrame Declaration property VisibleFrame: Integer; Description Specifies the visible image when is mdSingle or is True. !!} procedure TImageEnMView.SetVisibleFrame(v: integer); begin if (v = fFrame) or (v < 0) or (v >= fIEMBitmap.Count) then exit; if fTransitionEffect <> iettNone then begin fTransition.Transition := fTransitionEffect; fTransition.Duration := fTransitionDuration; fTransition.SetSizes( ThumbSizeInfo( itsCell ).X, ThumbSizeInfo( itsCell ).Y ); PaintTo(fTransition.SourceShot); fFrame := v; PaintTo(fTransition.TargetShot); fTransition.Run(true); end else begin fFrame := v; UpdateEx(false); end; end; {!! TImageEnMView.TransitionRunning Declaration property TransitionRunning: Boolean; Description Returns true when a transition is running. Example // Design time properties... ImageEnMView1.DisplayMode := mdSingle; ImageEnMView1.TransitionEffect := iettCrossDissolve; ImageEnMView1.TransitionDuration := 1500; // display next frame using cross dissolve ImageEnMView1.VisibleFrame := ImageEnMView1.VisibleFrame + 1; // wait for the transition to end While ImageEnMView1.TransitionRunning do Application.processmessages; ShowMessage('transition done!'); !!} function TImageEnMView.GetTransitionRunning: boolean; begin result := fTransition.Running; end; procedure TImageEnMView.RemoveAlphaChannel(Merge: boolean); begin // nothing end; // return nil function TImageEnMView.GetAlphaChannel: TIEBitmap; begin result := nil; end; function TImageEnMView.GetHasAlphaChannel: boolean; begin result := false; end; {!! TImageEnMView.Style Declaration property Style: ; Description Specifies the thumbnail style. ImageEnMView1.Style := iemsFlat; ImageEnMView1.Style := iemsACD; ImageEnMView1.Style := iemsFlatAndWide; ImageEnMView1.Style := iemsColumns; Notes on iemsColumns A header row is displayed with the iemsColumns style. is used for the font formatting, but this can be overriden in the event. The header row caption is based on the default text, but can be overriden in or . Columns will be shown for text fields which have text specified (e.g. using ) and a valid width. Columns are displayed in the order: , , . Example procedure TForm1.rdbShowThumbsClick(Sender: TObject); begin IEFolderMView.LockUpdate; try IEFolderMView.Style := iemsFlat; IEFolderMView.Zoom := 100; IEFolderMView.TopTextFont.Style := []; IEFolderMView.DefaultTopText := iedtNone; IEFolderMView.DefaultInfoText := iedtNone; IEFolderMView.DefaultBottomText := iedtFileName; IEFolderMView.ThumbnailsBorderWidth := 1; IEFolderMView.VertBorder := 8; IEFolderMView.HorizBorder := 8; finally IEFolderMView.UnlockUpdate; InitializeControls; end; end; procedure TForm1.rdbShowDetailsClick(Sender: TObject); begin IEFolderMView.LockUpdate; try IEFolderMView.Style := iemsFlatAndWide; IEFolderMView.Zoom := 50; IEFolderMView.TopTextFont.Style := [ fsBold ]; IEFolderMView.DefaultTopText := iedtFileName; IEFolderMView.DefaultInfoText := iedtFilePath; IEFolderMView.DefaultBottomText := iedtImageDimAndSize; IEFolderMView.ThumbnailsBorderWidth := 1; IEFolderMView.VertBorder := 8; IEFolderMView.HorizBorder := 8; finally IEFolderMView.UnlockUpdate; InitializeControls; end; end; procedure TForm1.rdbShowColumnsClick(Sender: TObject); begin IEFolderMView.LockUpdate; try IEFolderMView.Style := iemsColumns; IEFolderMView.Zoom := 17; IEFolderMView.TopTextFont.Style := []; IEFolderMView.DefaultTopText := iedtFileName; IEFolderMView.DefaultInfoText := iedtImageDimAndSize; IEFolderMView.DefaultBottomText := iedtFileCreateDate; IEFolderMView.ThumbnailsBorderWidth := 0; IEFolderMView.VertBorder := 0; IEFolderMView.HorizBorder := 0; finally IEFolderMView.UnlockUpdate; InitializeControls; end; end; Demo Demos\Multi\MViewStyles\MViewStyles.dpr See Also - - - !!} procedure TImageEnMView.SetStyle(value: TIEMStyle); begin if fStyle <> value then begin fStyle := value; ClearCache; Update; end; end; {!! TImageEnMView.SetStyleEx Declaration procedure SetStyleEx(aStyle: ; TopText : ; InfoText : ; BottomText : ; iThumbZoom: Double = 0; bAdjustSpacing: Boolean = True; bAdjustStyle: Boolean = True; bAdjustFont: Boolean = True); Description Provides a shortcut method to set the style of the control to several predefined styles: ImageEnMView1.SetStyleEx( iemsFlat, iedtNone, iedtNone, iedtFileName ); ImageEnMView1.SetStyleEx( iemsFlatAndWide, iedtFileName, iedtFilePath, iedtImageDimAndSize ); ImageEnMView1.SetStyleEx( iemsColumns, iedtFileName, iedtImageDimAndSize, iedtFileCreateDate ); ImageEnMView1.GridWidth := 1; ImageEnMView1.SetStyleEx( iemsFlatAndWide, iedtNone, iedtNone, iedtFileName, -24 ); Parameter Description aStyle Sets to one of iemsFlat, iemsFlatAndWide or iemsColumns TopText Sets InfoText Sets BottomText Sets iThumbZoom Sets . If a negative value is specified then will be set to give a thumbnail of that height in pixels (i.e. -22 would set the thumbnail height to 22 pixels). If 0 is specified, then actual zoom will depend on the specified aStyle bAdjustSpacing Sets the following properties with values best for the specified aStyle (and considering ): - - - - - - - bAdjustStyle Sets the to 0 if aStyle is iemsColumns bAdjustFont Sets the to [fsBold] if aStyle is iemsFlatAndWide
Note: If you have already set text for your images then you won't see the default text values you've specified above Example // An application with menu items to change the view style procedure TForm1.FormCreate(Sender: TObject); begin IEFolderMView.SetModernStyling( True ); end; // Show Large Thumbs procedure TForm1.rdbShowLargeThumbsClick(Sender: TObject); begin ImageEnMView1.GridWidth := -1; ImageEnMView1.ThumbnailOptionsEx := ImageEnMView1.ThumbnailOptionsEx - [ ietxOnlyShowIcons ]; ImageEnMView1.SetStyleEx( iemsFlat, iedtNone, iedtNone, iedtFileName, 200 ); end; // Show Thumbs procedure TForm1.rdbShowThumbsClick(Sender: TObject); begin ImageEnMView1.GridWidth := -1; ImageEnMView1.ThumbnailOptionsEx := ImageEnMView1.ThumbnailOptionsEx - [ ietxOnlyShowIcons ]; ImageEnMView1.SetStyleEx( iemsFlat, iedtNone, iedtNone, iedtFileName ); end; // Show Small Thumbs with Detail procedure TForm1.rdbShowDetailsClick(Sender: TObject); begin ImageEnMView1.GridWidth := -1; ImageEnMView1.ThumbnailOptionsEx := ImageEnMView1.ThumbnailOptionsEx - [ ietxOnlyShowIcons ]; ImageEnMView1.SetStyleEx( iemsFlatAndWide, iedtFileName, iedtFilePath, iedtImageDimAndSize ); end; // Show File List procedure TForm1.rdbShowDetailsClick(Sender: TObject); begin ImageEnMView1.GridWidth := 1; ImageEnMView1.ThumbnailOptionsEx := ImageEnMView1.ThumbnailOptionsEx + [ ietxOnlyShowIcons ]; ImageEnMView1.SetStyleEx( iemsFlatAndWide, iedtNone, iedtNone, iedtFileName, -24 ); end; // Show Text Columns procedure TForm1.rdbShowColumnsClick(Sender: TObject); begin ImageEnMView1.GridWidth := -1; ImageEnMView1.ThumbnailOptionsEx := ImageEnMView1.ThumbnailOptionsEx + [ ietxOnlyShowIcons ]; ImageEnMView1.SetStyleEx( iemsColumns, iedtFileName, iedtImageDimAndSize, iedtFileCreateDate ); end; Demo Demos\Multi\MViewStyles\MViewStyles.dpr See Also - - - !!} const Gap_For_Details_Style = 4; Gap_For_Thumbs_Style = 6; Gap_For_Columns_Style = 2; Gap_When_Soft_Shadow = 0; Default_Text_Margin = 4; Columns_Text_Margin = 6; Default_Cell_Spacing = 8; Columns_Cell_Spacing = 0; procedure TImageEnMView.SetStyleEx(aStyle: TIEMStyle; TopText : TIEImageEnMViewDefaultText; InfoText : TIEImageEnMViewDefaultText; BottomText : TIEImageEnMViewDefaultText; iThumbZoom: Double = 0; bAdjustSpacing: Boolean = True; bAdjustStyle: Boolean = True; bAdjustFont: Boolean = True); var iGap: Integer; bFileListView: Boolean; begin LockUpdate; try Style := aStyle; if iThumbZoom = 0 then case aStyle of iemsFlatAndWide : iThumbZoom := 50; iemsColumns : iThumbZoom := -24; else iThumbZoom := 100; end; if iThumbZoom < 0 then Zoom := abs( iThumbZoom ) / ThumbHeight * 100 else Zoom := iThumbZoom; bFileListView := ( aStyle = iemsFlatAndWide ) and ( ThumbSizeInfo( itsCell ).Y < 30 ) and // Less than 30 pixels high ( TopText = iedtNone ) and ( InfoText = iedtNone ) and ( BottomText <> iedtNone ); if bAdjustFont then begin if ( aStyle = iemsFlatAndWide ) and ( InfoText <> iedtNone ) and ( BottomText <> iedtNone ) then TopTextFont.Style := TopTextFont.Style + [fsBold] else TopTextFont.Style := TopTextFont.Style - [fsBold]; end; if bAdjustStyle then begin if ( aStyle = iemsColumns ) or bFileListView then ThumbnailsBorderWidth := 0 else if ThumbnailsBorderWidth = 0 then ThumbnailsBorderWidth := 1; end; if bAdjustSpacing then begin if ( aStyle = iemsColumns ) or bFileListView then iGap := Gap_For_Columns_Style else if SoftShadow.Enabled then iGap := Gap_When_Soft_Shadow else if aStyle = iemsFlatAndWide then iGap := Gap_For_Details_Style else iGap := Gap_For_Thumbs_Style; UpperGap := iGap; BottomGap := iGap; SideGap := iGap; if ( aStyle = iemsColumns ) or bFileListView then begin VertBorder := Columns_Cell_Spacing; HorizBorder := Columns_Cell_Spacing; if TextMargin < Columns_Text_Margin then TextMargin := Columns_Text_Margin; end else begin if VertBorder = Columns_Cell_Spacing then VertBorder := Default_Cell_Spacing; if HorizBorder = Columns_Cell_Spacing then HorizBorder := Default_Cell_Spacing; if TextMargin > Default_Text_Margin then TextMargin := Default_Text_Margin; end; TextBlockWidth := -1; end; DefaultTopText := TopText; DefaultInfoText := InfoText; DefaultBottomText := BottomText; finally UnlockUpdate; end; end; const Column_View = 0; File_List = 1; Detail_View = 2; Thumb_View = 3; // or > 4+ for zoom levels > 100% // Return the current layout in use function TImageEnMView.GetStyleInt() : Integer; begin case fStyle of iemsColumns : Result := Column_View; iemsFlatAndWide : if GridWidth = 1 then Result := File_List else Result := Detail_View; else { iemsFlat, iemsACD } Result := Thumb_View + imax( 0, Trunc(( Zoom - 100 ) / 50 )); end; end; // Cycles through 4 built-in layouts + extra zoom levels procedure TImageEnMView.SetStyleInt(v : Integer); var iZoom: Integer; begin if ( v < 0 ) or ( v > 11 { 500% zoom } ) then exit; LockUpdate; case v of Column_View: begin GridWidth := -1; SetStyleEx( iemsColumns, iedtFilename, iedtFileCreateDateTime, iedtImageDimAndSize ); ThumbnailOptionsEx := ThumbnailOptionsEx + [ ietxOnlyShowIcons ]; end; File_List: begin GridWidth := 1; SetStyleEx( iemsFlatAndWide, iedtNone, iedtNone, iedtFilename, -24 ); ThumbnailOptionsEx := ThumbnailOptionsEx + [ ietxOnlyShowIcons ]; end; Detail_View: begin GridWidth := -1; SetStyleEx( iemsFlatAndWide, iedtFilename, iedtFileCreateDateTime, iedtImageDimAndSize ); ThumbnailOptionsEx := ThumbnailOptionsEx - [ ietxOnlyShowIcons ]; end; else { Thumb_View } begin // v=3, zoom = 100%. v=4, zoom = 150%. v=5, zoom = 200%. etc. iZoom := 100 + (v - Thumb_View) * 50; GridWidth := -1; SetStyleEx( iemsFlat, iedtNone, iedtNone, iedtFilename, iZoom ); ThumbnailOptionsEx := ThumbnailOptionsEx - [ ietxOnlyShowIcons ]; end; end; UnlockUpdate; end; {!! TImageEnMView.SetModernStyling Declaration procedure SetModernStyling(bAutoGridWidth : Boolean = False; iThumbWidth : Integer = 0; iThumbHeight : Integer = 0; bSoftShadow: Boolean = True); Description Call SetModernStyling in FormCreate to update the control with the settings which closely match the current Windows styling. if bAutoGridWidth is enabled then is set to -1. You can also optionally specify default values for and and add a . The current implementation of SetModernStyling makes the following changes: := iemsFlat; := clWindow; := clWindow; := $00FCEADA; := $00CEA27D; := 1; := 4; := 8; := 8; := 0; (or 4 if bSoftShadow = False) := 0; (or 4 if bSoftShadow = False) := 0; (or 4 if bSoftShadow = False) := bsClear; := rfFastLinear; := 1; SoftShadow.Radius := 2; SoftShadow.OffsetX := 2; SoftShadow.OffsetY := 2; SoftShadow.Intensity := 70; SoftShadow.Enabled := bSoftShadow; Example procedure TForm1.FormCreate(Sender: TObject); begin ImageEnMView1.SetModernStyling( True ); end; See Also - - - !!} procedure TImageEnMView.SetModernStyling(bAutoGridWidth : Boolean = False; iThumbWidth : Integer = 0; iThumbHeight : Integer = 0; bSoftShadow: Boolean = True); var iGap: Integer; begin LockUpdate; try fModernStyling := True; fStyle := iemsFlat; SoftShadow.Radius := 2; SoftShadow.OffsetX := 2; SoftShadow.OffsetY := 2; SoftShadow.Intensity := 70; SoftShadow.Enabled := bSoftShadow; fBackground := clWindow; fThumbnailsBackground := clWindow; fThumbnailsBackgroundSelected := clExplorer_Selection_Background_Color; fThumbnailsSelectedBorderColor := clExplorer_Selection_Border_Color; fSelectionBorderWidth := 1; fSelectionBorderWidthNoFocus := -1; fTextMargin := Default_Text_Margin; fHorizBorder := Default_Cell_Spacing; fVertBorder := Default_Cell_Spacing; ParentCtl3D := False; Ctl3D := False; if bSoftShadow then iGap := Gap_When_Soft_Shadow else iGap := Gap_For_Thumbs_Style; fUpperGap := iGap; fBottomGap := iGap; fSideGap := iGap; fThumbnailsBorderWidth := 1; fThumbnailsBorderColor := clBtnFace; fTextBackgroundStyle := bsClear; fThumbnailsInternalBorder := False; if fThumbnailDisplayFilter = rfNone then fThumbnailDisplayFilter := rfFastLinear; if iThumbWidth > 0 then begin ThumbWidth := iThumbWidth; ClearCache; end; if iThumbHeight > 0 then begin ThumbHeight := iThumbHeight; ClearCache; end; if bAutoGridWidth then begin fGridWidth := -1; fCurrentGridWidth := -1; end; finally UnlockUpdate; end; end; {!! TImageEnMView.EnableMultiSelect Declaration property EnableMultiSelect: Boolean; Description Specify whether the user is able to select multiple images. Default: false (i.e. multi-selection is disabled) Example // select images 0 and 1 (assumes you have set at design time ImageEnMView1.EnableMultiSelect := True) ImageEnMView1.Deselect; ImageEnMView1.MultiSelecting := True; ImageEnMView1.SelectedImage := 0; ImageEnMView1.SelectedImage := 1; ImageEnMView1.MultiSelecting := False; See Also - - !!} procedure TImageEnMView.SetEnableMultiSelect(Value: boolean); begin if fEnableMultiSelect <> Value then begin fEnableMultiSelect := Value; Update; end; end; {!! TImageEnMView.ThumbnailsBorderWidth Declaration property ThumbnailsBorderWidth: Integer; Description Specifies the width (in pixels) of the thumbnail border. Default: 0 This value should be less than and . Specify the color of the border using . Example // Draw a thin green border around all thumbnails ImageEnMView1.ThumbnailsBorderWidth := 1; ImageEnMView1.ThumbnailsBorderColor := clGreen; See Also - - - !!} procedure TImageEnMView.SetThumbnailsBorderWidth(Value: integer); begin if fThumbnailsBorderWidth <> Value then begin fThumbnailsBorderWidth := Value; Update; end; end; {!! TImageEnMView.ThumbnailsBorderColor Declaration property ThumbnailsBorderColor: TColor; Description Specifies the color of the thumbnail border. Note: This value may be overridden if is enabled. Example // draw a thin green border to all thumbnails ImageEnMView1.ThumbnailsBorderWidth := 1; ImageEnMView1.ThumbnailsBorderColor := clGreen; See Also - - !!} procedure TImageEnMView.SetThumbnailsBorderColor(Value: TColor); begin if fThumbnailsBorderColor <> Value then begin fThumbnailsBorderColor := Value; Update; end; end; {!! TImageEnMView.ThumbnailsBorderCurved Declaration property ThumbnailsBorderCurved: Boolean; Description Specifies the width (in pixels) of the thumbnail border. Default: True Example // Draw rectangular borders for thumbnails ImageEnMView1.ThumbnailsBorderCurved := False; See Also - - - !!} procedure TImageEnMView.SetThumbnailsBorderCurved(Value: Boolean); begin if fThumbnailsBorderCurved <> Value then begin fThumbnailsBorderCurved := Value; Update; end; end; {!! TImageEnMView.ThumbnailsInternalBorder Declaration property ThumbnailsInternalBorder: boolean; Description If enabled, a border is drawn around the thumbnail interior. Specify the color using . !!} procedure TImageEnMView.SetThumbnailsInternalBorder(Value: boolean); begin if fThumbnailsInternalBorder <> Value then begin fThumbnailsInternalBorder := Value; Update; end; end; {!! TImageEnMView.ThumbnailsInternalBorderColor Declaration property ThumbnailsInternalBorderColor: TColor; Description Specifies the border color when is True. !!} procedure TImageEnMView.SetThumbnailsInternalBorderColor(Value: TColor); begin if fThumbnailsInternalBorderColor <> Value then begin fThumbnailsInternalBorderColor := Value; Update; end; end; {!! TImageEnMView.TextColumnWidths Declaration property TextColumnWidths[Col : ] : Integer; Description Specifies the width of each column when is set to iemsColumns. With the iemsColumns display style, data is shown in four columns: - Thumbnail - - - The width of the thumbnail is set by whereas the width of each column can be specified by TextColumnWidths. If a column width is set to -1, then it will be automatically calculated. TextColumnWidths set to zero will be hidden (also if the text is set to iedtNone). Notes: - Column widths will automatically be adjusted if they are too wide to fit in the available area - Users can also manually resize column widths by clicking the header area with the mouse Examples // Display to the full width of the control with each column width auto-calculated ImageEnMView1.LockUpdate; ImageEnMView1.Style := iemsColumns; ImageEnMView1.TextBlockWidth := -1; ImageEnMView1.TextColumnWidths[ iemtpTop ] := -1; ImageEnMView1.TextColumnWidths[ iemtpBottom ] := -1; ImageEnMView1.TextColumnWidths[ iemtpInfo ] := -1; ImageEnMView1.UnlockUpdate; // Display to the full width of the control with the first column 100 pixels wide, the center column hidden, and the last column width auto-calculated ImageEnMView1.LockUpdate; ImageEnMView1.Style := iemsColumns; ImageEnMView1.TextBlockWidth := -1; ImageEnMView1.TextColumnWidths[ iemtpTop ] := 100; ImageEnMView1.TextColumnWidths[ iemtpBottom ] := -1; ImageEnMView1.TextColumnWidths[ iemtpInfo ] := 0; ImageEnMView1.UnlockUpdate; // Display to a total width of 300 with each column width auto-calculated ImageEnMView1.LockUpdate; ImageEnMView1.Style := iemsColumns; ImageEnMView1.TextBlockWidth := 300; ImageEnMView1.TextColumnWidths[ iemtpTop ] := -1; ImageEnMView1.TextColumnWidths[ iemtpBottom ] := -1; ImageEnMView1.TextColumnWidths[ iemtpInfo ] := -1; ImageEnMView1.UnlockUpdate; // Display to a total width of 300 with the first column 200 wide, and the remaining ones auto-calculated ImageEnMView1.LockUpdate; ImageEnMView1.Style := iemsColumns; ImageEnMView1.TextBlockWidth := 300; ImageEnMView1.TextColumnWidths[ iemtpTop ] := 200; ImageEnMView1.TextColumnWidths[ iemtpBottom ] := -1; ImageEnMView1.TextColumnWidths[ iemtpInfo ] := -1; ImageEnMView1.UnlockUpdate; // Display to a total width of 300 by setting specific widths for each column ImageEnMView1.LockUpdate; ImageEnMView1.Style := iemsColumns; ImageEnMView1.TextBlockWidth := -1; ImageEnMView1.TextColumnWidths[ iemtpTop ] := 200; ImageEnMView1.TextColumnWidths[ iemtpBottom ] := 50; ImageEnMView1.TextColumnWidths[ iemtpInfo ] := 50; ImageEnMView1.UnlockUpdate; Demo \Demos\Multi\MViewStyles\MViewStyles.dpr See Also - - !!} function TImageEnMView.GetTextColumnWidths(Col: TIEMTextPos): integer; begin Result := fTextColumnWidths[ Col ]; end; procedure TImageEnMView.SetTextColumnWidths(Col: TIEMTextPos; value: integer); begin if fTextColumnWidths[ Col ] <> value then begin fTextColumnWidths[ Col ] := value; Update; end; end; function TImageEnMView.CurrentTextColumnWidths(Col: TIEMTextPos): integer; var iMaxWidth, iAvailWidth: Integer; itt: TIEMTextPos; ColText : TIEImageEnMViewDefaultText; CurrColWidths : array[ iemtpTop .. iemtpInfo ] of Integer; iUnknownCount: Integer; iTotalWidth: Integer; begin Result := 0; iAvailWidth := ClientWidth - trunc(fThumbWidth * fZoom / 100.0) - 2 * fHorizBorder; iMaxWidth := fTextBlockWidth; if ( iMaxWidth <= 0 ) or ( iMaxWidth > iAvailWidth ) then iMaxWidth := iAvailWidth; if iMaxWidth < 1 then exit; // Get all widths iUnknownCount := 0; iTotalWidth := 0; for itt := iemtpTop to iemtpInfo do begin case itt of iemtpTop : ColText := DefaultTopText; iemtpBottom : ColText := DefaultBottomText; else { iemtpInfo } ColText := DefaultInfoText; end; if ColText = iedtNone then CurrColWidths[ itt ] := 0 else CurrColWidths[ itt ] := fTextColumnWidths[ itt ]; if CurrColWidths[ itt ] = -1 then inc( iUnknownCount ) else inc( iTotalWidth, CurrColWidths[ itt ] ); end; // Are we wider than available space? Proportionally reduce all cells if iTotalWidth > iMaxWidth then begin for itt := iemtpTop to iemtpInfo do if CurrColWidths[ itt ] > 0 then CurrColWidths[ itt ] := Trunc( CurrColWidths[ itt ] * iMaxWidth / iTotalWidth ); iTotalWidth := iMaxWidth; end; Result := CurrColWidths[ Col ]; if Result = -1 then Result := ( iMaxWidth - iTotalWidth ) div iUnknownCount; end; {!! TImageEnMView.MultiSelectedImages Declaration property MultiSelectedImages[index: Integer]: Integer; Description Returns the index of all selected images, where MultiSelectedImages[0] returns the index of the first selected image, MultiSelectedImages[1] returns the second, etc. Notes: - Use to know how many images are selected - The index returned by MultiSelectedImages is not in any particular order unless is called - This property is valid even if multiple selection is not enabled (i.e. returning ). Example 1 // replaces all selected images with 'new.jpg' for i := 0 to ImageEnMView1.MultiSelectedImagesCount - 1 do begin iSelIndex := ImageEnMView1.MultiSelectedImages[ i ]; ImageEnMView1.SetImageFromFile(iSelIndex , 'new.jpg'); end; Example 2 // Get filenames of all selected files // Sort them by image index ImageEnMView1.MultiSelectSortList; lbxFilenames.clear; for i := 0 to ImageEnMView1.MultiSelectedImagesCount - 1 do begin iSelIndex := ImageEnMView1.MultiSelectedImages[ i ]; lbxFilenames.Items.Add(ImageEnMView1.ImageFileName[iSelIndex]); end; See Also - - - !!} function TImageEnMView.GetMultiSelectedImages(index: integer): integer; begin result := -1; if EnableMultiSelect and (index >= 0) and (index < fMultiSelectedImages.Count) then result := integer(fMultiSelectedImages[index]) else if (EnableMultiSelect = False) and (index = 0) and (fSelectedItem > -1) then Result := fSelectedItem; end; {!! TImageEnMView.MultiSelectedImagesCount Declaration property MultiSelectedImagesCount: Integer; Description MultiSelectedImagesCount returns the number of selected images. Selected indexes are returned by . Note: This property is valid even if multiple selection is not enabled (i.e. returning either 0 or 1). Example // replaces all selected images with 'new.jpg' for i := 0 to ImageEnMView1.MultiSelectedImagesCount - 1 do begin iSelIndex := ImageEnMView1.MultiSelectedImages[ i ]; ImageEnMView1.SetImageFromFile(iSelIndex , 'new.jpg'); end; See Also - - - !!} function TImageEnMView.GetMultiSelectedImagesCount: integer; begin Result := 0; if EnableMultiSelect then result := fMultiSelectedImages.Count else if fSelectedItem > -1 then Result := 1; end; {!! TImageEnMView.MultiSelectedImagesList Declaration property MultiSelectedImagesList: ; Description Returns an array of integers representing the indexes of all selected images. Changing the content of this list doesn't change the actual selected images. Notes: - The index returned by MultiSelectedImagesList is not in any particular order unless is called - This property is valid even if multiple selection is not enabled (i.e. returning ). !!} // returns a readonly list of selected images function TImageEnMView.GetMultiSelectedImagesList(): TIEArrayOfInteger; var i: integer; begin SetLength(result, MultiSelectedImagesCount); for i := 0 to length(result) - 1 do result[i] := MultiSelectedImages[i]; end; {!! TImageEnMView.Wallpaper Declaration property Wallpaper: TPicture; Description Sets a background image that appears behind the thumbnails. Use to specify how the wallpaper is painted. Demo Demos\Multi\Thumbnails2\Thumbnails2.dpr Example // Tile a bitmap over the background ImageEnMView1.WallpaperStyle := iewoTile ImageEnMView1.Wallpaper.LoadFromFile('D:\MyWallpaper.bmp'); !!} procedure TImageEnMView.SetWallpaper(Value: TPicture); begin fWallpaper.Assign(Value); Update; end; {!! TImageEnMView.WallpaperStyle Declaration property WallpaperStyle: ; Description Determines how the wallpaper (specified by ) is painted. Example // Tile a bitmap over the background ImageEnMView1.WallpaperStyle := iewoTile ImageEnMView1.Wallpaper.LoadFromFile('D:\MyWallpaper.bmp'); !!} procedure TImageEnMView.SetWallpaperStyle(Value: TIEWallpaperStyle); begin if Value <> fWallpaperStyle then begin fWallpaperStyle := Value; Update; end; end; {!! TImageEnMView.SelectAll Declaration procedure SelectAll; Description Selects all images (if is true). !!} procedure TImageEnMView.SelectAll; var q: integer; lMultiSelecting: boolean; begin if fEnableMultiSelect then begin DeselectNU; lMultiSelecting := fMultiSelecting; fMultiSelecting := true; for q := 0 to fIEMBitmap.Count - 2 do fMultiSelectedImages.Add(pointer(q)); SetSelectedItemNU(fIEMBitmap.Count - 1); // last item also is current selected item (own Bitmap object) fMultiSelecting := lMultiSelecting; UpdateEx(false); end; end; function TImageEnMView.GetEnableResamplingOnMinor : boolean; begin Result := ietxStretchSmallImages in fThumbnailOptionsEx; end; {$ifdef IEIncludeDeprecatedInV5} // Deprecated in 6.0.0 (2015-03-06) procedure TImageEnMView.SetEnableResamplingOnMinor(Value: boolean); begin if value then fThumbnailOptionsEx := fThumbnailOptionsEx + [ ietxStretchSmallImages ] else fThumbnailOptionsEx := fThumbnailOptionsEx - [ ietxStretchSmallImages ]; Update; end; {$endif} {!! TImageEnMView.IconSize Declaration property IconSize : ; Description For non-image types a system icon is displayed. The default setting is _icoHDStretch which means that a high quality icon is stretched to the display size. On Windows XP and older versions, it automatically downgrades to ieicDoubleSize. See Also - !!} procedure TImageEnMView.SetIconSize(Value: TIEImageEnMViewIconSize); begin if fIconSize <> Value then begin fIconSize := Value; ClearCache; Update; end; end; function TImageEnMView.GetImageEnMIO: TImageEnMIO; begin if not assigned(fImageEnMIO) then begin fImageEnMIO := TImageEnMIO.Create(self); fImageEnMIO.AttachedMView := self; fImageEnMIO.OnProgress := fOnProgress; fImageEnMIO.OnFinishWork := fOnFinishWork; fImageEnMIO.OnAcquireBitmap := fOnAcquireBitmap; end; result := fImageEnMIO; end; function TImageEnMView.GetImageEnProc: TImageEnProc; begin if fSelectedItem = -1 then SelectedImage := 0; if not assigned(fImageEnProc) then begin fImageEnProc := TImageEnProc.Create(self); fImageEnProc.AttachedImageEn := self; fImageEnProc.OnProgress := fOnProgress; fImageEnProc.OnFinishWork := fOnFinishWork; fImageEnProc.fOnUndoRedoEvent := ProcessUndoRedo; end; fImageEnProc.fMViewIndex := fSelectedItem; result := fImageEnProc; if not assigned(fSelectedBitmap) then fImageEnProc.AttachedImageEn := self; // refresh bitmap if fSelectedBitmap=nil end; function TImageEnMView.CheckSelectionChangingAllowed : Boolean; begin Result := True; if (fDestroying = False) and assigned(fOnSelectionChanging) then fOnSelectionChanging(self, Result); end; procedure TImageEnMView.ProcessUndoRedo(Sender : TObject; bIsUndo : Boolean; Source : TIEUndoSource; UndoObj : TObject; iIndex : Integer; var bHandled : Boolean); var bmp: TIEBitmap; begin if (Source <> ieuImage) or (iIndex < 0) then exit; bHandled := True; if iIndex = fSelectedItem then IEBitmap.assign(TIEBitmap(UndoObj)) else begin bmp := GetTIEBitmap(iIndex); bmp.assign(TIEBitmap(UndoObj)); ReleaseBitmap(iIndex); end; Update; end; {!! TImageEnMView.OnAcquireBitmap Declaration property OnAcquireBitmap: ; Description Occurs whenever a new bitmap is acquired during a multi-page Twain acquisition. Parameter Description Sender Will be either a TImageEnIO or TImageEnMIO control ABitmap A object that contains the acquired image DpiX, DpiY Tne DPI of the acquired image Handled Setting Handled to True causes ImageEn to ignore this image (i.e. the current image won't be inserted into the control, if attached). Handled has no effect when acquiring via a TImageEnView/TImageEnIO
Note: Handled defaults to False. Example procedure TForm1.ImageEnMView1AcquireBitmap(Sender: TObject; ABitmap: TIEBitmap; DpiX, DpiY: Integer; var Handled: boolean); begin // Skip retrieval of images that are less than 500x500 pixels If ( ABitmap.Width < 500 ) or ( ABitmap.Height < 500 ) then Handled := True; end; !!} function TImageEnMView.GetOnAcquireBitmap: TIEAcquireBitmapEvent; begin result := fOnAcquireBitmap; end; procedure TImageEnMView.SetOnAcquireBitmap(v: TIEAcquireBitmapEvent); begin fOnAcquireBitmap := v; if assigned(fImageEnIO) then fImageEnIO.OnAcquireBitmap := v; end; {!! TImageEnMView.OnFinishWork Declaration property OnFinishWork: TNotifyEvent; Description Occurs whenever an image processing or input/output task terminates. It is always called after so can be used to reset your progress bar. !!} function TImageEnMView.GetOnFinishWork: TNotifyEvent; begin result := fOnFinishWork; end; procedure TImageEnMView.SetOnFinishWork(v: TNotifyEvent); begin fOnFinishWork := v; if assigned(fImageEnMIO) then fImageEnMIO.OnFinishWork := v; if assigned(fImageEnProc) then fImageEnProc.OnFinishWork := v; end; procedure TImageEnMView.SetOnProgress(v: TIEProgressEvent); begin fOnProgress := v; if assigned(fImageEnMIO) then fImageEnMIO.OnProgress := v; if assigned(fImageEnProc) then fImageEnProc.OnProgress := v; end; {!! TImageEnMView.OnProgress Declaration property OnProgress: ; Description Occurs during image processing or input/output operations. It is useful to display progress to the user of the current task. You can use to reset the progress when the task has completed. !!} function TImageEnMView.GetOnProgress: TIEProgressEvent; begin result := fOnProgress; end; {!! TImageEnMView.MaximumViewX Declaration property MaximumViewX: Integer; Description Returns the maximum value that you can specify for (naturally "MinimumViewX" is zero). See also: . !!} function TImageEnMView.GetMaximumViewX: integer; begin result := imax(fVWidth - ClientWidth, 0); end; {!! TImageEnMView.MaximumViewY Declaration property MaximumViewY: Integer; Description Returns the maximum value that you can specify for (naturally "MinimumViewY" is zero). See also: . !!} function TImageEnMView.GetMaximumViewY: integer; begin result := imax(fVHeight - ClientHeight, 0); end; {!! TImageEnMView.DefaultTopText Declaration property DefaultTopText: ; Description The text that will display above the thumbnail for images that do not have a value specified for . Default: iedtNone You can also set: and Example // Display the filename and details for each image ImageEnMView1.DefaultImageTopText := iedtFilename; ImageEnMView1.DefaultImageInfoText := iedtImageDimensions; ImageEnMView1.DefaultImageBottomText := iedtFileEditDateAndSize; See Also - - !!} procedure TImageEnMView.SetDefaultTopText(Value : TIEImageEnMViewDefaultText); begin if fDefaultTopText <> Value then begin fDefaultTopText := Value; UpdateTopTextHeight( fDefaultTopText <> iedtNone ); Update; end; end; procedure TImageEnMView.UpdateTopTextHeight(bHasText: Boolean); begin fTopTextHeight := 0; if bHasText = False then exit; if not HandleAllocated then begin fTopTextHeight := CALCULATE_NOW; end else begin Canvas.Font.Assign( fTopTextFont ); fTopTextHeight := IETextHeightW( Canvas, 'Xy' ) + 2 + fTextMargin; end; end; procedure TImageEnMView.TopTextFontChange(Sender: TObject); begin UpdateTopTextHeight(( fDefaultTopText <> iedtNone ) or (fTopTextHeight > 0 )); end; {!! TImageEnMView.DefaultInfoText Declaration property DefaultInfoText: ; Description The text that will display directly below the thumbnail (above ) for images that do not have a value specified for . Default: iedtNone You can also set: and Example // Display the filename and details for each image ImageEnMView1.DefaultImageTopText := iedtFilename; ImageEnMView1.DefaultImageInfoText := iedtImageDimensions; ImageEnMView1.DefaultImageBottomText := iedtFileEditDateAndSize; See Also - - !!} procedure TImageEnMView.SetDefaultInfoText(Value : TIEImageEnMViewDefaultText); begin if fDefaultInfoText <> Value then begin fDefaultInfoText := Value; UpdateInfoTextHeight( fDefaultInfoText <> iedtNone ); Update; end; end; procedure TImageEnMView.UpdateInfoTextHeight(bHasText: Boolean); begin fInfoTextHeight := 0; if bHasText = False then exit; if not HandleAllocated then begin fInfoTextHeight := CALCULATE_NOW; end else begin Canvas.Font.Assign( fInfoTextFont ); fInfoTextHeight := IETextHeightW( Canvas, 'Xy' ); end; end; procedure TImageEnMView.InfoTextFontChange(Sender: TObject); begin UpdateInfoTextHeight(( fDefaultInfoText <> iedtNone ) or (fInfoTextHeight > 0 )); end; {!! TImageEnMView.DefaultBottomText Declaration property DefaultBottomText: ; Description The text that will display below the thumbnail (below ) for images that do not have a value specified for . TImageEnMView Default: iedtNone TImageEnFolderMView Default: iedtFilename You can also set: and Example // Display the filename and details for each image ImageEnMView1.DefaultImageTopText := iedtFilename; ImageEnMView1.DefaultImageInfoText := iedtImageDimensions; ImageEnMView1.DefaultImageBottomText := iedtFileEditDateAndSize; // Replace existing bottom text and display the file date and size for I := 0 to ImageEnMView1.ImageCount - 1 do ImageEnMView1.ImageBottomText[ i ] := '' ; ImageEnMView1.DefaultImageBottomText := iedtFileEditDateAndSize; See Also - - !!} procedure TImageEnMView.SetDefaultBottomText(Value : TIEImageEnMViewDefaultText); begin if fDefaultBottomText <> Value then begin fDefaultBottomText := Value; UpdateBottomTextHeight( fDefaultBottomText <> iedtNone ); Update; end; end; procedure TImageEnMView.UpdateBottomTextHeight(bHasText: Boolean); begin fBottomTextHeight := 0; if bHasText = False then exit; if not HandleAllocated then begin fBottomTextHeight := CALCULATE_NOW; end else begin Canvas.Font.Assign( fBottomTextFont ); fBottomTextHeight := IETextHeightW( Canvas, 'Xy' ) + 2 + fTextMargin; if fStyle = iemsACD then Inc( fBottomTextHeight, 2 ); end; end; procedure TImageEnMView.BottomTextFontChange(Sender: TObject); begin UpdateBottomTextHeight(( fDefaultBottomText <> iedtNone ) or ( fBottomTextHeight > 0 )); end; {!! TImageEnMView.ClearImageCache Declaration procedure ClearImageCache(idx: Integer); Description Clears the cache for image, idx. Image caching allows you to speed up the thumbnail painting by saving the view of each image to an internal cache. You should call this method only if you have refreshing problems. See Also - - - !!} procedure TImageEnMView.ClearImageCache(idx: integer); var info: TIEImageInfo; begin info := fIEMBitmap.GetImageInfo( idx ); if ( info <> nil ) and ( info.cacheImage <> nil ) then begin fcacheList.Delete(info.cacheImage); info.cacheImage := nil; end; end; procedure TImageEnMView.ClearCache; var i: integer; begin for i := 0 to fIEMBitmap.Count - 1 do ClearImageCache(i); fIconList.Clear(); end; {!! TImageEnMView.EnableImageCaching Declaration property EnableImageCaching: Boolean; Description Speeds up thumbnail painting by saving the view of each image to an internal cache. This is enabled by default. Set to false to disable image caching. See Also - - - !!} procedure TImageEnMView.SetEnableImageCaching(v: boolean); begin fEnableImageCaching := v; if not fEnableImageCaching then begin if fStoreType = ietFastThumb then fStoreType := ietThumb; ClearCache; update; end; end; {!! TImageEnMView.IsSelected Declaration function IsSelected(idx: Integer): Boolean; Description IsSelected returns true if the image, idx, is currently selected. Example // replaces all selected images with 'new.jpg' for idx := 0 to ImageEnMView1.ImageCount - 1 do if ImageEnMView1.IsSelected(idx) then ImageEnMView1.SetImageFromFile(idx, 'new.jpg'); end; See Also - !!} function TImageEnMView.IsSelected(idx: integer): boolean; begin result := (fSelectedItem = idx) or (fMultiSelectedImages.IndexOf(pointer(idx)) > -1); end; {!! TImageEnMView.MultiSelectSortList Declaration procedure MultiSelectSortList; Description Sorts the selected items list () by image index. Example // Get filenames of all selected files in the order they are displayed ImageEnMView1.MultiSelectSortList; lbxFilenames.clear; for i := 0 to ImageEnMView1.MultiSelectedImagesCount - 1 do begin iSelIndex := ImageEnMView1.MultiSelectedImages[ i ]; lbxFilenames.Items.Add(ImageFileName[iSelIndex]); end; !!} procedure TImageEnMView.MultiSelectSortList; begin fMultiSelectedImages.Sort(@ComparePointers); end; {!! TImageEnMView.EnableAlphaChannel Declaration property EnableAlphaChannel: Boolean; Description Set EnableAlphaChannel to True to enable the alpha channel of thumbnails (e.g. for the display of soft shadows). !!} procedure TImageEnMView.SetEnableAlphaChannel(v: boolean); begin fEnableAlphaChannel := v; Update; end; {!! TImageEnMView.BackgroundStyle Declaration property BackgroundStyle: ; Description Specifies the style of the background (the component region behind the thumbnails). Example // Small chessboard background ImageEnMView1.BackgroundStyle := iebsChessboard; ImageEnMView1.SetChessboardStyle(5, bsSolid); // Solid white background ImageEnMView1.BackgroundStyle := iebsSolid; ImageEnMView1.Background := clWhite; // Navy -> Black gradient background ImageEnMView1.BackgroundStyle := iebsGradient; ImageEnMView1.Background := clNavy; ImageEnMView1.GradientEndColor := clBlack; !!} procedure TImageEnMView.SetBackgroundStyle(v: TIEBackgroundStyle); begin fBackgroundStyle := v; Update; end; {!! TImageEnMView.ThumbnailsBackgroundStyle Declaration property ThumbnailsBackgroundStyle: Description Specifies the style of the thumbnail background (the region of the thumbnail that does not contain the image). Note: Only applicable when is true and the image has an alpha channel to make it transparent. !!} procedure TImageEnMView.SetThumbnailsBackgroundStyle(v: TIEBackgroundStyle); begin fThumbnailsBackgroundStyle := v; Update; end; {!! TImageEnMView.SetChessboardStyle Declaration procedure SetChessboardStyle(Size: Integer; BrushStyle: TBrushStyle = bsSolid; Color1: TColor = clNone; Color2: TColor = clNone); Description Sets the size and brush of the chessboard background (when is iebsChessboard). Parameter Description Size Specifies the box size (default 16) BrushStyle Specifies the brush style of the boxes (default bsSolid) Color1 Color 1 of chessboard. Specifying this as something other than clNone will set Color2 Color 2 of chessboard. If specified as clNone, then color 2 will be a reverse of Color 1
Example // Set small chessboard background of Yellow and Blue ImageEnMView1.SetChessboardStyle( 5, bsSolid, clBlue, clYellow ); ImageEnMView1.BackgroundStyle := iebsChessboard; !!} procedure TImageEnMView.SetChessboardStyle(Size: Integer; BrushStyle: TBrushStyle = bsSolid; Color1: TColor = clNone_; Color2: TColor = clNone_); begin fChessboardSize := Size; fChessboardBrushStyle := BrushStyle; fChessboardColor2Customized := Color2 <> clNone_; if Color1 <> clNone_ then Background := Color1; if Color2 <> clNone_ then GradientEndColor := Color2; end; {!! TImageEnMView.GradientEndColor Declaration property GradientEndColor: TColor Description Specifies the ending color of the gradient when is iebsGradient. specifies the starting color. Note: This value may be overridden if is enabled. Default: clBtnShadow Example // Set Navy -> Black gradient background ImageEnMView1.BackgroundStyle := iebsGradient; ImageEnMView1.Background := clNavy; ImageEnMView1.GradientEndColor := clBlack; !!} procedure TImageEnMView.SetGradientEndColor(Value: TColor); begin fGradientEndColor := Value; Update; end; {!! TImageEnMView.FillThumbnail Declaration property FillThumbnail: Boolean; Description When enabled, the thumbnail background is filled with the background color. Generally an unselected image is filled with , and selected one filled with . Default: True See also: !!} procedure TImageEnMView.SetFillThumbnail(Value: boolean); begin fFillThumbnail := Value; Update; end; {!! TImageEnMView.AnnotationsVisible Declaration property AnnotationsVisible: Boolean; Description When enabled, Wang annotations and ImageEn annotations of the image are shown on the thumbnail. Default: False Notes: - This property has no effect if is ietThumb. It is only supported by ietNormal and ietFastThumb. - This will slow performance so is only recommended for annotation-specific applications. Example // Test application with a TImageEnMView that loads and saves a multiple page TIFF file, and TImageEnVect that allows annotation editing // Show annotations of selected frame procedure TForm1.ImageEnMView1ImageSelect(Sender: TObject; idx: Integer); begin // Clear TImageEnVect ImageEnVect1.RemoveAllObjects; ImageEnVect1.Clear; // Get selected image ImageEnMView1.CopyToIEBitmap( idx, ImageEnVect1.IEBitmap ); // Get ImageEn annotations if ImageEnMView1.MIO.Params[ idx ].ImageEnAnnot.IsEmpty = False then ImageEnMView1.MIO.Params[ idx ].ImageEnAnnot.CopyToTImageEnVect( ImageEnVect1 ); // Refresh the TImageEnVect ImageEnVect1.Update; end; // Save the annotations procedure TForm1.btnSaveAnnotClick(Sender: TObject); begin if ImageEnMView1.SelectedImage > -1 then begin ImageEnMView1.MIO.Params[ ImageEnMView1.SelectedImage ].ImageEnAnnot.CopyFromTImageEnVect( ImageEnVect1 ); ImageEnMView1.UpdateImage( ImageEnMView1.SelectedImage ); end; end; !!} procedure TImageEnMView.SetAnnotationsVisible(Value: boolean); begin if fAnnotationsVisible <> Value then begin fAnnotationsVisible := Value; Update; end; end; {!! TImageEnMView.ShowText Declaration property ShowText: Boolean; Description If enabled, the , and are displayed. Default: True !!} procedure TImageEnMView.SetShowText(Value: boolean); begin fShowText := Value; Update; end; {!! TImageEnMView.ThumbnailClipping Declaration property ThumbnailClipping: Integer; Description Automatically clips the sides of the thumbnail when displaying it so that it more closely matches the size of the grid cell, for example, if you have a tall/portrait image the top and bottom would not be shown so that the thumbnail is as wide as the display area. ThumbnailClipping is a percentage so the valid range is 0 to 100. Possible values Value Description 0 The entire image will be displayed as a thumbnail pointer. 1 - 99 The percentage of permissible clipping. E.g. 10 would mean that up 10% of the image can be clipped. 100 The maximum clipping will be performed so that the thumbnail has no border space (and all thumbnails will be displayed at an identical size)
!!} procedure TImageEnMView.SetThumbnailClipping(Value: Integer); begin if fThumbnailClipping <> Value then begin fThumbnailClipping := Value; ClearCache; Update; end; end; {!! TImageEnMView.FillFromDirectory Declaration procedure FillFromDirectory(const Directory: WideString; Limit : integer = -1; AllowUnknownFormats : boolean = false; const ExcludeExtensions : WideString = ''; DetectFileFormat : boolean = false; const FilterMask : WideString = ''; IncludeVideoFiles : Boolean = False; LoadOnDemand : boolean = true; DefaultTopText :
= iedtNone; DefaultInfoText : = iedtNone; DefaultBottomText : = iedtFilename; bShowHiddenFiles : Boolean = False; bShowFolders : Boolean = False); Description Fills the ImageEnMView with files from the specified Directory. For each file will be set with the full path and with the filename. You can cancel the insertion of files by setting MIO.Aborting := True; Parameter Description Directory The folder to search for files Limit The maximum number of images to load. Use -1 to retrieve all files AllowUnknownFormats If false (default) only known and supported file formats are loaded. Otherwise all files are loaded ExcludeExtensions A comma separated list of file extensions to skip (e.g. 'lyr,all,iev') DetectFileFormat If true then the image type is detected by reading the header (which can be slow). Otherwise ImageEn only checks the file extension FilterMask Limits the fill to file extensions found in a comma separated list (e.g. 'jpg,jpeg,jpe'). Specify an empty string to return all supported extensions bIncludeVideoFiles If AllowUnknownFormats is false then video files are excluded by default. Set to true to include supported video file types such as AVI and MPEG. Thumbnails for video files will be retrieved from Windows Explorer if the format is specified in LoadOnDemand If True (Default), images are only loaded as they are displayed (i.e. not until they are scrolled into view). Set to false to load all images immediately DefaultTopText Specify the text that is applied to DefaultInfoText Specify the text that is applied to DefaultBottomText Specify the text that is applied to (defaults to the filename) bShowHiddenFiles Enable to include hidden and system files (default is false) bShowFolders Enable to include folders (default is false)
Notes: - Does NOT clear existing content. Use first to replace existing content - More functionality for the display of thumbnails of file folders is available with . Demo Demos\Multi\Thumbnails\Thumbnails.dpr Example ImageEnMView1.Clear; ImageEnMView1.StoreType := ietFastThumb; ImageEnMView1.FillFromDirectory('C:\images'); !!} procedure TImageEnMView.FillFromDirectory(const Directory: WideString; Limit : integer = -1; AllowUnknownFormats : boolean = false; const ExcludeExtensions : WideString = ''; DetectFileFormat : boolean = false; const FilterMask : WideString = ''; IncludeVideoFiles : Boolean = False; LoadOnDemand : boolean = true; DefaultTopText : TIEImageEnMViewDefaultText = iedtNone; DefaultInfoText : TIEImageEnMViewDefaultText = iedtNone; DefaultBottomText : TIEImageEnMViewDefaultText = iedtFilename; bShowHiddenFiles : Boolean = False; bShowFolders : Boolean = False); var l, idx: Integer; fpath, fname: WideString; iAdded: Integer; sep: WideString; excList: TStringList; mskList: TStringList; dir: TIEDirContent; ext: WideString; lAnimation: TIEAnimation; bInclude: Boolean; bAllowAddition: Boolean; iTotal: Integer; iRead: Integer; begin lAnimation := Animation; fAnimation := nil; LockPaint(); dir := nil; excList := TStringList.Create; mskList := TStringList.Create; MIO.Aborting := False; try excList.CommaText := LowerCase( ExcludeExtensions ); mskList.CommaText := LowerCase( FilterMask ); l := length( Directory ); if ( l = 0 ) or ( Directory[ l ] = '\' ) then sep := '' else sep := '\'; // NEED FILE COUNT FOR PROGRESS??? (Only useful when not loading on demand) iTotal := 0; if ( LoadOnDemand = False ) and assigned( fOnProgress ) then begin dir := TIEDirContent.Create( Directory + sep + '*.*' ); while dir.GetItem( fname, True, bShowFolders, bShowHiddenFiles ) do begin Inc( iTotal ); if (Limit > -1) and ( iTotal = Limit ) then break; end; dir.Free; end; iAdded := 0; iRead := 0; dir := TIEDirContent.Create( Directory + sep + '*.*' ); while dir.GetItem( fname, True, bShowFolders, bShowHiddenFiles ) do begin if ( LoadOnDemand = False ) and assigned( fOnProgress ) then fOnProgress( Self, MulDiv( iRead, 100, iTotal )); Inc( iRead ); fpath := Directory + sep + fname; ext := IEExtractFileExtW( fname, false ); if dir.IsFolder then bInclude := True else bInclude := ( AllowUnknownFormats or ( DetectFileFormat and ( FindFileFormat( fpath, ffContentOnly ) <> ioUnknown )) or IsKnownFormat( fpath, IncludeVideoFiles )) and ( excList.IndexOf( ext ) = -1) and (( mskList.Count = 0 ) or ( mskList.IndexOf( ext ) > -1 )); if bInclude then begin if ( Limit > -1 ) and ( iAdded = Limit ) then break else if MIO.Aborting then break; bAllowAddition := True; if assigned( fOnImageAdd ) then fOnImageAdd( self, fIEMBitmap.Count, fpath, dir.IsFolder, dir.IsHiddenFile, dir.FileSizeBytes, dir.CreateDate, dir.EditDate, bAllowAddition ); if bAllowAddition then begin idx := AppendImage( fpath, LoadOnDemand, DefaultTopText, DefaultInfoText, DefaultBottomText, False ); ImageFileSize[idx] := dir.FileSizeBytes; ImageCreateDate[idx] := dir.CreateDate; ImageEditDate[idx] := dir.EditDate; If dir.IsFolder then fIEMBitmap.GetImageInfo( idx ).SourceType := iestFolderIcon; inc(iAdded); end; end; end; {$ifdef IEIncludeDeprecatedInV5} // Legacy support: select last added item SetSelectedItemNU( fIEMBitmap.Count - 1 ); {$endif} finally dir.Free; mskList.Free; excList.Free; fAnimation := lAnimation; UnLockPaint(); Update; end; fCurrentOrderBy := iesbFilename; fCurrentAscending := True; if ( LoadOnDemand = False ) and assigned( fOnFinishWork ) then fOnFinishWork( Self ); end; {!! TImageEnMView.EnsureImageLoaded Declaration procedure TImageEnMView.EnsureImageLoaded(idx: integer); Description If the content of the TImageEnMView is being loaded on demand (e.g. because you are using ) then the image properties such as and , and I/O parameters will not be valid until the image has loaded. Calling EnsureImageLoaded will force an image to be loaded so you can access its properties. Naturally calling EnsureImageLoaded too often (e.g. for all images) would defeat the purpose of loading on demand and affect performance. Example // Get the dimensions of the selected image if ImageEnMView1.SelectedImage >= 0 then begin ImageEnMView1.EnsureImageLoaded( ImageEnMView1.SelectedImage ); StatusBar.Text [ 0 ] := ImageEnMView1.ImageWidth[ ImageEnMView1.SelectedImage ] + ' x ' + ImageEnMView1.ImageHeight[ ImageEnMView1.SelectedImage ]; end; // Read the Photoshop description of the selected image if ImageEnMView1.SelectedImage >= 0 then begin ImageEnMView1.EnsureImageLoaded( ImageEnMView1.SelectedImage ); StatusBar.Text [ 1 ] := ImageEnMView1.MIO.Params[ ImageEnMView1.SelectedImage ].ReadIPTCField(PhotoShop_IPTC_Records, IPTC_PS_Caption); end; !!} procedure TImageEnMView.EnsureImageLoaded(idx: integer); begin fThreadCS.Enter(); try if fIEMBitmap.GetImageInfo( idx ).image = nil then ObtainImageNow(idx); finally fThreadCS.Leave(); end; end; {!! TImageEnMView.MoveImage Declaration procedure MoveImage(idx: Integer; destination: Integer); Description Moves an image from the index position idx to the destination position. If the destination index is greater than or equal to the image count, the image is moved to the position after the last image. Notes: - If you have images of the order ABCD, then calling MoveImage(0, 2) would change it to BCAD - Cannot be used if a is attached to the control Example // Exchange first and second images ImageEnMView1.MoveImage(0, 1); // Move first image to the end of the grid ImageEnMView1.MoveImage(0, ImageEnMView1.ImageCount); !!} // move image idx to destination index procedure TImageEnMView.MoveImage(idx: integer; destination: integer); var psel: integer; mm: TList; i, p: Integer; begin if IEMBitmap_IsTIEDBMultiBitmap then raise EIEException.create('Not available when attached to TIEDBMultiBitmap'); if (idx >= 0) and (idx < fIEMBitmap.Count) and (destination >= 0) and (destination <> idx) then begin SetPlaying(false); psel := fSelectedItem; mm := TList.Create; try for i := 0 to fMultiSelectedImages.Count-1 do begin p := integer( fMultiSelectedImages[i] ); if p = idx then p := destination else begin if p > idx then dec(p); if p >= destination then inc(p); end; mm.Add( pointer(p) ); end; TIEMultiBitmap( fIEMBitmap ).MoveImage( idx, destination ); CallBitmapChangeEvents; if (mm.Count > 0) and ((idx = psel) or (fMultiSelectedImages.Count > 0)) then begin fSelectedItem := integer(mm[0]); fIEMBitmap.SetActiveImage( fSelectedItem ); for i := 0 to fMultiSelectedImages.Count-1 do fMultiSelectedImages[i] := mm[i]; end else begin DeselectNU; SetSelectedItemNU(psel); end; UpdateEx(false); finally mm.free; end; end; end; {!! TImageEnMView.MoveSelectedImagesTo Declaration procedure MoveSelectedImagesTo(beforeImage: Integer; bUseDisplayOrder: Boolean = true); Description Moves all selected images to the postion prior to beforeImage. To move images after last image set beforeImage to . if bUseDisplayOrder is true, then will be called so that multiple selected files will be inserted in their new position in the order they are displayed. When false, they are inserted in the order that they were selected. Example // Move all selected images to the start of the grid ImageEnMView1.MoveSelectedImagesTo(0); // Move all selected images to the end of the grid ImageEnMView1.MoveSelectedImagesTo(ImageEnMView1.ImageCount); !!} // beforeImage can be 0 up to imagecount procedure TImageEnMView.MoveSelectedImagesTo(beforeImage: Integer; bUseDisplayOrder: Boolean = true); var mm: array of TIEImageInfo; i: Integer; sn: Boolean; ImGroup: TIEArrayOfInteger; begin if (beforeImage < 0) or (beforeImage > fIEMBitmap.Count) then exit; SetPlaying(false); if bUseDisplayOrder then MultiSelectSortList; sn := (fSelectedItem > -1) and (fMultiSelectedImages.Count = 0); if sn then fMultiSelectedImages.Add(pointer(fSelectedItem)); SetLength( ImGroup, fMultiSelectedImages.Count ); for i := 0 to fMultiSelectedImages.Count - 1 do ImGroup[i] := MultiSelectedImages[i]; SetLastImOp( IEM_OP_MOVEGROUP, fSelectedItem, beforeImage, ImGroup); SetLength(mm, fIEMBitmap.Count); for i := 0 to fIEMBitmap.Count - 1 do mm[i] := fIEMBitmap.fImageInfo[ i ]; for i := 0 to fMultiSelectedImages.Count - 1 do begin fIEMBitmap.fImageInfo[ fIEMBitmap.fImageInfo.IndexOf( mm[MultiSelectedImages[i]] ) ] := nil; // mark as to remove fIEMBitmap.fImageInfo.Insert( beforeImage, mm[MultiSelectedImages[i]] ); inc(beforeImage); end; for i := fIEMBitmap.Count - 1 downto 0 do if fIEMBitmap.fImageInfo[ i ] = nil then fIEMBitmap.fImageInfo.Delete( i ); for i := 0 to fMultiSelectedImages.Count - 1 do fMultiSelectedImages[i] := pointer(fIEMBitmap.fImageInfo.IndexOf( mm[MultiSelectedImages[i]] )); CallBitmapChangeEvents; fSelectedItem := MultiSelectedImages[0]; fIEMBitmap.SetActiveImage( fSelectedItem ); if sn then fMultiSelectedImages.Clear; UpdateEx(false); end; // no image must be selected // doesn't restore selected image // doesn't update procedure TImageEnMView.SwapImages(idx1, idx2: Integer); begin if IEMBitmap_IsTIEDBMultiBitmap then raise EIEException.create('Not available when attached to TIEDBMultiBitmap'); TIEMultiBitmap( fIEMBitmap ).SwapImages( idx1, idx2 ); CallBitmapChangeEvents; end; function TImageEnMView.SortCompareFunction(index1, index2: Integer): Integer; begin if assigned(fCurrentCompare) then result := fCurrentCompare(index1, index2) else result := fCurrentCompareEx(index1, index2) end; {!! TImageEnMView.Sort Declaration procedure Sort(Compare: ); procedure Sort(Compare: ); procedure Sort(OrderBy: ; Ascending: boolean = true; CaseSensitive: boolean = true); Description Sorts all images in the TImageEnMView by property (filename, dimensions, etc) or using a custom comparison function. Example 1 // sort by filename ImageEnMView1.Sort( iesbFilename ); Example 2 // sort by filename even if files come from different folders ImageEnMView1.Sort( iesbFilenameWithoutPath ); Example 3 // custom sort function (by DPI) function XCompareDPI(i1, i2: Integer): Integer; var s1, s2: Integer; begin s1 := Form1.ImageEnMView1.Params[i1].DPI; s2 := Form1.ImageEnMView1.Params[i2].DPI; if s1 < s2 then result := -1 else if s1 > s2 then result := 1 else result := 0; end; // Sort By DPI procedure TForm1.Button1Click(Sender: TObject); begin ImageEnMView1.Sort( XCompareDPI ); end; !!} procedure TImageEnMView.Sort(Compare: TIEImageEnMViewSortCompare); begin Sort2(Compare, nil); fCurrentOrderBy := iesbCustom; fCurrentAscending := True; end; procedure TImageEnMView.Sort(Compare: TIEImageEnMViewSortCompareEx); begin Sort2(nil, Compare); fCurrentOrderBy := iesbCustom; fCurrentAscending := True; end; function TImageEnMView.SortCompareBy(index1, index2: Integer): Integer; function _DoCompareStr(const S1, S2: string): Integer; begin if fCurrentCaseSensitive then Result := CompareStr(s1, s2) else Result := CompareText(s1, s2) end; function _GetText(const ws : WideString; idx : Integer; DefaultText : TIEImageEnMViewDefaultText):string; begin Result := ReplaceIEMConst( ws, idx ); if Result = '' then Result := ReplaceIEMConst( DefaultText, idx ); end; var s1, s2 : integer; u1, u2 : Int64; d1, d2 : TDateTime; bIndex1IsFolder, bIndex2IsFolder : Boolean; begin bIndex1IsFolder := fIEMBitmap.GetImageInfo( index1 ).SourceType = iestFolderIcon; bIndex2IsFolder := fIEMBitmap.GetImageInfo( index2 ).SourceType = iestFolderIcon; // Folders always appear before files if bIndex1IsFolder <> bIndex2IsFolder then begin if bIndex1IsFolder then Result := -1 else Result := 1; end else // Both files are folders, sort by name, if the sort type is not supported if bIndex1IsFolder and (fCurrentOrderBy in [iesbFilename, iesbImageSize, iesbFilenameWithoutPath, iesbFileExtension, iesbFileSize, iesbFileType]) then begin if SameText( ImageFileName[index1], IEF_Drives_Folder ) then Result := -1 else if SameText( ImageFileName[index2], IEF_Drives_Folder ) then Result := 1 else result := _DoCompareStr(ImageFileName[index1], ImageFileName[index2]); end else begin // Normal sorting case fCurrentOrderBy of iesbFilename: result := _DoCompareStr(ImageFileName[index1], ImageFileName[index2]); iesbTopText: result := _DoCompareStr( _GetText( ImageTopText[index1], index1, fDefaultTopText ), _GetText( ImageTopText[index2], index2, fDefaultTopText )); iesbBottomText: result := _DoCompareStr( _GetText( ImageBottomText[index1], index1, fDefaultBottomText ), _GetText(ImageBottomText[index2], index2, fDefaultBottomText )); iesbInfoText: result := _DoCompareStr( _GetText( ImageInfoText[index1], index1, fDefaultInfoText ), _GetText( ImageInfoText[index2], index2, fDefaultInfoText )); iesbImageSize: begin s1 := ImageOriginalWidth[index1] * ImageOriginalHeight[index1]; s2 := ImageOriginalWidth[index2] * ImageOriginalHeight[index2]; if s1 < s2 then result := -1 else if s1 > s2 then result := 1 else result := 0; end; iesbFilenameWithoutPath: result := _DoCompareStr(ExtractFilename(ImageFileName[index1]), ExtractFilename(ImageFileName[index2])); iesbFileExtension: result := CompareText(ExtractFileExt(ImageFileName[index1]), ExtractFileExt(ImageFileName[index2])); iesbFileSize : begin u1 := ImageFileSize[index1]; u2 := ImageFileSize[index2]; if u1 < u2 then result := -1 else if u1 > u2 then result := 1 else result := 0; end; iesbCreateDate : begin d1 := ImageCreateDate[index1]; d2 := ImageCreateDate[index2]; if d1 < d2 then result := -1 else if d1 > d2 then result := 1 else result := 0; end; iesbEditDate : begin d1 := ImageEditDate[index1]; d2 := ImageEditDate[index2]; if d1 < d2 then result := -1 else if d1 > d2 then result := 1 else result := 0; end; iesbFileType : result := CompareText(fFileTypeList[fIEMBitmap.GetImageInfo( index1 ).FileTypeIndex], fFileTypeList[fIEMBitmap.GetImageInfo( index2 ).FileTypeIndex]); else result := 0; // impossible end; // if files are identical then sort by name if (Result = 0) and (fCurrentOrderBy in [iesbImageSize, iesbFileExtension, iesbFileSize, iesbCreateDate, iesbEditDate, iesbFileType]) then Result := _DoCompareStr(ImageFileName[index1], ImageFileName[index2]); end; if not fCurrentAscending then result := -result; end; procedure TImageEnMView.Sort(OrderBy: TIEImageEnMViewSortBy; Ascending: boolean = true; CaseSensitive: boolean = true); var I: Integer; sFileType: string; begin if OrderBy = iesbFileType then begin fFileTypeList := TStringList.create; for I := 0 to ImageCount - 1 do begin sFileType := GetImageFileType(I); fFileTypeList.Add(sFileType); fIEMBitmap.GetImageInfo( I ).FileTypeIndex := fFileTypeList.Count - 1; end; end; fCurrentOrderBy := OrderBy; fCurrentAscending := Ascending; fCurrentCaseSensitive := CaseSensitive; if (OrderBy <> iesbNone) and (OrderBy <> iesbCustom) then Sort2(nil, SortCompareBy); if OrderBy = iesbFileType then FreeAndNil(fFileTypeList); end; procedure TImageEnMView.Sort2(Compare: TIEImageEnMViewSortCompare; CompareEx: TIEImageEnMViewSortCompareEx); var psel: integer; begin if fIEMBitmap.Count > 0 then begin SetPlaying(false); psel := fSelectedItem; DeselectNU; fCurrentCompare := Compare; fCurrentCompareEx := CompareEx; try fThreadCS.Enter(); IEQuickSort(fIEMBitmap.Count, SortCompareFunction, SwapImages); finally fThreadCS.Leave(); end; SetSelectedItemNU(psel); UpdateEx(false); end; end; procedure TImageEnMView.DoImageSelect(idx: integer); begin if assigned(fOnImageSelect) and fUserAction then fOnImageSelect(self, idx); end; procedure TImageEnMView.DoImageDeselect(idx: integer); begin if not fDestroying and assigned(fOnImageDeselect) and fUserAction then fOnImageDeselect(self, idx); end; {$ifdef IEINCLUDEFLATSB} {!! TImageEnMView.FlatScrollBars Declaration property FlatScrollBars: Boolean; Description Specifies whether the component's scrollbars are flat. !!} procedure TImageEnMView.SetFlatScrollBars(Value: Boolean); begin if Value<>fFlatScrollBars then begin fFlatScrollBars := Value; if fFlatScrollBars then begin // Why calls to IESetScrollRange? Please ask Microsoft's programmers! IESetScrollRange(Handle, SB_HORZ, 0, 65535, false, false); IESetScrollRange(Handle, SB_VERT, 0, 65535, false, false); InitializeFlatSB(Handle); IEShowScrollBar(handle, SB_HORZ, false, true); IEShowScrollBar(handle, SB_VERT, false, true); end else UninitializeFlatSB(Handle); end; end; {$endif} {!! TImageEnMView.SetPresetThumbnailFrame Declaration procedure SetPresetThumbnailFrame(PresetIndex: Integer; UnselectedColor: TColor; SelectedColor: TColor); Description Applies a background style to the thumbnails from an internal set Value Description PresetIndex The style to use (-1: No custom style, 0: Photo, 1: Film, 2: Album, 3: Picture Frame) UnselectedColor Color modification when frame is unselected SelectedColor Color modification when frame is selected
Examples ImageEnMView1.SetPresetThumbnailFrame(0, clWhite, clGreen); ImageEnMView1.SetPresetThumbnailFrame(2, clWhite, clGreen); // Clear custom thumbs ImageEnMView1.SetPresetThumbnailFrame(-1, clWhite, clWhite); See demo Multi\Thumbnails2 !!} procedure TImageEnMView.SetPresetThumbnailFrame(PresetIndex: Integer; UnselectedColor: TColor; SelectedColor: TColor); var io: TImageEnIO; proc: TImageEnProc; rgb: TRGB; begin if assigned(fThumbnailFrame) then FreeAndNil(fThumbnailFrame); if assigned(fThumbnailFrameSelected) then FreeAndNil(fThumbnailFrameSelected); if (PresetIndex >= 0) and (PresetIndex < iegPresetImages.Count) then begin EnableAlphaChannel := true; FillThumbnail := false; SelectionWidth := 0; ShowText := false; Style := iemsFlat; DrawImageBackground := false; fThumbnailFrame := TIEBitmap.Create; fThumbnailFrameSelected := TIEBitmap.Create; io := TImageEnIO.CreateFromBitmap(fThumbnailFrame); try with TIEPresetImage(iegPresetImages[PresetIndex]) do begin io.LoadFromBuffer( Data, Size, FileFormat ); fThumbnailFrameRect := ThumbRect; end; finally FreeAndNil(io); end; fThumbnailFrameSelected.Assign( fThumbnailFrame ); proc := TImageEnProc.CreateFromBitmap(fThumbnailFrameSelected); // set selected color rgb := TColor2TRGB(SelectedColor); proc.IntensityRGBall(rgb.r-255, rgb.g-255, rgb.b-255); // set unselected color proc.AttachedIEBitmap := fThumbnailFrame; rgb := TColor2TRGB(UnselectedColor); proc.IntensityRGBall(rgb.r-255, rgb.g-255, rgb.b-255); FreeAndNil(proc); ThumbWidth := fThumbnailFrame.Width; ThumbHeight := fThumbnailFrame.Height; Update; end; end; {$ifdef IEDOTNETVERSION} procedure TImageEnMView.WMContextMenu(var Message: TWMContextMenu); begin // just to remove Delphi default behavior end; {$endif} {!! TImageEnMView.IEBeginDrag Declaration procedure IEBeginDrag(Immediate: Boolean; Threshold: Integer = -1); Description ImageEn's implementation of BeginDrag. You must use this for Drag/Drop operations in TImageEnMView Demos Demos\DragDrop\TImageEnMView_DragDrop\TImageEnMView_DragDrop.dpr Demos\Multi\Multiview2\Multiview2.dpr See Also -
- iemoOptimizeForDragging !!} procedure TImageEnMView.IEBeginDrag(Immediate: Boolean; Threshold: Integer); begin // Why this? Because BeginDrag calls MouseUp, but "Dragging" of VCL is still not True and MouseUp must know we are dragging fDragging := true; BeginDrag(immediate, Threshold); fDragging := Dragging; // get the official dragging value InitializeDragScrollTimer; end; {!! TImageEnMView.IEEndDrag Declaration procedure IEEndDrag; Description ImageEn's implementation of EndDrag. You must use this for Drag/Drop operations in TImageEnMView Demos Demos\DragDrop\TImageEnMView_DragDrop\TImageEnMView_DragDrop.dpr Demos\Multi\Multiview2\Multiview2.dpr See Also - !!} procedure TImageEnMView.IEEndDrag; begin EndDrag(true); fDragging := false; TerminateDragScrollTimer; end; // Handle automatic scrolling when we drag to the edges procedure TImageEnMView.InitializeDragScrollTimer; begin {$ifndef DISABLE_AUTO_SCROLL_WHEN_DRAG} if assigned(fDragScrollTimer) = False then fDragScrollTimer := TTimer.create(Self); fDragScrollCount := 0; fDragScrollTimer.Interval := 250; fDragScrollTimer.Enabled := True; fDragScrollTimer.OnTimer := DragScrollTimer; {$endif} end; // End automatic scrolling when dragging completes procedure TImageEnMView.TerminateDragScrollTimer; begin if assigned(fDragScrollTimer) then fDragScrollTimer.Enabled := False; end; // Handle automatic scrolling when we drag to the edges procedure TImageEnMView.DragScrollTimer(Sender: TObject); const Scrollable_Area = 30; Max_Speed_Up_Dragging_Pos = 50; var Pos: TPoint; iLineStep: Integer; bHaveScrolled: Boolean; bHaveVertScrolling: Boolean; bHaveHorzScrolling: Boolean; iScrollBarHeight: Integer; begin // Are we still dragging? Dragging may have terminated without the user calling IEEndDrag if Dragging = False then begin TerminateDragScrollTimer; exit; end; GetCursorPos(Pos); Pos := ScreenToClient(Pos); // Still over the control? if (Pos.X < 0) or (Pos.X > Width) or (Pos.Y < 0) or (Pos.Y > Height) then exit; bHaveScrolled := False; bHaveVertScrolling := (fCurrentGridWidth <> 0) and (fVHeight > ClientHeight); bHaveHorzScrolling := (fCurrentGridWidth <> -1) and (fVWidth > ClientWidth); // Vertical scrolling if bHaveVertScrolling and (Pos.X > 0) and (Pos.X < Width) then begin if fVScrollBarParams.LineStep = -1 then iLineStep := ThumbSizeInfo( itsCell ).Y - fVertBorder else iLineStep := fVScrollBarParams.LineStep; // Is there a horizontal scrollbar? iScrollBarHeight := 0; if ((fScrollBars = ssHorizontal) or (fScrollBars = ssBoth)) and (fVWidth > ClientWidth) then iScrollBarHeight := IEGlobalSettings().HScrollHeight; if Pos.Y < Scrollable_Area then begin SetViewY(fViewY - iLineStep); bHaveScrolled := True; end else if Pos.Y > Height - Scrollable_Area - iScrollBarHeight then begin SetViewY(fViewY + iLineStep); bHaveScrolled := True; end; end else // Horizontal scrolling if bHaveHorzScrolling and (Pos.Y > 0) and (Pos.Y < Height) then begin if fHScrollBarParams.LineStep = -1 then iLineStep := ThumbSizeInfo( itsCell ).X - fHorizBorder else iLineStep := fHScrollBarParams.LineStep; if Pos.X < Scrollable_Area then begin SetViewX(fViewX - iLineStep); bHaveScrolled := True; end else if Pos.X > Width - Scrollable_Area then begin SetViewX(fViewX + iLineStep); bHaveScrolled := True; end; end; if bHaveScrolled then begin ViewChange(0); if fDragScrollCount < Max_Speed_Up_Dragging_Pos then begin inc(fDragScrollCount); if fDragScrollCount mod 5 = 0 then fDragScrollTimer.Interval := MulDiv(fDragScrollTimer.Interval, 3, 4); // speed up the scrolling by reducing the timer interval end; end else begin InitializeDragScrollTimer; exit; end; end; {!! TImageEnMView.JobsRunning Declaration property JobsRunning: Integer; Description Returns the number of active threads which are loading thumbnails. Demo Demos\Multi\Thumbnails\Thumbnails.dpr !!} function TImageEnMView.GetJobsRunning: Integer; begin result := fThreadPoolIO.Count; end; {!! TImageEnMView.JobsWaiting Declaration property JobsWaiting: Integer; Description Returns the number of images/thumbnails waiting to be loaded. Demo Demos\Multi\Thumbnails\Thumbnails.dpr !!} function TImageEnMView.GetJobsWaiting: Integer; begin result := fThreadRequests.Count; end; {!! TImageEnMView.LoadFromFileOnDemand Declaration procedure LoadFromFileOnDemand(const FileName: WideString; Append: Boolean = false); Description Fills TImageEnMView with all frames of a multiple image file (AVI, MPEG, TIFF, etc.) by filling with filenames and all indexes of its frames (in the format 'FileName::0', 'FileName::1', etc.). In this way loading of individual frames will be delayed until they are required (i.e. frames are only loaded when they appear on-screen). It is mainly used for loading the frames of files with numerous frames (such as videos). When Append is false, the existing content of the TImageEnMView is cleared. Note: You can set TImageEnMView.MIO.Aborting := True to abort the loading of an OnDemand sequence Example ImageEnMView1.LoadFromFileOnDemand('C:\input.mpeg'); If input.mpeg has 1000 frames, then we will now have: ImageEnMView1.ImageFileName[0] = 'C:\input.mpeg::0' ImageEnMView1.ImageFileName[1] = 'C:\input.mpeg::1' ... ImageEnMView1.ImageFileName[999] = 'C:\input.mpeg::999' Demo Demos\InputOutput\LargeVideos\LargeVideos.dpr !!} procedure TImageEnMView.LoadFromFileOnDemand(const FileName: WideString; Append: Boolean); var FramesCount, i, ofs: Integer; lAnimation: TIEAnimation; begin lAnimation := Animation; fAnimation := nil; LockPaint(); MIO.Aborting := False; try if Append then begin ofs := ImageCount; end else begin ofs := 0; Clear(); end; FramesCount := IEGetFileFramesCount(FileName); for i := 0 to FramesCount - 1 do begin InsertImageEx( ofs + i ); ImageFileName[ ofs + i ] := Filename + IEM_Path_Index_Delimiter + IntToStr(i); if assigned( fOnImageAdded ) then fOnImageAdded( self, ofs + i ); end; finally fAnimation := lAnimation; UnLockPaint(); end; end; function CreateLinesArray(vect: TImageEnVect): PIELineArray; var i, hobj: Integer; r: TRect; begin getmem(result, SizeOf(TIELine) * vect.ObjectsCount); for i := 0 to vect.ObjectsCount-1 do begin hobj := vect.GetObjFromIndex(i); vect.GetObjRect(hobj, r); result[i].P.x := r.Left; result[i].P.y := r.Top; result[i].Q.x := r.Right; result[i].Q.y := r.Bottom; end; end; {!! TImageEnMView.CreateMorphingSequence Declaration procedure CreateMorphingSequence(Source: ; Target: ; FramesCount: Integer); Description Creates a sequence of frames which are the transformation of the Source image to Target image. FramesCount specifies the number of frames to create. Notes: - The of both images must be ie24RGB (true color) - The dimension of the images must be identical - The Source and Target must contain iekLINE objects to describe the transformation. The number of line objects must be identical and applied in the same order on both TImageEnVect components - Does not call Demo Demos\Other\Morphing\Morphing.dpr !!} procedure TImageEnMView.CreateMorphingSequence(Source: TImageEnVect; Target: TImageEnVect; FramesCount: Integer); var source_lines, dest_lines: PIELineArray; outimages_src, outimages_trg: TList; outcount, i: Integer; ie: TImageEnView; idx: Integer; begin if (Source.ObjectsCount=0) or (Target.ObjectsCount=0) or (Source.ObjectsCount<>Target.ObjectsCount) then exit; if (Source.IEBitmap = nil) or (Target.IEBitmap = nil) then exit; if (Source.IEBitmap.PixelFormat<>ie24RGB) or (Target.IEBitmap.PixelFormat<>ie24RGB) then exit; source_lines := nil; dest_lines := nil; outimages_src := nil; outimages_trg := nil; outcount := 0; try source_lines := CreateLinesArray(Source); dest_lines := CreateLinesArray(Target); outimages_src := TList.Create; outimages_trg := TList.Create; IEFields_warp( Source.IEBitmap, source_lines, dest_lines, Source.ObjectsCount, FramesCount, outimages_src); IEFields_warp( Target.IEBitmap, dest_lines, source_lines, Target.ObjectsCount, FramesCount, outimages_trg); idx := AppendImage; SetIEBitmapEx( idx , Source.IEBitmap); ie := TImageEnView.Create(nil); try outcount := outimages_src.Count; for i := 0 to outcount-1 do begin ie.IEBitmap.Assign(outimages_src[i]); ie.Update; ie.Proc.Merge(TIEBitmap(outimages_trg[outcount - 1 - i]), trunc((outcount - i) / outcount * 100)); idx := AppendImage; SetIEBitmapEx( idx , ie.IEBitmap ); end; finally FreeAndNil(ie); end; idx := AppendImage; SetIEBitmapEx( idx , Target.IEBitmap); finally for i := 0 to outcount-1 do TIEBitmap(outimages_src[i]).Free; FreeAndNil(outimages_src); for i := 0 to outcount-1 do TIEBitmap(outimages_trg[i]).Free; FreeAndNil(outimages_trg); freemem(dest_lines); freemem(source_lines); end; Update; end; {!! TImageEnMView.ImageEnVersion Declaration property ImageEnVersion: String; Description Returns the ImageEn version as a string. !!} function TImageEnMView.GetImageEnVersion: String; begin result := IEMAINVERSION; end; procedure TImageEnMView.SetImageEnVersion(Value: String); begin // this is a read-only property, but it must be displayed in object inspector end; procedure TImageEnMView.SaveSnapshot(FileName: WideString; SaveCache: Boolean; Compressed: Boolean; SaveParams: Boolean); var fs: TIEWideFileStream; begin fs := TIEWideFileStream.Create(FileName, fmCreate); try SaveSnapshot(fs, SaveCache, Compressed, SaveParams); finally fs.Free; end; end; function TImageEnMView.LoadSnapshot(FileName: WideString): Boolean; var fs: TIEWideFileStream; begin fs := TIEWideFileStream.Create(FileName, fmOpenRead or fmShareDenyWrite); try result := LoadSnapshot(fs); finally fs.Free; end; end; {!! TImageEnMView.SaveSnapshot Declaration procedure SaveSnapshot(FileName: WideString; SaveCache: Boolean = True; Compressed: Boolean = False; SaveParams: Boolean = False); procedure SaveSnapshot(Stream: TStream; SaveCache: Boolean = True; Compressed: Boolean = False; SaveParams: Boolean = False); Description Saves the image, cache data, text and dimensions of all frames to the specified stream or file. This can be used to create caching mechanism, like Windows .db files, to load quickly an entire directory of images. Value Description Filename/Stream Destination for snapshot SaveCache If enabled (default), the image cache is also saved. This will speed up display but require more disk space Compressed If enabled, an LZ compression algorithm is used to reduce disk space (though saving will be slower) SaveParams Enable to save the input/output parameters for all images
You can reload a saved snapshot using
. !!} procedure TImageEnMView.SaveSnapshot(Stream: TStream; SaveCache: Boolean; Compressed: Boolean; SaveParams: Boolean); begin SaveSnapshotEx(Stream, SaveCache, Compressed, SaveParams, nil); end; // versions (IEMVIEWSNAPSHOWVERSION): // 2: 2.3.2 // 3: 3.0.0 // 4: 3.0.5 // 5: 4.0.3 // 6: 4.1.1-B // 7: 5.0.1 // 8: 6.0.0 Move from TIEMText to Widesting for text procedure TImageEnMView.SaveSnapshotEx(Stream: TStream; SaveCache: Boolean; Compressed: Boolean; SaveParams: Boolean; GetExtraParams: TIEProcessStreamEvent); var ver: byte; i, i32: Integer; LZStream: TZCompressionStream; begin // magic IESaveStringToStream(Stream, 'MVIEWSNAPSHOT'); // version ver := IEMVIEWSNAPSHOTVERSION; Stream.Write(ver, SizeOf(byte)); Stream.Write(Compressed, SizeOf(boolean)); if Compressed then begin LZStream := TZCompressionStream.Create(Stream, zcDefault, 15); Stream := LZStream; end else LZStream := nil; try // fThumbWidth and fThumbHeight Stream.Write(fThumbWidth, SizeOf(integer)); Stream.Write(fThumbHeight, SizeOf(integer)); // fUpperGap and fBottomGap Stream.Write(fUpperGap, SizeOf(integer)); Stream.Write(fBottomGap, SizeOf(integer)); // SideGap and TextMargin Stream.Write(fSideGap, SizeOf(integer)); Stream.Write(fTextMargin, SizeOf(integer)); // StoreType Stream.Write(fStoreType, SizeOf(TIEStoreType)); // Parameters for descended components, such as TImageEnFolderMView if assigned(GetExtraParams) then GetExtraParams(Self, Stream, IEMVIEWSNAPSHOTVERSION); // images fIEMBitmap.fImageList.SaveToStream(Stream); // caches Stream.Write(SaveCache, SizeOf(boolean)); if SaveCache then fCacheList.SaveToStream(Stream); // images count i32 := fIEMBitmap.Count; Stream.Write(i32, SizeOf(integer)); // info for i := 0 to fIEMBitmap.Count-1 do begin fIEMBitmap.GetImageInfo( i ).SaveToStream(Stream, SaveCache, fIEMBitmap.fImageList, fCacheList); // I/O params (only of MIO embedded object) Stream.Write(SaveParams, SizeOf(boolean)); if SaveParams then MIO.Params[i].SaveToStream(Stream); end; finally if Compressed then LZStream.Free; end; end; {!! TImageEnMView.LoadSnapshot Declaration function LoadSnapshot(FileName: WideString): Boolean; function LoadSnapshot(Stream: TStream): Boolean; Description Loads the image, cache data, text and dimensions of frames that have been save to a stream or file using . This can be used to create caching mechanism, like Windows .db files, to load quickly an entire directory of images. !!} function TImageEnMView.LoadSnapshot(Stream: TStream): Boolean; begin result := LoadSnapshotEx(Stream, nil); end; function TImageEnMView.LoadSnapshotEx(Stream: TStream; SetExtraParams: TIEProcessStreamEvent): Boolean; var magicStr: AnsiString; ver: byte; i, i32: Integer; LoadCache: Boolean; LoadParams: Boolean; Compressed: Boolean; LZStream: TZDecompressionStream; ii : TIEImageInfo; bHaveTopText, bHaveInfoText, bHaveBottomText: Boolean; begin result := false; bHaveTopText := False; bHaveInfoText := False; bHaveBottomText := False; // magic IELoadStringFromStream(Stream, magicStr); if magicStr <> 'MVIEWSNAPSHOT' then exit; // version Stream.Read(ver, SizeOf(byte)); Clear; Stream.Read(Compressed, SizeOf(boolean)); if Compressed then begin LZStream := TZDecompressionStream.Create(Stream); Stream := LZStream; end else LZStream := nil; try // fThumbWidth and fThumbHeight Stream.Read(fThumbWidth, SizeOf(integer)); Stream.Read(fThumbHeight, SizeOf(integer)); if ver >= 3 then begin // fUpperGap and fBottomGap Stream.Read(fUpperGap, SizeOf(integer)); Stream.Read(fBottomGap, SizeOf(integer)); end; if ver >= 7 then begin // SideGap and TextMargin Stream.Read(fSideGap, SizeOf(integer)); Stream.Read(fTextMargin, SizeOf(integer)); end; if ver >= 4 then Stream.Read(fStoreType, SizeOf(TIEStoreType)); // Parameters for descended components, such as TImageEnFolderMView if assigned(SetExtraParams) then SetExtraParams(Self, Stream, ver); // images result := fIEMBitmap.fImageList.LoadFromStream(Stream); if not result then exit; // caches Stream.Read(LoadCache, SizeOf(boolean)); if LoadCache then result := fCacheList.LoadFromStream(Stream); if not result then exit; // images count Stream.Read(i32, SizeOf(integer)); // info for i := 0 to i32 - 1 do begin ii := TIEImageInfo.CreateFromStream( self, Stream, ver, LoadCache, fIEMBitmap.fImageList, fCacheList ); fIEMBitmap.fImageInfo.Add( ii ); if ( bHaveTopText = False ) and ( ii.TopText <> '' ) then bHaveTopText := true; if ( bHaveInfoText = False ) and ( ii.InfoText <> '' ) then bHaveInfoText := true; if ( bHaveBottomText = False ) and ( ii.BottomText <> '' ) then bHaveBottomText := true; SetLastImOp( IEM_OP_INSERT, i ); CallBitmapChangeEvents; fCheckedCount := -1; // I/O params (only of MIO embedded object) if ver >= 4 then begin Stream.Read(LoadParams, SizeOf(boolean)); if LoadParams then MIO.Params[i].LoadFromStream(Stream); end; end; UpdateTopTextHeight(( fDefaultTopText <> iedtNone ) or bHaveTopText ); UpdateInfoTextHeight(( fDefaultInfoText <> iedtNone ) or bHaveInfoText ); UpdateBottomTextHeight(( fDefaultBottomText <> iedtNone ) or bHaveBottomText ); finally if Compressed then LZStream.Free; end; if LoadCache then UpdateEx(false) else UpdateEx(true); result := true; end; {!! TImageEnMView.RemoveBlankPages Declaration function RemoveBlankPages(Tolerance: Double = 0.0; Complete: boolean = true; LeftToRight: boolean = true): Integer; Description Locate images in the TImageEnMView of a single color (i.e. blank images) and remove them. Parameter Description Tolerance Determines how tolerant to be in checking color variance (in the range 0.0 to 1.0). For example, if tolerance is 0.1 then 10% of pixels can be of different color and the image would still be considered "blank" Complete If true all images are checked. Otherwise the check stops once the first non blank image has been found and removed. LeftToRight If true the scan starts at the first image and proceeds to the last (otherwise it proceeds in reverse order)
Returns the number of removed pages. Notes: - Does not call
- Cannot be used if a is attached to the control Examples // Remove last blank pages ImageEnMView1.RemoveBlankPages( 0.0, False, False ); // Remove any pages that are 95% blank ImageEnMView1.RemoveBlankPages( 0.05 ); !!} function TImageEnMView.RemoveBlankPages(Tolerance: Double = 0; Complete: boolean = true; LeftToRight: boolean = true): Integer; begin if IEMBitmap_IsTIEDBMultiBitmap then raise EIEException.create('Not available when attached to TIEDBMultiBitmap'); LockPaint; result := TIEMultiBitmap( fIEMBitmap ).RemoveBlankPages( Tolerance, Complete, LeftToRight ); if fSelectedItem > GetImageCount - 1 then fSelectedItem := GetImageCount - 1; UnlockPaint; if Result > 0 then Update; end; {!! TImageEnMView.RemoveDuplicates Declaration function RemoveDuplicates(): Integer; Description Locate images with duplicate content in the TImageEnMView and remove other instances. Returns the number of removed pages. Notes: - Does not call - Cannot be used if a is attached to the control Examples // Ensure there are no blank images in our TImageEnMView after filling it from a folder ImageEnMView1.Clear; ImageEnMView1.StoreType := ietNormal; ImageEnMView1.FillFromDirectory('C:\Images'); ImageEnMView1.RemoveDuplicates(); !!} function TImageEnMView.RemoveDuplicates(): Integer; begin if IEMBitmap_IsTIEDBMultiBitmap then raise EIEException.create('Not available when attached to TIEDBMultiBitmap'); LockPaint; result := TIEMultiBitmap( fIEMBitmap ).RemoveDuplicates(); if fSelectedItem > GetImageCount - 1 then fSelectedItem := GetImageCount - 1; UnlockPaint; if Result > 0 then Update; end; {!! TImageEnMView.DisplayImageAt Declaration procedure DisplayImageAt(idx: Integer; x, y: Integer); Description Scrolls the control to display image, idx, at specified position in the current view. Parameter Description idx Index of the image to display x Horizontal offset in client area y Vertical offset in client area
Example // make then tenth image visible at 0, 0 (Top-left of control) ImageEnMView1.DisplayImageAt(9, 0, 0); !!} procedure TImageEnMView.DisplayImageAt(idx: Integer; x, y: Integer); var newViewX, newViewY: Integer; image: TIEImageInfo; begin image := fIEMBitmap.GetImageInfo( idx ); newViewX := image.X + x; newViewY := image.Y + y; SetViewXY(newViewX, newViewY); end; ////////////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Animation Support {!! TImageEnMView.Animation Declaration property Animation:
; Description Uses a special animated mode to display your images. Two internal animations are available: - : Coverflow style animation - : Circular flow animation Setting Animation to nil disables animation. Default: nil (no animation) Example ImageEnMView1.Animation := TIEHorizontalFlow.Create(); Demo Demos\Display\MviewFlow\MviewFlow.dpr See Also - !!} procedure TImageEnMView.SetAnimation(value: TIEAnimation); begin if assigned(fAnimation) then begin fAnimationTimer.Enabled := false; FreeAndNil(fAnimation); end; fAnimation := value; if assigned(fAnimation) then begin // hide scroll bars IEShowScrollBar(handle, SB_VERT, false, fFlatScrollBars); IEShowScrollBar(handle, SB_HORZ, false, fFlatScrollBars); UpdateEx(false); fAnimation.SetupEvents(AnimGetImage, AnimReleaseImage, AnimGetImageInfo); fAnimation.ViewWidth := ClientWidth; fAnimation.ViewHeight := ClientHeight; fAnimation.ImageCount := ImageCount; fAnimationTimer.Interval := 10; fAnimationTimer.OnTimer := AnimTimer; fAnimationTimer.Enabled := true; end; Update(); end; procedure TImageEnMView.AnimGetImageInfo(Sender: TObject; imageIndex: Integer; isVisible: Boolean; var ImageWidth: Integer; var ImageHeight: Integer; var text: WideString); var info: TIEImageInfo; begin ImageWidth := 0; ImageHeight := 0; info := fIEMBitmap.GetImageInfo( imageIndex ); if isVisible or // We need the actual image size (( info <> nil ) and ( info.image <> nil )) then // Or image is already loaded begin // Image loading will be automatically forced if not yet loaded ImageWidth := self.ImageWidth[imageIndex]; ImageHeight := self.ImageHeight[imageIndex]; end; if (ImageWidth = 0) or (ImageHeight = 0) then begin // return thumb size (if still not loaded) ImageWidth := self.ThumbSizeInfo( itsCell ).X; ImageHeight := self.ThumbSizeInfo( itsCell ).Y; end; if assigned(fOnAnimationText) then fOnAnimationText(self, imageIndex, text) else text := GetDisplayName( ImageFileName[ imageIndex ] ); end; procedure TImageEnMView.AnimGetImage(Sender: TObject; imageIndex: Integer; var image: TIEBitmap; var text: WideString); begin image := GetTIEBitmap(imageIndex); text := GetDisplayName( ImageFileName[ imageIndex ] ); end; procedure TImageEnMView.AnimReleaseImage(Sender: TObject; imageIndex: Integer; var image: TIEBitmap); begin ReleaseBitmap(imageIndex, false); end; procedure TImageEnMView.AnimPaintTo(dest: TIEBitmap); begin if fAnimation.NeedRefresh then begin PaintBackgroundTo(dest.VclBitmap); fAnimation.Display(dest); end; end; procedure TImageEnMView.AnimTimer(Sender: TObject); begin Paint(); end; ////////////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Copy selection from one TImageEnMView to another (assumes multiselction and that both have same image set) procedure TImageEnMView.CopySelection(SourceMView : TImageEnMView); var q: integer; lMultiSelecting: boolean; begin If ImageCount <> SourceMView.ImageCount then exit; if fEnableMultiSelect then begin DeselectNU; lMultiSelecting := fMultiSelecting; fMultiSelecting := true; for q := 0 to SourceMView.ImageCount - 1 do if SourceMView.IsSelected(q) then SetSelectedItemNU(q); fMultiSelecting := lMultiSelecting; UpdateEx(false); end; end; {!! TImageEnMView.CalcGridWidth Declaration function CalcGridWidth(): Integer; Description Returns the number of columns displayed in the grid. This is mainly used when the column count is automatically calculated (i.e. when = -1). !!} function TImageEnMView.CalcGridWidth(): Integer; begin if fStyle = iemsColumns then Result := 1 else case fCurrentGridWidth of -1: begin result := (ClientWidth - fHorizBorder) div ThumbSizeInfo( itsOuter ).X; if (result < 1) and (ImageCount > 0) then result := 1; end; 0: result := ImageCount; else result := fCurrentGridWidth; end; end; {!! TImageEnMView.CalcGridHeight Declaration function CalcGridHeight(): Integer; Description Returns the number of rows displayed in the grid. !!} function TImageEnMView.CalcGridHeight(): Integer; var gw: integer; begin gw := CalcGridWidth(); if (ImageCount > 0) and (gw <> 0) then result := Ceil(ImageCount / gw) else result := 0; end; procedure TImageEnMView.CheckSelectedImageIsVisible; var info: TIEImageInfo; iViewX, iViewY : integer; begin if (fLockPaint > 0) or (fLockUpdate > 0) then exit; if fSelectedItem > GetImageCount - 1 then fSelectedItem := GetImageCount - 1; if assigned(Parent) and (fSelectedItem >= 0) and (fMultiSelecting = False) then begin iViewX := fViewX; iViewY := fViewY; info := fIEMBitmap.GetImageInfo( fSelectedItem ); if info.Col = 0 then iViewX := 0 else if info.X < iViewX then iViewX := info.X else if info.X + ThumbSizeInfo( itsCell ).X > iViewX + ClientWidth then iViewX := info.X - ClientWidth + ThumbSizeInfo( itsCell ).X; if info.Row = 0 then iViewY := 0 else if info.Y < iViewY then iViewY := info.Y else if info.Y + ThumbSizeInfo( itsCell ).Y > iViewY + ClientHeight then iViewY := info.Y - ClientHeight + ThumbSizeInfo( itsCell ).Y; SetViewXY(iViewX, iViewY); end; end; {!! TImageEnMView.Seek Declaration function Seek(Page : ) : integer; Description When is mdSingle then Seek sets to display the first/previous/next/last image. Otherwise it sets to move the selection to the first/previous/next/last image. Returns the new page index. Example // Display a single image ImageEnMView1.DisplayMode := mdSingle; .. // Advance to the next image ImageEnMView1.IO.Seek(ieioSeekNext); !!} function TImageEnMView.Seek(Destination : TIEIOSeekDestination): Integer; // NPC: 23/11/11 var iIndex: Integer; begin Result := -1; if fIEMBitmap.Count = 0 then exit; if fDisplayMode = mdSingle then iIndex := VisibleFrame else iIndex := SelectedImage; result := 0; case Destination of ieioSeekFirst: result := 0; ieioSeekPrior: result := imax(0, iIndex - 1); ieioSeekNext: result := imin(fIEMBitmap.Count - 1, iIndex + 1); ieioSeekLast: result := fIEMBitmap.Count - 1; end; if fDisplayMode = mdSingle then VisibleFrame := Result else begin SelectedImage := Result; CheckSelectedImageIsVisible; end; end; procedure TImageEnMView.DoAfterEvent(e: TIEAfterEvent); begin if assigned(fOnAfterEvent) then fOnAfterEvent(self, e); end; procedure TImageEnMView.CNKEYUP(var Message: TMessage); begin inherited; case Message.wParam of VK_LEFT, VK_RIGHT, VK_UP, VK_DOWN, VK_PRIOR, VK_NEXT, VK_HOME, VK_END: DoAfterEvent(ieaeKeyUp); // because no KeyUp event is generated on special keys end; end; {!! TImageEnMView.SetAllText Declaration procedure SetAllText(TopText : ; InfoText : ; BottomText : );; Description Set the values for , and . Example // Show only the filename ImageEnMView1.SetAllText( iedtNone, iedtNone, iedtFileName ); !!} procedure TImageEnMView.SetAllText(TopText : TIEImageEnMViewDefaultText; InfoText : TIEImageEnMViewDefaultText; BottomText : TIEImageEnMViewDefaultText); var I: Integer; begin LockUpdate; try for I := 0 to ImageCount - 1 do begin ImageTopText [ I ] := IEMDefaultTextToConst( TopText ); ImageInfoText [ I ] := IEMDefaultTextToConst( InfoText ); ImageBottomText [ I ] := IEMDefaultTextToConst( BottomText ); end; finally UnlockUpdate; end; end; constructor TIECachedIcon.Create(aBmp: TIEBitmap; const sExt: string); begin inherited Create(); Bmp := TIEBitmap.Create(aBmp); Ext := Uppercase(sExt); end; destructor TIECachedIcon.Destroy(); begin Bmp.Free(); inherited; end; function TIECachedIcon.MatchesExt(const sExt : string) : Boolean; begin Result := Uppercase(sExt) = Ext; end; constructor TIECachedIconList.Create(Owner : TImageEnMView; iMaxIconCount : Integer); begin inherited Create; fDataList := TList.create; fOwner := Owner; fMaxIconCount := iMaxIconCount; end; destructor TIECachedIconList.Destroy(); begin Clear(); fDataList.free(); inherited; end; procedure TIECachedIconList.ClearLastItem; var Idx: Integer; begin Idx := fDataList.Count - 1; TIECachedIcon(fDataList[Idx]).Free(); fDataList.Delete(Idx); end; procedure TIECachedIconList.Clear(); var i: integer; begin for i := 0 to fDataList.Count - 1 do TIECachedIcon(fDataList[i]).Free(); fDataList.Clear(); end; function TIECachedIconList.GetCacheName(aType : TCachedIconType; const sFilename : string; bIsFolder : Boolean) : string; const _Folder_Item = '~FOLDER'; begin if bIsFolder then Result := _Folder_Item else Result := ExtractFileExt(sFilename); if Result <> '' then begin if aType = citIconOnly then Result := Result + '~I' else Result := Result + '~F'; end; end; function TIECachedIconList.LookUpExt(const sExt : string) : Integer; var i: integer; begin Result := -1; // CHECK CACHE VALIDITY // Most property changes will automatically reset the icon cache, but not changes to the soft shadow, so ensure properties still match if (fOwner.SoftShadow.Enabled <> fOwnerSoftShadowEnabled) or (fOwner.SoftShadow.Radius <> fOwnerSoftShadowRadius) then begin fOwnerSoftShadowEnabled := fOwner.SoftShadow.Enabled; fOwnerSoftShadowRadius := fOwner.SoftShadow.Radius; Clear(); exit; end; // Locate the extension in our list for i := 0 to fDataList.Count - 1 do if TIECachedIcon(fDataList[i]).MatchesExt(sExt) then begin Result := i; Break; end; end; // bWantCopy = True: Dest is pointer to Bitmap in list (don't create or free). bWantCopy = False: Copy of bitmap is made, must be created and freed function TIECachedIconList.RetrieveFromCache(aType : TCachedIconType; const sFilename : string; bIsFolder : Boolean; var Dest : TIEBitmap; bWantCopy : Boolean): boolean; const File_Extensions_With_Custom_Icons = '*.exe;*.lnk;*.ico;'; Cache_Folder_Icons = False; // Folder icons can change by content var Idx: Integer; sExt: string; begin Result := False; // Is it a file type with a changeable icon? if IEFilenameInExtensions( sFilename, File_Extensions_With_Custom_Icons ) then exit; if ( Cache_Folder_Icons = False ) and bIsFolder then exit; sExt := GetCacheName(aType, sFilename, bIsFolder); Idx := LookUpExt(sExt); if Idx >= 0 then begin if bWantCopy then Dest. Assign( TIECachedIcon(fDataList[Idx]).Bmp ) else Dest := TIECachedIcon(fDataList[Idx]).Bmp; Result := True; // Promote the item if Idx <> 0 then fDataList.Move(Idx, 0); end; end; procedure TIECachedIconList.SaveToCache(Image : TIEBitmap; aType : TCachedIconType; const sFilename : string; bIsFolder : Boolean); var aItem : TIECachedIcon; Idx: Integer; sExt: string; begin sExt := GetCacheName(aType, sFilename, bIsFolder); if (sExt = '') or (Image.Width < 2) then exit; Idx := LookUpExt(sExt); if Idx = -1 then begin aItem := TIECachedIcon.Create(Image, sExt); fDataList.Insert(0, aItem); end else begin // Promote the item if Idx <> 0 then fDataList.Move(Idx, 0); end; if (fMaxIconCount > 0) and (fDataList.Count > fMaxIconCount) then ClearLastItem(); end; function TImageEnMView.BiDiModeIsRTL : Boolean; begin Result := ( fDisplayMode <> mdSingle ) and ( BiDiMode in [ bdRightToLeft ]); // Not: bdRightToLeftNoAlign, bdRightToLeftReadingOnly end; procedure TImageEnMView.ProbeLastSort(out OrderBy: TIEImageEnMViewSortBy; out Ascending: boolean; out CaseSensitive: Boolean); begin OrderBy := fCurrentOrderBy; Ascending := fCurrentAscending; CaseSensitive := fCurrentCaseSensitive; end; procedure TImageEnMView.WMEnabled(var Msg: TMessage); begin Invalidate; inherited; end; procedure TImageEnMView.WMGestureNotify(var Msg: TIEWMGestureNotify); var c: integer; gc: array of TIEGESTURECONFIG; begin inherited; if fGestures.Enabled and IEHasGestures() then begin IEUnregisterTouchWindow(Handle); if fGestures.fPan.Enabled then begin c := length(gc); SetLength(gc, c + 1); gc[c].dwID := IEGID_PAN; gc[c].dwWant := IEGC_PAN or IEGC_PAN_WITH_INERTIA; if fGestures.fPan.PanWithSingleFingerVertically then gc[c].dwWant := gc[c].dwWant or IEGC_PAN_WITH_SINGLE_FINGER_VERTICALLY; if fGestures.fPan.PanWithSingleFingerHorizontally then gc[c].dwWant := gc[c].dwWant or IEGC_PAN_WITH_SINGLE_FINGER_HORIZONTALLY; gc[c].dwBlock := IEGC_PAN_WITH_GUTTER; end; if fGestures.fZoom.Enabled then begin c := length(gc); SetLength(gc, c + 1); gc[c].dwID := IEGID_ZOOM; gc[c].dwWant := IEGC_ALLGESTURES; gc[c].dwBlock := 0; end; IESetGestureConfig(Handle, 0, length(gc), @gc[0], sizeof(TIEGESTURECONFIG)); end; end; procedure TImageEnMView.DoImageEnGestureEvent(const GInfo: TIEGESTUREINFO; var Handled: boolean); var Flags: TIEGestureFlags; ID: TIEGestureID; begin if assigned(fOnImageEnGesture) then begin Flags := []; if (IEGF_BEGIN and GInfo.dwFlags) <> 0 then Flags := Flags + [iegfBegin]; if (IEGF_INERTIA and GInfo.dwFlags) <> 0 then Flags := Flags + [iegfInertia]; if (IEGF_END and GInfo.dwFlags) <> 0 then Flags := Flags + [iegfEnd]; ID := TIEGestureID(GInfo.dwID - 1); fOnImageEnGesture(self, Flags, ID, GInfo.ptsLocation, GInfo.ullArguments and $FFFFFFFF, (GInfo.ullArguments shr 32) and $FFFF, (GInfo.ullArguments shr 48) and $FFFF, (GInfo.ullArguments shr 32), Handled); end; end; function TImageEnMView.PerformZoomSnap(Value: double): double; begin result := Value; if fGestures.fZoom.SnapValues then begin if abs(result - 100.0) <= fGestures.fZoom.SnapDelta then result := 100; end; end; procedure TImageEnMView.WMGesture(var Msg: TMessage); var gInfo: TIEGESTUREINFO; value: integer; v: double; isBegin: boolean; isInertia: boolean; handled: boolean; begin Msg.Result := 1; // not handled if fGestures.Enabled and IEHasGestures() then begin FillChar(gInfo, sizeof(gInfo), 0); gInfo.cbSize := sizeof(gInfo); if IEGetGestureInfo(Msg.LParam, @gInfo) then begin try handled := false; DoImageEnGestureEvent(gInfo, handled); if not handled then begin value := gInfo.ullArguments and $FFFFFFFF; isBegin := (IEGF_BEGIN and gInfo.dwFlags) <> 0; isInertia := (IEGF_INERTIA and gInfo.dwFlags) <> 0; case gInfo.dwID of IEGID_ZOOM: begin // begin zoom if isBegin then begin fGestureStartValue := value; fGestureBaseZoom := Zoom; end // perform zoom else if fGestures.fZoom.Enabled and (not isInertia or fGestures.fZoom.Inertia) then begin v := fGestureBaseZoom * (value / fGestureStartValue); v := dmax(v, fGestures.fZoom.Min); v := dmin(v, fGestures.fZoom.Max); v := v * fGestures.fZoom.Multiplier; Zoom := PerformZoomSnap(v); Msg.Result := 0; // handled end end; IEGID_PAN: begin // begin pan if isBegin then begin fGestureStartX := gInfo.ptsLocation.x; fGestureStartY := gInfo.ptsLocation.y; fGestureBaseViewX := ViewX; fGestureBaseViewY := ViewY; end // perform pan else if fGestures.fPan.Enabled and (not isInertia or fGestures.fPan.Inertia) then begin v := fGestureBaseViewX + (fGestureStartX - gInfo.ptsLocation.x); v := dmax(v, fGestures.fPan.BoundingBox.Left); v := dmin(v, fGestures.fPan.BoundingBox.Right); v := v * fGestures.fPan.Multiplier; ViewX := trunc(v); v := fGestureBaseViewY + (fGestureStartY - gInfo.ptsLocation.y); v := dmax(v, fGestures.fPan.BoundingBox.Top); v := dmin(v, fGestures.fPan.BoundingBox.Bottom); v := v * fGestures.fPan.Multiplier; ViewY := trunc(v); Msg.Result := 0; // handled end; end; end; end else begin // handled by user (in OnImageEnGesture event) Msg.Result := 0; // handled end; finally if Msg.Result = 0 then IECloseGestureInfoHandle(Msg.LParam); end; end end; if Msg.Result <> 0 then inherited; end; constructor TIEMViewerGestures.Create(); begin inherited; fPan := TIEGesturePanOptions.Create(); fZoom := TIEGestureZoomOptions.Create(); // Pan defaults fPan.Enabled := false; fPan.Inertia := true; fPan.BoundingBox := Rect(Low(integer), Low(integer), High(integer), High(integer)); fPan.Multiplier := 1.0; fPan.SnapValues := false; fPan.SnapDelta := 0.0; fPan.PanWithSingleFingerVertically := True; fPan.PanWithSingleFingerHorizontally := True; // Zoom defaults fZoom.Enabled := false; fZoom.Inertia := true; fZoom.Min := 1.0; fZoom.Max := 8000.0; fZoom.Multiplier := 1.0; fZoom.SnapValues := true; fZoom.SnapDelta := 5.0; end; destructor TIEMViewerGestures.Destroy(); begin fPan.Free(); fZoom.Free(); inherited; end; function TIEMViewerGestures.GetEnabled(): boolean; begin result := fPan.Enabled or fZoom.Enabled; end; function TImageEnMView.GetIEMBitmap: TIECustomMultiBitmap; begin result := fIEMBitmap; end; {!! TImageEnMView.SetExternalMBitmap Declaration procedure SetExternalMBitmap(value : ); Description Allows a custom or object to be attached to the TImageEnMView. The TImageEnMView will automatically display changes to the attached Multi-Bitmap. It is mainly used to make a TImageEnMView DB aware. Notes: - You must create and destroy the external multi-bitmap yourself - Use SetExternalMBitmap( nil ) to reset usage to the internal Example // Create DB Aware TImageEnMView procedure TMainForm.FormCreate(Sender: TObject); begin ... Open a database table ... fDBMBitmap := TIEDBMultiBitmap.create( DataSource1, 'Name', 'Image' ); ImageEnMView1.SetExternalMBitmap( fDBMBitmap ); end; procedure TMainForm.FormDestroy(Sender: TObject); begin ImageEnMView1.SetExternalMBitmap( nil ); FreeAndNil( fDBMBitmap ); end; !!} procedure TImageEnMView.SetExternalMBitmap(value : TIECustomMultiBitmap); begin if value = nil then begin // Use internal fIEMBitmap if fIEMBitmapIsExternal then begin if assigned( fIEMBitmap ) then begin fIEMBitmap.OnUpdateParams := nil; fIEMBitmap.fOwner := nil; end; fIEMBitmap := nil; fIEMBitmap := TIEMultiBitmap.Create( True ); end; fIEMBitmapIsExternal := False; end else begin // Use external IEMBitmap if fIEMBitmapIsExternal = False then FreeAndNil( fIEMBitmap ); fIEMBitmap := value; fIEMBitmapIsExternal := True; end; fIEMBitmap.OnUpdateParams := UpdateParams; fIEMBitmap.fOwner := Self; // Free fImageEnMIO and fImageEnProc so that they use the newly attached TIEMultiBitmap if assigned(fImageEnMIO) then FreeAndNil(fImageEnMIO); if assigned(fImageEnProc) then FreeAndNil(fImageEnProc); Reset; end; {$IFDEF UNITTESTING} function TImageEnMView.UnitTesting_GetExternalMBitmap: TIECustomMultiBitmap; begin if fIEMBitmapIsExternal then Result := fIEMBitmap else Result := nil; end; {$ENDIF} // Called from attached TIEMultiBitmap when the params need to realigned procedure TImageEnMView.UpdateParams(Sender : TObject; Operation : Integer; Idx : integer; ExtraParam: Integer); begin SetLastImOp( Operation, Idx, ExtraParam ); end; function TImageEnMView.IEMBitmap_IsTIEDBMultiBitmap: Boolean; begin Result := fIEMBitmap.ClassName = 'TIEDBMultiBitmap'; end; // Returns the pointer to the image of the specified filename (and optionally index) in the cache list function TImageEnMView.FindImageInCache( idx: Integer; const sFilename: string ): Pointer; begin Result := nil; if ( idx < 0 ) or ( sFilename = '' ) then exit; case fImageCacheReusage of iecrLoose : Result := fCacheList.GetImageByIdentifier( sFilename ); iecrStrict : Result := fCacheList.GetImageByIdentifier( IntToStr( idx ) + '/' + sFilename ) end; end; procedure TImageEnMView.ClickColumnsHeaderRowCell(Col: TIEMTextPos); begin // Not implemented in TImageEnMView end; procedure TImageEnMView.DrawColumnsHeaderRowCell(Canvas: TCanvas; Rect: TRect; Col: TIEMTextPos); begin // Not implemented in TImageEnMView end; {!! TImageEnMView.ShowThumbnailHint Declaration property ShowThumbnailHint : Boolean; Description Automatically fills the control's Hint property with full details of the thumbnail under the cursor. You can specify the hint display time using !!} procedure TImageEnMView.SetShowThumbnailHint(const Value: Boolean); begin if fShowThumbnailHint <> Value then begin fShowThumbnailHint := Value; if fShowThumbnailHint then ShowHint := True else Hint := ''; end; end; {!! TImageEnMView.FilenameToIndex Declaration function FilenameToIndex(const sFilename : string) : integer; Description Returns the index of the specified filename or -1 if the file does not exist in the list. sFilename must be a full path (file folder and name). Example // Set caption of "Image.jpg" to "Cool Image" idx := IEFolderMView.FilenameToIndex('C:\My Images\Image.jpg'); if idx >=0 then IEFolderMView.ImageInfoText[idx].Caption := 'Cool Image'; !!} function TImageEnMView.FilenameToIndex(const sFilename : string) : integer; var I: Integer; begin Result := -1; if sFilename = '' then exit; for I := 0 to ImageCount - 1 do begin if SameText(ImageFilename[I], sFilename) then begin Result := I; Break; end; end; end; procedure TImageEnMView.CMHintShow(var Message: TMessage); begin if ShowHint and fShowThumbnailHint then TCMHintShow(Message).HintInfo^.HideTimeout := IEGlobalSettings().CustomHintTimeout; end; {$ELSE} // {$ifdef IEINCLUDEMULTIVIEW} interface implementation {$ENDIF} end.