BSOne.SFC/EM.Lib/ImageEn_SRC/Source/iexWindowsFunctions.pas

2253 lines
68 KiB
Plaintext

(* 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: iexWindowsFunctions.pas
Description: Windows File Functions
File version: 1002
*)
unit iexWindowsFunctions;
{$I ie.inc}
interface
uses
{$ifdef IEHASUITYPES} System.UITypes, {$endif}
{$IFDEF IEINCLUDEMULTIVIEW} iemview, {$endif}
Windows, Forms, ActiveX, ComObj, Controls, Classes, hyiedefs, Messages;
type
{!!
<FS>TIEFileDropEvent
<FM>Declaration<FC>
}
TIEFileDropEvent = procedure(Sender: TObject; ssFiles : TStrings; dwEffect: Integer) of object;
{!!}
{!!
<FS>TIEFileDragDrop
<FM>Declaration<FC>
TIEFileDragDrop = class(TInterfacedObject, IDropTarget, IDropSource)
public
property ActivateDropping : Boolean;
property DropActions : <A TIEFileDragDropActions> ;
constructor Create(Control: TWinControl; OnFileDrop : <A TIEFileDropEvent>);
destructor Destroy; override;
procedure InitiateDragging(ssFilenames : TStrings; DragActions: <A TIEFileDragDropActions>);
end;
<FM>Description<FN>
Class to provide support for dragging and dropping files from/to Windows Explorer (and other applications). Used by <A TImageEnFolderMView>.
See iexFolderMView.pas for example usage.
!!}
// CLASS TO HANDLE DRAGGING/DROPPING FILES TO/FROM WINDOWS EXPLORER
TIEFileDragDrop = class(TInterfacedObject, IDropTarget, IDropSource)
private
fControl : TWinControl;
fControlHandle : HWND;
fDroppingActive : Boolean;
fOnFileDrop : TIEFileDropEvent;
fDropActions : TIEFileDragDropActions;
procedure GetFileNames(const dataObj: IDataObject; Dest: TStrings);
function GetDataObject(ssFiles: TStrings): IDataObject;
function GetDragEffect(KeyState : Integer) : Integer;
procedure SetDroppingActive(const Value: Boolean);
// Supporting IDropTarget
function DragEnter(const dataObj: IDataObject; grfKeyState: Integer; pt: TPoint; var dwEffect: Integer): HResult; stdcall;
function DragOver(grfKeyState: Longint; pt: TPoint; var dwEffect: Longint): HResult; stdcall;
function DragLeave: HResult; stdcall;
function Drop(const dataObj: IDataObject; grfKeyState: Longint; pt: TPoint; var dwEffect: Longint): HResult; stdcall;
// Supporting IDropSource
function QueryContinueDrag(fEscapePressed: BOOL; grfKeyState: Longint): HResult; stdcall;
function GiveFeedback(dwEffect: Longint): HResult; stdcall;
public
property ActivateDropping : Boolean read fDroppingActive write SetDroppingActive;
property DropActions : TIEFileDragDropActions read fDropActions write fDropActions;
constructor Create(Control: TWinControl; OnFileDrop : TIEFileDropEvent);
destructor Destroy; override;
procedure InitiateDragging(ssFilenames : TStrings; DragActions: TIEFileDragDropActions);
end;
// CLASS TO MONITOR CHANGES TO A FOLDER
// Based on Cromis.DirectoryWatch
// http://www.cromis.net/blog/downloads/
// Created by Iztok Kacin, Cromis (iztok.kacin@gmail.com).
// Used by permission (10-7-13)
const
cShutdownTimeout = 3000;
cFileWaitTimeout = 0;
type
{!!
<FS>TWatchOptions
<FM>Declaration<FC>
}
// the filters that control when the watch is triggered
TWatchOption = (woFileName, woFolderName, woAttributes, woSize, woLastWrite, woLastAccess, woCreation, woSecurity);
TWatchOptions = set of TWatchOption;
{!!}
{!!
<FS>TWatchActions
<FM>Declaration<FC>
}
// the filters that control when the watch is triggered
// the actions that are the result of the watch being triggered
TWatchAction = (waAdded, waRemoved, waModified, waRenamedOld, waRenamedNew);
TWatchActions = set of TWatchAction;
{!!}
{!!
<FS>TFileChangeNotifyEvent
<FM>Declaration<FC>
}
TFileChangeNotifyEvent = procedure(const Sender: TObject;
const Action: TWatchAction;
const FileName: string
) of Object;
{!!}
{!!
<FS>TOnError
<FM>Declaration<FC>
}
TOnError = procedure(const Sender: TObject;
const ErrorCode: Integer;
const ErrorMessage: string
) of Object;
{!!}
{!!
<FS>TIEFolderWatch
<FM>Declaration<FC>
TIEFolderWatch = class
public
constructor Create;
destructor Destroy; override;
procedure Start;
procedure Stop;
function Running: Boolean;
property WatchSubTree: Boolean;
property WatchOptions: <A TWatchOptions>;
property WatchActions: <A TWatchActions>;
property BufferSize: Integer;
property Path: string;
property OnNotify: <A TFileChangeNotifyEvent>;
property OnChange: TNotifyEvent;
property OnError: <A TOnError>;
end;
<FM>Description<FN>
Class that automatically notifies changes to files within a specified folder. Used by <A TImageEnFolderMView>.
See iexFolderMView.pas for example usage.
<FM>Attribution<FC>
Based on Cromis.DirectoryWatch by Iztok Kacin, Cromis (iztok.kacin@gmail.com).
<L http://www.cromis.net/blog/downloads/>www.cromis.net</L>
!!}
TIEFolderWatch = class
private
FWatchOptions : TWatchOptions;
FWatchActions : TWatchActions;
FWatchSubTree : Boolean;
FWatchThread : TThread;
FBufferSize : Integer;
FWndHandle : HWND;
FPath : string;
FAbortEvent : THandle;
FOnError : TOnError;
FOnChange : TNotifyEvent;
FOnNotify : TFileChangeNotifyEvent;
procedure WatchWndProc(var Msg: TMessage);
procedure SetPath(const Value: string);
procedure SetWatchOptions(const Value: TWatchOptions);
procedure SetWatchActions(const Value: TWatchActions);
procedure SetWatchSubTree(const Value: Boolean);
procedure DeallocateHWnd(Wnd: HWND);
function MakeFilter: Integer;
protected
procedure Change; virtual;
procedure AllocWatchThread;
procedure ReleaseWatchThread;
procedure RestartWatchThread;
procedure Notify(const Action: Integer;
const FileName: string
); virtual;
public
constructor Create;
destructor Destroy; override;
procedure Start;
procedure Stop;
function Running: Boolean;
property WatchSubTree: Boolean read FWatchSubTree write SetWatchSubTree;
property WatchOptions: TWatchOptions read FWatchOptions write SetWatchOptions;
property WatchActions: TWatchActions read FWatchActions write SetWatchActions;
property BufferSize: Integer read FBufferSize write FBufferSize;
property Path: string read FPath write SetPath;
// notification properties. Notify about internal and external changes
property OnNotify: TFileChangeNotifyEvent read FOnNotify write FOnNotify;
property OnChange: TNotifyEvent read FOnChange write FOnChange;
property OnError: TOnError read FOnError write FOnError;
end;
// waits for the file to be ready (it is not in use anymore) or timeout occurs
procedure WaitForFileReady(const FileName: string; const Timeout: Cardinal = cFileWaitTimeout);
// Clipboard
function CutFilesToClipboard(Handle : HWND; Filenames: TStrings): Boolean;
function CopyFilesToClipboard(Handle : HWND; Filenames: TStrings): Boolean;
function PasteFilesFromClipboard(Handle : HWND; ssFilenames: TStrings; out bMoveFiles : Boolean) : Boolean;
function CanPasteFilesFromClipboard(Handle : HWND) : Boolean;
procedure PopupSystemMenu(Handle: HWND; ssFileList: TStrings; x, y: integer);
// Similar to FileCtrl.SelectDirectory
function WindowsSelectDirectory(const Caption: string; var Directory: string;
Parent: TWinControl = nil; bAllowNewFolder : Boolean = True): Boolean;
function WindowsLocalAppDataFolder : string;
function WindowsMyDocumentsFolder : string;
function WindowsMyPicturesFolder : string;
function WindowsMyMusicFolder : string;
function WindowsMyVideosFolder : string;
function WindowsDesktopFolder : string;
function WindowsProgramFilesFolder : String;
function WindowsTempFolder() : String;
procedure WindowsAddToRecentDocs(const Filename: string);
{To allow multiple source files, replace spaces with #0}
function WindowsCopy(Handle : HWnd; sFromFilename, sDestFolder: String; bRenameOnCollision, bShowConfirmation, bShowProgress: boolean; bVerboseErrors : boolean = True): Boolean; overload;
function WindowsMove(Handle : HWnd; sFromFilename, sDestFolder: String; bRenameOnCollision, bShowConfirmation, bShowProgress: boolean; bVerboseErrors : boolean = True): Boolean; overload;
function WindowsErase(Handle : HWnd; sFilename: String; bSendToRecycleBin, bShowConfirmation, bShowProgress: Boolean; bVerboseErrors : boolean = True): Boolean; overload;
function WindowsCopy(Handle : HWnd; ssFiles : TStrings; const sDestFolder : String; bRenameOnCollision, bShowConfirmation, bShowProgress: boolean; bVerboseErrors : boolean = True): Boolean; overload;
function WindowsMove(Handle : HWnd; ssFiles : TStrings; const sDestFolder : String; bRenameOnCollision, bShowConfirmation, bShowProgress: boolean; bVerboseErrors : boolean = True): Boolean; overload;
function WindowsErase(Handle : HWnd; ssFiles : TStrings; bSendToRecycleBin, bShowConfirmation, bShowProgress: Boolean; bVerboseErrors : boolean = True): Boolean; overload;
// sNewName must be a name only without a file path
function WindowsRename(Handle : HWnd; const sFilename, sNewName: String; bRenameOnCollision, bShowConfirmation : Boolean; bVerboseErrors : boolean = True; bCheckForOverwrite : Boolean = True): Boolean;
procedure WindowsLaunchFile(Handle: THandle; const sFilename: string);
// CSIDL_... definitions in ShlObj
// return a path such as CSIDL_LOCAL_APPDATA or CSIDL_BITBUCKET
// fpMypictures = CSIDL_MYPICTURES
// fpMyMusic = CSIDL_COMMON_MUSIC
// Non-local app data CSIDL_APPDATA
function GetWindowsSpecialFolder(const iCSIDL: Integer): string;
{$IFNDEF Delphi6orNewer}
function DirectoryExists(const Directory: string): Boolean;
{$ENDIF}
{$IFDEF IEINCLUDEMULTIVIEW}
procedure ShowWindowsPrintWizard(ImageEnMView: TImageEnMView; bAllImages: Boolean); overload;
procedure ShowWindowsPrintWizard(ssFiles: TStrings); overload;
{$ENDIF}
implementation
uses
{$IFNDEF Delphi6orNewer} FileCtrl, {$ENDIF}
Sysutils, ShlObj, shellapi, Dialogs, consts, hyieutils
{$IfDef UNICODE}, AnsiStrings {$EndIf}
{$ifdef IENEWVARIANTS}
, variants
{$endif};
{$IFNDEF Delphi2007orNewer}
const
CSIDL_PROGRAM_FILES = $0026; { C:\Program Files }
CSIDL_LOCAL_APPDATA = $001c; { <user name>\Local Settings\Application Data (non roaming) }
CSIDL_MYPICTURES = $0027; { C:\Program Files\My Pictures }
CSIDL_MYDOCUMENTS = $000c; { logical "My Documents" desktop icon }
CSIDL_MYMUSIC = $000d; { "My Music" folder }
CSIDL_MYVIDEO = $000e; { "My Video" folder }
BIF_NONEWFOLDERBUTTON = $00000200;
BIF_NEWDIALOGSTYLE = $0040;
BIF_SHAREABLE = $8000;
function DirectoryExists(const Directory: string): Boolean;
var
Code: Integer;
begin
Code := GetFileAttributes(PChar(Directory));
Result := (Code <> -1) and (FILE_ATTRIBUTE_DIRECTORY and Code <> 0);
end;
{$ENDIF}
type
// Required by _PopupSystemMenu
IShellCommandVerb = interface
['{7D2A7245-2376-4D33-8008-A130935A2E8B}']
procedure ExecuteCommand(Verb: string; var Handled: boolean);
procedure CommandCompleted(Verb: string; Succeeded: boolean);
end;
PArrayOfPItemIDList = ^TArrayOfPItemIDList;
TArrayOfPItemIDList = array[0..0] of PItemIDList;
{!!
<FS>WindowsLaunchFile
<FM>Declaration<FC>
procedure WindowsLaunchFile(Handle: THandle; const sFilename: string);
<FM>Description<FN>
Calls ShellExecute to launch the specified file in the default application. Can also be used to launch a web page.
<FM>Example<FC>
WindowsLaunchFile(Form1.Handle, IEFolderMView1.SelectedFilename);
WindowsLaunchFile(Form1.Handle, 'http://www.ImageEn.com');
!!}
procedure WindowsLaunchFile(Handle: THandle; const sFilename: string);
var
ret: integer;
begin
ret := ShellExecute(Handle, nil, PChar(sFileName), nil, nil, SW_SHOWNORMAL);
if ret <= 32 then
raise EIEException.create(SysErrorMessage(GetLastError));
end;
{!!
<FS>WindowsProgramFilesFolder
<FM>Declaration<FC>
function WindowsProgramFilesFolder : String;
<FM>Description<FN>
Returns the full path to "Program Files" (using <L http://msdn.microsoft.com/en-us/library/windows/desktop/bb762494%28v=vs.85%29.aspx>CSIDL_PROGRAM_FILES</L>)
<FM>Example<FC>
IEFolderMView1.Folder := WindowsProgramFilesFolder;
!!}
function WindowsProgramFilesFolder : String;
begin
Result := GetWindowsSpecialFolder(CSIDL_PROGRAM_FILES);
end;
function WindowsTempFolder() : String;
var
tempPath: array[ 0..MAX_PATH ] of Char;
begin
GetTempPath( 250, tempPath );
Result := IncludeTrailingBackslash( string( temppath ));
end;
{!!
<FS>GetWindowsSpecialFolder
<FM>Declaration<FC>
function GetWindowsSpecialFolder(const iCSIDL: Integer): string;
<FM>Description<FN>
Calls <L http://msdn.microsoft.com/en-us/library/windows/desktop/bb762204%28v=vs.85%29.aspx>SHGetSpecialFolderPath</L> to return a Windows special folder.
<FM>Example<FC>
// Display the contents of the Recycle Bin
IEFolderMView1.Folder := GetWindowsSpecialFolder(CSIDL_BITBUCKET);
!!}
// return a path such as CSIDL_LOCAL_APPDATA or CSIDL_BITBUCKET
function GetWindowsSpecialFolder(const iCSIDL: Integer): string;
var
Path: array[0..1023] of Char;
begin
Result := '';
try
if SHGetSpecialFolderPath(0, Path, iCSIDL, False) then
Result := Path;
except
{ ERROR }
end;
end;
{!!
<FS>WindowsAddToRecentDocs
<FM>Declaration<FC>
procedure WindowsAddToRecentDocs(Const Filename: string);
<FM>Description<FN>
Adds a file to Windows' list of recent documents (displayed under the Start menu)
<FM>Example<FC>
WindowsAddToRecentDocs('C:\My File.jpg');
!!}
procedure WindowsAddToRecentDocs(Const Filename: string);
begin
SHAddToRecentDocs(SHARD_PATH, @Filename[1]);
end;
function ShGetKnownFolderPath(const rfid: TGUID; dwFlags: DWord; hToken: THandle; out ppszPath: PWideChar): HResult;
type
TShGetKnownFolderPath = function(const rfid: TGUID; dwFlags: DWord; hToken: THandle; out ppszPath: PWideChar): HResult; stdcall;
var
Shell: HModule;
Fn: TShGetKnownFolderPath;
begin
Shell := LoadLibrary('shell32.dll');
Win32Check(Shell <> 0);
try
@Fn := GetProcAddress(Shell, 'SHGetKnownFolderPath');
Win32Check(Assigned(Fn));
Result := Fn(rfid, dwFlags, hToken, ppszPath);
finally
FreeLibrary(Shell);
end;
end;
function GetKnownFolderPath(const rfid: TGUID; dwFlags: DWord; hToken: THandle): WideString;
var
buffer: PWideChar;
ret: HResult;
begin
ret := ShGetKnownFolderPath(rfid, dwFlags, hToken, buffer);
OleCheck(ret);
try
Result := buffer;
finally
CoTaskMemFree(buffer);
end;
end;
function PerformSHFileOperation(Handle : HWnd; iAction : UINT; sFromFilename, sDestFolder: String; bRenameOnCollision, bSendToRecycleBin, bShowConfirmation, bShowProgress, bVerboseErrors : boolean): Boolean;
var
Struct : TSHFileOpStructA;
bDelete: Boolean;
bAborted : Boolean;
begin
bAborted := False;
bDelete := iAction = FO_Delete;
sFromFilename := sFromFilename + #0#0;
if not bDelete then
sDestFolder := sDestFolder + #0#0;
with Struct do
begin
wnd := Handle;
wFunc := iAction;
pFrom := PAnsiChar(AnsiString(sFromFilename));
if bDelete then
pTo := nil
else
pTo := PAnsiChar(AnsiString(sDestFolder));
If (bDelete = False) or bSendToRecycleBin then
fFlags := FOF_ALLOWUNDO or FOF_FILESONLY
else
fFlags := 0 or FOF_FILESONLY;
If bShowConfirmation = false then
fFlags := fFlags or FOF_NOCONFIRMATION;
if bShowProgress = False then
fFlags := fFlags or FOF_SILENT;
If (bDelete = False) and bRenameOnCollision then
fFlags := fFlags or FOF_RENAMEONCOLLISION;
if bVerboseErrors = false then
fFlags := fFlags or FOF_NOERRORUI;
fAnyOperationsAborted := bAborted;
hNameMappings := nil;
lpszProgressTitle := nil;
end;
result := (SHFileOperationA(Struct) = 0) and (not bAborted);
end;
function PerformSHFileOperation2(Handle : HWnd; iAction : UINT; ssFiles : TStrings; const sDestFolder : String; bRenameOnCollision, bSendToRecycleBin, bShowConfirmation, bShowProgress, bVerboseErrors : boolean): Boolean;
var
sFromFilename : String;
I: Integer;
bDelete: Boolean;
begin
Result := False;
bDelete := iAction = FO_Delete;
if (bDelete = False) and (sDestFolder = '') then
exit;
sFromFilename := '';
for I := 0 to ssFiles.Count - 1 do
sFromFilename := sFromFilename + ssFiles[I] + #0;
if sFromFilename = '' then
exit;
// Remove final #0
Delete(sFromFilename, Length(sFromFilename), 1);
Result := PerformSHFileOperation(Handle, iAction, sFromFilename, sDestFolder, bRenameOnCollision, bSendToRecycleBin, bShowConfirmation, bShowProgress, bVerboseErrors);
end;
{!!
<FS>WindowsCopy
<FM>Declaration<FC>
function WindowsCopy(Handle : HWnd; sFromFilename, sDestFolder: String; bRenameOnCollision, bShowConfirmation, bShowProgress: boolean; bVerboseErrors : boolean = True): Boolean;
function WindowsCopy(Handle : HWnd; ssFiles : TStrings; const sDestFolder : String; bRenameOnCollision, bShowConfirmation, bShowProgress: boolean; bVerboseErrors : boolean = True): Boolean; overload;
<FM>Description<FN>
Uses <L http://msdn.microsoft.com/en-us/library/windows/desktop/bb762164%28v=vs.85%29.aspx>PerformSHFileOperation</L> to copy files to a folder.
<TABLE>
<R> <H>Parameter</H> <H>Description</H> </R>
<R> <C>sFromFilename/ssFiles</C> <C>The file(s) to copy. If using sFromFilename the multiple files can be delimited using #0</C> </R>
<R> <C>sDestFolder</C> <C>The folder to copy files to</C> </R>
<R> <C>bRenameOnCollision</C> <C>Give the file being operated on a new name if a file with the target name already exists at the destination (pertains to <L http://msdn.microsoft.com/en-us/library/windows/desktop/bb759795%28v=vs.85%29.aspx>FOF_RENAMEONCOLLISION</L></C> </R>
<R> <C>bShowConfirmation</C> <C>If not specified then will automatically respond with "Yes to All" for any dialog box that is displayed (undefines <L http://msdn.microsoft.com/en-us/library/windows/desktop/bb759795%28v=vs.85%29.aspx>FOF_NOCONFIRMATION</L></C> </R>
<R> <C>bShowProgress</C> <C>Displays a progress dialog box (undefines <L http://msdn.microsoft.com/en-us/library/windows/desktop/bb759795%28v=vs.85%29.aspx>FOF_SILENT</L></C> </R>
<R> <C>bVerboseErrors</C> <C>Displays a dialog to the user if an error occurs (undefines <L http://msdn.microsoft.com/en-us/library/windows/desktop/bb759795%28v=vs.85%29.aspx>FOF_NOERRORUI</L></C> </R>
</TABLE>
Result is true unless the operation fails or is aborted.
<FM>Example<FC>
WindowsCopy(Form1.Handle, 'C:\My Image.jpg', 'C:\My Files', True, True, True);
!!}
function WindowsCopy(Handle : HWnd; sFromFilename, sDestFolder: String; bRenameOnCollision, bShowConfirmation, bShowProgress: boolean; bVerboseErrors : boolean = True): Boolean;
begin
Result := PerformSHFileOperation(Handle, FO_Copy, sFromFilename, sDestFolder, bRenameOnCollision, True, bShowConfirmation, bShowProgress, bVerboseErrors);
end;
function WindowsCopy(Handle : HWnd; ssFiles : TStrings; const sDestFolder : String; bRenameOnCollision, bShowConfirmation, bShowProgress: boolean; bVerboseErrors : boolean = True): Boolean; overload;
begin
Result := PerformSHFileOperation2(Handle, FO_Copy, ssFiles, sDestFolder, bRenameOnCollision, True, bShowConfirmation, bShowProgress, bVerboseErrors);
end;
{!!
<FS>WindowsMove
<FM>Declaration<FC>
function WindowsMove(Handle : HWnd; sFromFilename, sDestFolder: String; bRenameOnCollision, bShowConfirmation, bShowProgress: boolean; bVerboseErrors : boolean = True): Boolean;
function WindowsMove(Handle : HWnd; ssFiles : TStrings; const sDestFolder : String; bRenameOnCollision, bShowConfirmation, bShowProgress: boolean; bVerboseErrors : boolean = True): Boolean; overload;
<FM>Description<FN>
Uses <L http://msdn.microsoft.com/en-us/library/windows/desktop/bb762164%28v=vs.85%29.aspx>PerformSHFileOperation</L> to move files to a folder.
<TABLE>
<R> <H>Parameter</H> <H>Description</H> </R>
<R> <C>sFromFilename/ssFiles</C> <C>The file(s) to move. If using sFromFilename the multiple files can be delimited using #0</C> </R>
<R> <C>sDestFolder</C> <C>The folder to move files to</C> </R>
<R> <C>bRenameOnCollision</C> <C>Give the file being operated on a new name if a file with the target name already exists at the destination (pertains to <L http://msdn.microsoft.com/en-us/library/windows/desktop/bb759795%28v=vs.85%29.aspx>FOF_RENAMEONCOLLISION</L></C> </R>
<R> <C>bShowConfirmation</C> <C>If not specified then will automatically respond with "Yes to All" for any dialog box that is displayed (undefines <L http://msdn.microsoft.com/en-us/library/windows/desktop/bb759795%28v=vs.85%29.aspx>FOF_NOCONFIRMATION</L></C> </R>
<R> <C>bShowProgress</C> <C>Displays a progress dialog box (undefines <L http://msdn.microsoft.com/en-us/library/windows/desktop/bb759795%28v=vs.85%29.aspx>FOF_SILENT</L></C> </R>
<R> <C>bVerboseErrors</C> <C>Displays a dialog to the user if an error occurs (undefines <L http://msdn.microsoft.com/en-us/library/windows/desktop/bb759795%28v=vs.85%29.aspx>FOF_NOERRORUI</L></C> </R>
</TABLE>
Result is true unless the operation fails or is aborted.
<FM>Example<FC>
WindowsMove(Form1.Handle, 'C:\My Image.jpg', 'C:\My Files', True, True, True);
!!}
function WindowsMove(Handle : HWnd; sFromFilename, sDestFolder: String; bRenameOnCollision, bShowConfirmation, bShowProgress: boolean; bVerboseErrors : boolean = True): Boolean;
begin
Result := PerformSHFileOperation(Handle, FO_Move, sFromFilename, sDestFolder, bRenameOnCollision, True, bShowConfirmation, bShowProgress, bVerboseErrors);
end;
function WindowsMove(Handle : HWnd; ssFiles : TStrings; const sDestFolder : String; bRenameOnCollision, bShowConfirmation, bShowProgress: boolean; bVerboseErrors : boolean = True): Boolean; overload;
begin
Result := PerformSHFileOperation2(Handle, FO_Move, ssFiles, sDestFolder, bRenameOnCollision, True, bShowConfirmation, bShowProgress, bVerboseErrors);
end;
{!!
<FS>WindowsErase
<FM>Declaration<FC>
function WindowsErase(Handle : HWnd; sFilename: String; bSendToRecycleBin, bShowConfirmation, bShowProgress: Boolean; bVerboseErrors : boolean = True): Boolean;
function WindowsErase(Handle : HWnd; ssFiles : TStrings; bSendToRecycleBin, bShowConfirmation, bShowProgress: Boolean; bVerboseErrors : boolean = True): Boolean; overload;
<FM>Description<FN>
Uses <L http://msdn.microsoft.com/en-us/library/windows/desktop/bb762164%28v=vs.85%29.aspx>PerformSHFileOperation</L> to delete files from a folder.
<TABLE>
<R> <H>Parameter</H> <H>Description</H> </R>
<R> <C>sFilename/ssFiles</C> <C>The file(s) to delete. If using sFromFilename the multiple files can be delimited using #0</C> </R>
<R> <C>bSendToRecycleBin</C> <C>Moves the file to the Recycle Bin rather than permanently deleting it (pertains to <L http://msdn.microsoft.com/en-us/library/windows/desktop/bb759795%28v=vs.85%29.aspx>FOF_ALLOWUNDO</L></C> </R>
<R> <C>bShowConfirmation</C> <C>If not specified then will automatically respond with "Yes to All" for any dialog box that is displayed (undefines <L http://msdn.microsoft.com/en-us/library/windows/desktop/bb759795%28v=vs.85%29.aspx>FOF_NOCONFIRMATION</L></C> </R>
<R> <C>bShowProgress</C> <C>Displays a progress dialog box (undefines <L http://msdn.microsoft.com/en-us/library/windows/desktop/bb759795%28v=vs.85%29.aspx>FOF_SILENT</L></C> </R>
<R> <C>bVerboseErrors</C> <C>Displays a dialog to the user if an error occurs (undefines <L http://msdn.microsoft.com/en-us/library/windows/desktop/bb759795%28v=vs.85%29.aspx>FOF_NOERRORUI</L></C> </R>
</TABLE>
Result is true unless the operation fails or is aborted.
<FM>Example<FC>
WindowsErase(Form1.Handle, 'C:\My Image.jpg', True, True, True);
!!}
function WindowsErase(Handle : HWnd; sFilename: String; bSendToRecycleBin, bShowConfirmation, bShowProgress: Boolean; bVerboseErrors : boolean = True): Boolean;
begin
Result := PerformSHFileOperation(Handle, FO_Delete, sFilename, '', False, bSendToRecycleBin, bShowConfirmation, bShowProgress, bVerboseErrors);
end;
function WindowsErase(Handle : HWnd; ssFiles : TStrings; bSendToRecycleBin, bShowConfirmation, bShowProgress: Boolean; bVerboseErrors : boolean = True): Boolean; overload;
begin
Result := PerformSHFileOperation2(Handle, FO_Delete, ssFiles, '', False, bSendToRecycleBin, bShowConfirmation, bShowProgress, bVerboseErrors);
end;
{!!
<FS>WindowsRename
<FM>Declaration<FC>
function WindowsRename(Handle : HWnd; const sFilename, sNewName: String; bRenameOnCollision, bShowConfirmation : Boolean; bVerboseErrors : boolean = True; bCheckForOverwrite : Boolean = True): Boolean; overload;
<FM>Description<FN>
Uses <L http://msdn.microsoft.com/en-us/library/windows/desktop/bb762164%28v=vs.85%29.aspx>PerformSHFileOperation</L> to delete files from a folder.
<TABLE>
<R> <H>Parameter</H> <H>Description</H> </R>
<R> <C>sFilename/ssFiles</C> <C>The file(s) to rename (only one can be specified</C> </R>
<R> <C>sNewName</C> <C>The new filename for the file (do not include path)</C> </R>
<R> <C>bRenameOnCollision</C> <C>Give the file being operated on a new name if a file with the target name already exists at the destination (pertains to <L http://msdn.microsoft.com/en-us/library/windows/desktop/bb759795%28v=vs.85%29.aspx>FOF_RENAMEONCOLLISION</L></C> </R>
<R> <C>bShowConfirmation</C> <C>If not specified then will automatically respond with "Yes to All" for any dialog box that is displayed (undefines <L http://msdn.microsoft.com/en-us/library/windows/desktop/bb759795%28v=vs.85%29.aspx>FOF_NOCONFIRMATION</L></C> </R>
<R> <C>bVerboseErrors</C> <C>Displays a dialog to the user if an error occurs (undefines <L http://msdn.microsoft.com/en-us/library/windows/desktop/bb759795%28v=vs.85%29.aspx>FOF_NOERRORUI</L></C> </R>
</TABLE>
Result is true unless the operation fails or is aborted.
<FM>Example<FC>
WindowsRename(Form1.Handle, 'C:\My Image.jpg', 'My New Name.jpg', True, True);
!!}
// sNewName must be a name only without a file path
function WindowsRename(Handle : HWnd; const sFilename, sNewName: String; bRenameOnCollision, bShowConfirmation : Boolean; bVerboseErrors : boolean = True; bCheckForOverwrite : Boolean = True): Boolean; overload;
var
sNewFilename: string;
begin
Result := False;
if (sFilename = '') or (sNewName = '') then
exit;
sNewFilename := IEAddBackSlash(ExtractFilepath(sFilename)) + sNewName;
if bCheckForOverwrite and FileExists(sNewFilename) then
begin
Result := False;
if bVerboseErrors then
MessageDlg(format('A file already exists of the name, "%s"', [sNewName]), mtInformation, [mbOK], 0);
exit;
end;
Result := PerformSHFileOperation(Handle, FO_Rename, sFilename, sNewFilename, bRenameOnCollision, True, bShowConfirmation, False, bVerboseErrors);
end;
{!!
<FS>WindowsLocalAppDataFolder
<FM>Declaration<FC>
function WindowsLocalAppDataFolder : string;
<FM>Description<FN>
Returns the full path to the "Local Apps" folder (using <L http://msdn.microsoft.com/en-us/library/windows/desktop/bb762494%28v=vs.85%29.aspx>CSIDL_LOCAL_APPDATA</L>)
<FM>Example<FC>
IEFolderMView1.Folder := WindowsLocalAppDataFolder;
!!}
function WindowsLocalAppDataFolder : string;
begin
Result := IEAddBackSlash(GetWindowsSpecialFolder(CSIDL_LOCAL_APPDATA));
end;
{!!
<FS>WindowsMyDocumentsFolder
<FM>Declaration<FC>
function WindowsMyDocumentsFolder: string;
<FM>Description<FN>
Returns the full path to the "My Documents" folder (using <L http://msdn.microsoft.com/en-us/library/windows/desktop/bb762494%28v=vs.85%29.aspx>CSIDL_PERSONAL</L>)
<FM>Example<FC>
IEFolderMView1.Folder := WindowsMyDocumentsFolder;
!!}
function WindowsMyDocumentsFolder: string;
begin
Result := IEAddBackSlash(GetWindowsSpecialFolder(CSIDL_PERSONAL));
end;
{!!
<FS>WindowsMyPicturesFolder
<FM>Declaration<FC>
function WindowsMyPicturesFolder: string;
<FM>Description<FN>
Returns the full path to the "My Pictures" folder (using <L http://msdn.microsoft.com/en-us/library/windows/desktop/bb762494%28v=vs.85%29.aspx>CSIDL_MYPICTURES</L>)
<FM>Example<FC>
IEFolderMView1.Folder := WindowsMyPicturesFolder;
!!}
function WindowsMyPicturesFolder: string;
begin
Result := IEAddBackSlash(GetWindowsSpecialFolder(CSIDL_MYPICTURES));
end;
{!!
<FS>WindowsMyMusicFolder
<FM>Declaration<FC>
function WindowsMyMusicFolder: string;
<FM>Description<FN>
Returns the full path to the "My Music" folder (using <L http://msdn.microsoft.com/en-us/library/windows/desktop/bb762494%28v=vs.85%29.aspx>CSIDL_MYMUSIC</L>)
<FM>Example<FC>
IEFolderMView1.Folder := WindowsMyMusicFolder;
!!}
function WindowsMyMusicFolder: string;
begin
Result := IEAddBackSlash(GetWindowsSpecialFolder(CSIDL_MYMUSIC));
end;
{!!
<FS>WindowsMyVideosFolder
<FM>Declaration<FC>
function WindowsMyVideosFolder: string;
<FM>Description<FN>
Returns the full path to the "My Videos" folder (using <L http://msdn.microsoft.com/en-us/library/windows/desktop/bb762494%28v=vs.85%29.aspx>CSIDL_MYVIDEO</L>)
<FM>Example<FC>
IEFolderMView1.Folder := WindowsMyVideosFolder;
!!}
function WindowsMyVideosFolder: string;
begin
Result := IEAddBackSlash(GetWindowsSpecialFolder(CSIDL_MYVIDEO));
end;
{!!
<FS>WindowsDesktopFolder
<FM>Declaration<FC>
function WindowsDesktopFolder: string;
<FM>Description<FN>
Returns the full path to the "Desktop" (using <L http://msdn.microsoft.com/en-us/library/windows/desktop/bb762494%28v=vs.85%29.aspx>CSIDL_DESKTOP</L>)
<FM>Example<FC>
IEFolderMView1.Folder := WindowsDesktopFolder;
!!}
function WindowsDesktopFolder: string;
begin
Result := IEAddBackSlash(GetWindowsSpecialFolder(CSIDL_DESKTOP));
end;
{$IFDEF Delphi6orNewer}
type
TSelectDirCallback = class(TObject)
private
FDirectory: string;
protected
function SelectDirCB(Wnd: HWND; uMsg: UINT; lParam, lpData: LPARAM): Integer;
public
constructor Create(const ADirectory: string);
end;
function SelectDirCB(Wnd: HWND; uMsg: UINT; lParam, lpData: LPARAM): Integer stdcall;
begin
Result := TSelectDirCallback(lpData).SelectDirCB(Wnd, uMsg, lParam, lpData);
end;
{$ENDIF}
{!!
<FS>WindowsSelectDirectory
<FM>Declaration<FC>
function WindowsSelectDirectory(const Caption: string; var Directory: string;
Parent: TWinControl = nil; bAllowNewFolder : Boolean = True): Boolean;
<FM>Description<FN>
Displays a dialog to the user which allows the to select a folder.
Note: Similar to FileCtrl.SelectDirectory
<FM>Example<FC>
sFolder := IEFolderMView1.Folder;
WindowsSelectDirectory('Specify Folder', sFolder);
IEFolderMView1.Folder := sFolder;
!!}
{$IFNDEF Delphi6orNewer}
function WindowsSelectDirectory(const Caption: string; var Directory: string;
Parent: TWinControl = nil; bAllowNewFolder : Boolean = True): Boolean;
var
Ops : TSelectDirOpts;
begin
if not DirectoryExists(Directory) then
Directory := '';
if bAllowNewFolder then
Ops := [sdAllowCreate, sdPerformCreate, sdPrompt]
else
Ops := [];
Result := FileCtrl.SelectDirectory(Directory, Ops, 0);
end;
{$ELSE}
function WindowsSelectDirectory(const Caption: string; var Directory: string;
Parent: TWinControl = nil; bAllowNewFolder : Boolean = True): Boolean;
const
Display_Sharable_Resources = True;
Validate_Directory = True;
var
WindowList: Pointer;
BrowseInfo: TBrowseInfo;
Buffer: PChar;
OldErrorMode: Cardinal;
RootItemIDList, ItemIDList: PItemIDList;
ShellMalloc: IMalloc;
IDesktopFolder: IShellFolder;
Eaten, Flags: LongWord;
CoInitResult: HRESULT;
SelectDirCallback: TSelectDirCallback;
Root: WideString;
begin
Result := False;
Root := '';
if not DirectoryExists(Directory) then
Directory := '';
FillChar(BrowseInfo, SizeOf(BrowseInfo), 0);
if (ShGetMalloc(ShellMalloc) = S_OK) and (ShellMalloc <> nil) then
begin
Buffer := ShellMalloc.Alloc(MAX_PATH);
try
RootItemIDList := nil;
if Root <> '' then
begin
SHGetDesktopFolder(IDesktopFolder);
IDesktopFolder.ParseDisplayName(Application.Handle, nil,
POleStr(Root), Eaten, RootItemIDList, Flags);
end;
with BrowseInfo do
begin
if (Parent = nil) or not Parent.HandleAllocated then
hwndOwner := Application.Handle
else
hwndOwner := Parent.Handle;
pidlRoot := RootItemIDList;
pszDisplayName := Buffer;
lpszTitle := PChar(Caption);
ulFlags := BIF_RETURNONLYFSDIRS or BIF_NEWDIALOGSTYLE or BIF_EDITBOX;
if not bAllowNewFolder then
ulFlags := ulFlags or BIF_NONEWFOLDERBUTTON;
if Display_Sharable_Resources then
ulFlags := ulFlags or BIF_SHAREABLE;
if Validate_Directory then
ulFlags := ulFlags or BIF_VALIDATE;
lpfn := SelectDirCB;
end;
SelectDirCallback := TSelectDirCallback.Create(Directory);
try
BrowseInfo.lParam := Integer(SelectDirCallback);
CoInitResult := CoInitializeEx(nil, COINIT_APARTMENTTHREADED);
if CoInitResult = RPC_E_CHANGED_MODE then
BrowseInfo.ulFlags := BrowseInfo.ulFlags and not BIF_NEWDIALOGSTYLE;
try
WindowList := DisableTaskWindows(0);
OldErrorMode := SetErrorMode(SEM_FAILCRITICALERRORS);
try
ItemIDList := ShBrowseForFolder(BrowseInfo);
finally
SetErrorMode(OldErrorMode);
EnableTaskWindows(WindowList);
end;
finally
CoUninitialize;
end;
finally
SelectDirCallback.Free;
end;
Result := ItemIDList <> nil;
if Result then
begin
ShGetPathFromIDList(ItemIDList, Buffer);
ShellMalloc.Free(ItemIDList);
Directory := Buffer;
end;
finally
ShellMalloc.Free(Buffer);
end;
end;
end;
{ TSelectDirCallback }
constructor TSelectDirCallback.Create(const ADirectory: string);
begin
inherited Create;
FDirectory := ADirectory;
end;
function TSelectDirCallback.SelectDirCB(Wnd: HWND; uMsg: UINT; lParam, lpData: LPARAM): Integer;
var
Rect: TRect;
Monitor: TMonitor;
begin
Result := 0;
if uMsg = BFFM_INITIALIZED then
begin
if Assigned(Application.MainForm) then
Monitor := Screen.MonitorFromWindow(Application.MainForm.Handle)
else
Monitor := Screen.MonitorFromWindow(0);
GetWindowRect(Wnd, Rect);
SetWindowPos(Wnd, 0, (Monitor.Width - (Rect.Right - Rect.Left)) div 2,
(Monitor.Height - (Rect.Bottom - Rect.Top)) div 2, 0, 0, SWP_NOSIZE or SWP_NOZORDER);
if FDirectory <> '' then
SendMessage(Wnd, BFFM_SETSELECTION, Integer(True), Windows.LPARAM(PChar(FDirectory)));
end
else
if uMsg = BFFM_VALIDATEFAILED then
begin
MessageDlg(Format(iemsg(IEMsg_XIsNotAValidFolder), [PChar(lParam)]), mtError, [mbOK], 0);
Result := 1;
end;
end;
{$ENDIF}
const
CF_PreferredDropEffect_Str = 'Preferred DropEffect'; // Windows Explorer Clipboard format string for specifying whether a file is moved or copied
{!!
<FS>CutFilesToClipboard
<FM>Declaration<FC>
function CutFilesToClipboard(Handle : HWND; Filenames: TStrings): Boolean;
<FM>Description<FN>
Adds a list of filenames to the clipboard and specifies that they should moved (same as selecting Ctrl+X in Windows Explorer). The filenames can then be pasted into other Windows applications such as Explorer using Ctrl+V. After pasting they will be removed from the source folder.
<FM>Example<FC>
CutFilesToClipboard(Form1.Handle, ssFilenames);
!!}
function CutFilesToClipboard(Handle : HWND; Filenames: TStrings): Boolean;
{$IFNDEF Delphi6orNewer}
type
PCardinal = ^Cardinal;
{$ENDIF}
var
sFilenames: String;
iIndex: Integer;
hBuffer: HGLOBAL;
pBuffer: PDropFiles;
f: UINT;
d: pcardinal;
begin
Result := False;
if (Filenames = nil) and (Filenames.Count = 0) then
Exit;
// Filenames are separated by #0 and end with a double #0#0
sFilenames := '';
for iIndex := 0 to Filenames.Count - 1 do
sFilenames := sFilenames + ExcludeTrailingBackslash(Filenames.Strings[iIndex]) + #0;
sFilenames := sFilenames + #0;
if OpenClipboard(Handle) = False then
Exit;
EmptyClipboard();
hBuffer := GlobalAlloc(GMEM_MOVEABLE or GMEM_ZEROINIT, SizeOf(DROPFILES) + Length(sFilenames));
try
if hBuffer = 0 then
exit;
pBuffer := GlobalLock(hBuffer);
// prepare the "DROPFILES" structure
pBuffer^.pFiles := SizeOf(DROPFILES);
pBuffer := Pointer(NativeInt(pBuffer) + SizeOf(DROPFILES));
CopyMemory(pBuffer, PChar(sFilenames), Length(sFilenames));
GlobalUnlock(hBuffer);
SetClipboardData(CF_HDROP, hBuffer);
// Preferred DropEffect
f := RegisterClipboardFormat(PChar(CF_PreferredDropEffect_Str));
hBuffer := GlobalAlloc(GMEM_SHARE or GMEM_MOVEABLE or GMEM_ZEROINIT, sizeof(dword));
d := pcardinal(GlobalLock(hBuffer));
d^ := DROPEFFECT_MOVE;
SetClipboardData(f, hBuffer);
GlobalUnlock(hBuffer);
CloseClipboard;
Result := True;
except
// free only if handle could not be passed to the clipboard
GlobalFree(hBuffer);
Raise;
end;
end;
{!!
<FS>CopyFilesToClipboard
<FM>Declaration<FC>
function CopyFilesToClipboard(Handle : HWND; Filenames: TStrings): Boolean;
<FM>Description<FN>
Adds a list of filenames to the clipboard (same as selecting Ctrl+C in Windows Explorer). The filenames can then be pasted into other Windows applications such as Explorer using Ctrl+V.
<FM>Example<FC>
CopyFilesToClipboard(Form1.Handle, ssFilenames);
!!}
// Source: http://www.martinstoeckli.ch/delphi/
function CopyFilesToClipboard(Handle : HWND; Filenames: TStrings): Boolean;
var
sFilenames: String;
iIndex: Integer;
hBuffer: HGLOBAL;
pBuffer: PDropFiles;
begin
Result := False;
if (Filenames = nil) and (Filenames.Count = 0) then
Exit;
// Filenames are separated by #0 and end with a double #0#0
sFilenames := '';
for iIndex := 0 to Filenames.Count - 1 do
sFilenames := sFilenames + ExcludeTrailingBackslash(Filenames.Strings[iIndex]) + #0;
sFilenames := sFilenames + #0;
// allocate memory with the size of the "DropFiles" structure plus the
// length of the filename buffer.
hBuffer := GlobalAlloc(GMEM_MOVEABLE or GMEM_ZEROINIT, SizeOf(DROPFILES) + Length(sFilenames));
try
if hBuffer = 0 then
exit;
pBuffer := GlobalLock(hBuffer);
try
// prepare the "DROPFILES" structure
pBuffer^.pFiles := SizeOf(DROPFILES);
// behind the "DROPFILES" structure we place the filenames
pBuffer := Pointer(NativeInt(pBuffer) + SizeOf(DROPFILES));
CopyMemory(pBuffer, PChar(sFilenames), Length(sFilenames));
finally
GlobalUnlock(hBuffer);
end;
// copy buffer to the clipboard
if OpenClipboard(Handle) = False then
raise EIEException.CreateRes(@SCannotOpenClipboard);
try
EmptyClipboard;
SetClipboardData(CF_HDROP, hBuffer);
finally
CloseClipboard;
end;
Result := True;
except
// free only if handle could not be passed to the clipboard
GlobalFree(hBuffer);
Raise;
end;
end;
procedure _FilenamesFromDropHandle(hDropHandle: HDROP; Dest : TStrings);
var
szBuffer: PChar;
iCount, iIndex: Integer;
iLength: Integer;
begin
Dest.Clear;
iCount := DragQueryFile(hDropHandle, $FFFFFFFF, nil, 0);
for iIndex := 0 to iCount - 1 do
begin
iLength := DragQueryFile(hDropHandle, iIndex, nil, 0);
szBuffer := StrAlloc(iLength + 1);
try
DragQueryFile(hDropHandle, iIndex, szBuffer, iLength + 1);
Dest.Add(szBuffer);
finally
StrDispose(szBuffer);
end;
end;
end;
{!!
<FS>PasteFilesFromClipboard
<FM>Declaration<FC>
function PasteFilesFromClipboard(Handle : HWND; ssFilenames: TStrings; out bMoveFiles : Boolean) : Boolean;
<FM>Description<FN>
If there are files om the clipboard that have been copied from Windows Explorer or <A TImageEnFolderMView> then they will be assigned to <FC>ssFilenames<FN>.
<FC>bMoveFiles<FN> will be true if they are marked to be moved (i.e. Ctrl+X was used instead of Ctrl+V).
Result is true if there are files on the clipboard
<FM>Example<FC>
bHaveFiles := PasteFilesFromClipboard(Form1.Handle, ssFilenames, bMoveFiles);
if bHaveFiles then
ShowMessage('No Files to paste')
else
if bMoveFiles then
ShowMessage('Files to Move:' + #13#10 + ssFilenames.Text)
else
ShowMessage('Files to Copy:' + #13#10 + ssFilenames.Text)
!!}
// Source: http://www.martinstoeckli.ch/delphi/
// Can pass nil to ssFilenames to test if there are files on the clipboard
function PasteFilesFromClipboard(Handle : HWND; ssFilenames: TStrings; out bMoveFiles : Boolean) : Boolean;
var
hDropHandle: HDROP;
ClipFormat, hn: Cardinal;
szBuffer: array [0 .. 511] of Char;
FormatID: string;
pMem: Pointer;
iDropEffect : Cardinal;
begin
Result := False;
bMoveFiles := False;
if assigned(ssFilenames) then
ssFilenames.Clear;
if OpenClipboard(Handle) = False then
Exit;
try
// does clipboard contain filenames?
Result := IsClipboardFormatAvailable(CF_HDROP);
if assigned(ssFilenames) and result then
begin
hDropHandle := GetClipboardData(CF_HDROP);
_FilenamesFromDropHandle(hDropHandle, ssFilenames);
end;
ClipFormat := EnumClipboardFormats(0);
while ClipFormat <> 0 do
begin
GetClipboardFormatName(ClipFormat, szBuffer, SizeOf(szBuffer));
FormatID := string(szBuffer);
if SameText(FormatID, CF_PreferredDropEffect_Str) then
begin
hn := GetClipboardData(ClipFormat);
pMem := GlobalLock(hn);
Move(pMem^, iDropEffect, 4);
bMoveFiles := iDropEffect = DROPEFFECT_MOVE;
GlobalUnlock(hn);
Break;
end;
ClipFormat := EnumClipboardFormats(ClipFormat);
end;
finally
CloseClipboard;
end;
end;
{!!
<FS>CanPasteFilesFromClipboard
<FM>Declaration<FC>
function CanPasteFilesFromClipboard(Handle : HWND) : Boolean;
<FM>Description<FN>
Returns True if there are files on the clipboard that have been copied from Windows Explorer or <A TImageEnFolderMView> and can be pasted using <A PasteFilesFromClipboard>.
<FM>Example<FC>
btnPaste.Enabled := CanPasteFilesFromClipboard(Form1.Handle);
!!}
function CanPasteFilesFromClipboard(Handle : HWND) : Boolean;
var
bDummy: Boolean;
begin
try
Result := PasteFilesFromClipboard(Handle, nil, bDummy);
except
Result := False;
end;
end;
{!!
<FS>PopupSystemMenu
<FM>Declaration<FC>
procedure PopupSystemMenu(Handle: HWND; ssFileList: TStrings; x, y: integer);
<FM>Description<FN>
Displays the system menu for the specified files at position x,y. This menu is the same as that displayed when right-clicking a selection of files in Windows Explorer
<FM>Example<FC>
PopupSystemMenu(Form1.Handle, ssSelectedFiles, ClickPos.X, ClickPos.Y);
!!}
// Source: http://blog.issamsoft.com/index.php?q=en/node/65
procedure PopupSystemMenu(Handle: HWND; ssFileList: TStrings; x, y: integer);
var
Root: IShellFolder;
ShellParentFolder: IShellFolder;
chEaten, dwAttributes: ULONG;
FilePIDL, ParentFolderPIDL: PItemIDList;
CM: IContextMenu;
Menu: HMenu;
Command: LongBool;
ICM2: IContextMenu2;
ICI: TCMInvokeCommandInfo;
ICmd: integer;
ZVerb: array[0..255] of AnsiChar;
Verb: string;
Handled: boolean;
SCV: IShellCommandVerb;
HR: HResult;
P: TPoint;
ItemIDListArray: PArrayOfPItemIDList;
idx: Integer;
Begin
if ssFileList.Count = 0 then
Exit;
OleCheck(SHGetDesktopFolder(Root));//Get the Desktop IShellFolder interface
OleCheck(Root.ParseDisplayName(Handle, nil,
PWideChar(WideString(ExtractFilePath(ssFileList[0]))),
chEaten, ParentFolderPIDL, dwAttributes)); // Get the PItemIDList of the parent folder
OleCheck(Root.BindToObject(ParentFolderPIDL, nil, IShellFolder, ShellParentFolder)); // Get the IShellFolder Interface of the Parent Folder
//allocate memory for the PItemIDList array
ItemIDListArray := AllocMem(SizeOf(PItemIDList) * ssFileList.Count);
try
for idx := 0 to ssFileList.Count - 1 do
Begin
// Get the relative PItemIDList of each file in the list
OleCheck(ShellParentFolder.ParseDisplayName(Handle, nil,
PWideChar(WideString(ExtractFileName(ssFileList[idx]))),
chEaten, FilePIDL, dwAttributes));
ItemIDListArray^[idx] := FilePIDL;
End;
// get the IContextMenu Interace for the file array
ShellParentFolder.GetUIObjectOf(Handle, ssFileList.Count, ItemIDListArray^[0], IID_IContextMenu, nil, CM);
finally
FreeMem(ItemIDListArray);
end;
if CM = nil then
Exit;
P.X := X;
P.Y := Y;
Windows.ClientToScreen(Handle, P);
Menu := CreatePopupMenu;
try
CM.QueryContextMenu(Menu, 0, 1, $7FFF, CMF_EXPLORE or CMF_CANRENAME);
CM.QueryInterface(IID_IContextMenu2, ICM2); //To handle submenus.
try
Command := TrackPopupMenu(Menu, TPM_LEFTALIGN or TPM_LEFTBUTTON or TPM_RIGHTBUTTON or TPM_RETURNCMD, p.X, p.Y, 0, Handle, nil);
finally
ICM2 := nil;
end;
if Command then
begin
ICmd := LongInt(Command) - 1;
HR := CM.GetCommandString(ICmd, GCS_VERBA, nil, ZVerb, SizeOf(ZVerb));
Verb := string( {$IfDef DelphiXE4orNewer}AnsiStrings.{$EndIf}StrPas(ZVerb) ); // Verb := String(PAnsiString(@ZVerb[0])); <-- v5.0.6. Fails in 64bit
Handled := False;
if Supports(nil, IShellCommandVerb, SCV) then
begin
HR := 0;
SCV.ExecuteCommand(Verb, Handled);
end;
if not Handled then
begin
FillChar(ICI, SizeOf(ICI), #0);
with ICI do
begin
cbSize := SizeOf(ICI);
hWND := 0;
lpVerb := MakeIntResourceA(ICmd);
nShow := SW_SHOWNORMAL;
end;
HR := CM.InvokeCommand(ICI);
end;
if Assigned(SCV) then
SCV.CommandCompleted(Verb, HR = S_OK);
end;
finally
DestroyMenu(Menu)
end;
End;
{$IFDEF IEINCLUDEMULTIVIEW}
{!!
<FS>ShowWindowsPrintWizard
<FM>Declaration<FC>
procedure ShowWindowsPrintWizard(ImageEnMView: TImageEnMView; bAllImages: Boolean); overload;
procedure ShowWindowsPrintWizard(ssFiles: TStrings); overload;
<FM>Description<FN>
Display the Windows Print Wizard with the images of a <A TImageEnMView> or a file list.
<FM>Example<FC>
ShowWindowsPrintWizard( ImageEnMView1, True );
!!}
procedure ShowWindowsPrintWizard(ImageEnMView: TImageEnMView; bAllImages: Boolean);
// Bill Miller: http://www.imageen.com/ieforum/topic.asp?TOPIC_ID=2129
var
i: integer;
ssFiles: TStringList;
begin
ssFiles := TStringList.create;
try
if bAllImages then
begin
for i := 0 to ImageEnMView.ImageCount - 1 do
ssFiles.Add( ImageEnMView.MIO.Params[ i ].FileName );
end
else
begin
for i := 0 to ImageEnMView.MultiSelectedImagesCount - 1 do
ssFiles.Add( ImageEnMView.MIO.Params[ ImageEnMView.MultiSelectedImages[ i ] ].FileName );
end;
ShowWindowsPrintWizard( ssFiles );
finally
ssFiles.Free;
end;
end;
procedure ShowWindowsPrintWizard(ssFiles: TStrings);
// Bill Miller: http://www.imageen.com/ieforum/topic.asp?TOPIC_ID=2129
var
i: integer;
vFiles: OleVariant;
vCommDlg: OleVariant;
begin
Screen.Cursor := crHourGlass;
try
vCommDlg := CreateOleObject( 'WIA.CommonDialog' );
vFiles := CreateOleObject( 'WIA.Vector' );
for i := 0 to ssFiles.Count - 1 do
vFiles.Add( ssFiles[ i ] );
vCommDlg.ShowPhotoPrintingWizard( vFiles );
vFiles := Unassigned;
vCommDlg := Unassigned;
finally
Screen.Cursor := crDefault;
end;
end;
{$ENDIF}
{ TIEFileDragDrop }
constructor TIEFileDragDrop.Create(Control: TWinControl; OnFileDrop : TIEFileDropEvent);
begin
inherited Create;
fDroppingActive := False;
fControl := Control;
fOnFileDrop := OnFileDrop;
fDropActions := [iedaCopy, iedaMove];
fControlHandle := 0;
end;
destructor TIEFileDragDrop.Destroy;
begin
if fControlHandle <> 0 then
RevokeDragDrop(fControlHandle);
fControlHandle := 0;
inherited;
end;
function TIEFileDragDrop.GetDragEffect(KeyState : Integer) : Integer;
var
bIsShiftKeyPressed : Boolean;
begin
if fDropActions = [iedaCopy, iedaMove] then
begin
bIsShiftKeyPressed := (KeyState and MK_SHIFT = MK_SHIFT);
if bIsShiftKeyPressed then
Result := DROPEFFECT_MOVE
else
Result := DROPEFFECT_COPY;
end
else
if fDropActions = [iedaCopy] then
Result := DROPEFFECT_COPY
else
if fDropActions = [iedaMove] then
Result := DROPEFFECT_MOVE
else
Result := DROPEFFECT_NONE;
end;
function TIEFileDragDrop.DragEnter(const dataObj: IDataObject; grfKeyState: Integer; pt: TPoint; var dwEffect: Integer): HResult;
begin
dwEffect := GetDragEffect(grfKeyState);
result := S_OK;
end;
function TIEFileDragDrop.DragLeave: HResult;
begin
Result := S_OK;
end;
function TIEFileDragDrop.DragOver(grfKeyState: Integer; pt: TPoint; var dwEffect: Integer): HResult;
begin
dwEffect := GetDragEffect(grfKeyState);
result := S_OK;
end;
function TIEFileDragDrop.Drop(const dataObj: IDataObject; grfKeyState: Integer; pt: TPoint; var dwEffect: Integer): HResult;
var
ssFilenames: TStringList;
begin
Result := S_OK;
Try
ssFilenames := TStringList.create;
try
dwEffect := GetDragEffect(grfKeyState);
GetFilenames(dataObj, ssFilenames);
fOnFileDrop(Self, ssFilenames, dwEffect);
finally
ssFilenames.free;
end;
Except
Application.HandleException(Self);
End;
end;
procedure TIEFileDragDrop.GetFileNames(const dataObj: IDataObject; Dest: TStrings);
var
formatetcIn: TFormatEtc;
medium: TStgMedium;
hDropHandle: HDROP;
begin
Dest.Clear;
formatetcIn.cfFormat := CF_HDROP;
formatetcIn.ptd := nil;
formatetcIn.dwAspect := DVASPECT_CONTENT;
formatetcIn.lindex := -1;
formatetcIn.tymed := TYMED_HGLOBAL;
if dataObj.GetData(formatetcIn, medium)=S_OK then
begin
(* This cast needed because HDROP is incorrectly declared as Longint in ShellAPI.pas. It should be declared as THandle
which is an unsigned integer. Without this fix the routine fails in top-down memory allocation scenarios. *)
hDropHandle := HDROP(medium.hGlobal);
_FilenamesFromDropHandle(hDropHandle, Dest);
end;
end;
function TIEFileDragDrop.GiveFeedback(dwEffect: Integer): HResult;
begin
Result := DRAGDROP_S_USEDEFAULTCURSORS;
end;
function TIEFileDragDrop.QueryContinueDrag(fEscapePressed: BOOL; grfKeyState: Integer): HResult;
begin
if fEscapePressed or ((MK_LBUTTON or MK_RBUTTON) = (grfKeyState and (MK_LBUTTON or MK_RBUTTON))) then
Result := DRAGDROP_S_CANCEL
else
if grfKeyState and MK_LBUTTON = 0 then
Result := DRAGDROP_S_DROP
else
Result := S_OK;
end;
procedure TIEFileDragDrop.SetDroppingActive(const Value: Boolean);
begin
if fDroppingActive <> Value then
begin
fDroppingActive := Value;
if fDroppingActive and (fControlHandle = 0) then
begin
fControlHandle := fControl.Handle;
RegisterDragDrop(fControlHandle, Self);
end;
end;
end;
function TIEFileDragDrop.GetDataObject(ssFiles: TStrings): IDataObject;
var
Malloc: IMalloc;
Root: IShellFolder;
p: PArrayOfPItemIDList;
chEaten, dwAttributes: ULONG;
i, iFileCount: Integer;
begin
Result := nil;
iFileCount := ssFiles.Count;
if iFileCount = 0 then
Exit;
OleCheck(SHGetMalloc(Malloc));
OleCheck(SHGetDesktopFolder(Root));
p := AllocMem(SizeOf(PItemIDList) * iFileCount);
try
for i := 0 to iFileCount - 1 do
try
OleCheck(Root.ParseDisplayName(GetActiveWindow, nil, PWideChar(WideString(ssFiles[i])), chEaten, p^[i], dwAttributes));
except
// ERROR
end;
OleCheck(Root.GetUIObjectOf(GetActiveWindow, iFileCount, p^[0], IDataObject, nil, Pointer(Result)));
finally
for i := 0 to iFileCount - 1 do
begin
if p^[i] <> nil then
Malloc.Free(p^[i]);
end;
FreeMem(p);
end;
end;
procedure TIEFileDragDrop.InitiateDragging(ssFilenames : TStrings; DragActions: TIEFileDragDropActions);
var
DataObject: IDataObject;
dwEffect: Integer;
dwOKEffects: Longint;
begin
DataObject := GetDataObject(ssFilenames);
if DataObject = nil then
exit;
dwEffect := DROPEFFECT_NONE;
if DragActions = [iedaCopy] then
dwOKEffects := DROPEFFECT_COPY
else
if DragActions = [iedaMove] then
dwOKEffects := DROPEFFECT_MOVE
else
dwOKEffects := DROPEFFECT_COPY or DROPEFFECT_MOVE;
DoDragDrop(DataObject, Self, dwOKEffects, dwEffect);
end;
{ TIEFolderWatch }
const
FILE_NOTIFY_CHANGE_FILE_NAME = $00000001;
FILE_NOTIFY_CHANGE_DIR_NAME = $00000002;
FILE_NOTIFY_CHANGE_ATTRIBUTES = $00000004;
FILE_NOTIFY_CHANGE_SIZE = $00000008;
FILE_NOTIFY_CHANGE_LAST_WRITE = $00000010;
FILE_NOTIFY_CHANGE_LAST_ACCESS = $00000020;
FILE_NOTIFY_CHANGE_CREATION = $00000040;
FILE_NOTIFY_CHANGE_SECURITY = $00000100;
type
PFILE_NOTIFY_INFORMATION = ^TFILE_NOTIFY_INFORMATION;
TFILE_NOTIFY_INFORMATION = record
NextEntryOffset : Cardinal;
Action : Cardinal;
FileNameLength : Cardinal;
FileName : array[0..MAX_PATH - 1] of WideChar;
end;
const
WM_FOLDERWATCH_ERROR = WM_USER + 137;
WM_FOLDERWATCH_NOTIFY = WM_USER + 138;
FILE_LIST_DIRECTORY = $0001;
const
// error messages
cErrorInWatchThread = 'Error "%s" in watch thread. Error code: %d';
cErrorCreateWatchError = 'Error trying to create file handle for "%s". Error code: %d';
type
TIEFolderWatchThread = class(TThread)
private
FWatchSubTree : Boolean;
FAbortEvent : THandle;
FChangeEvent : THandle;
FBufferSize : Integer;
FWndHandle : HWND;
FDirHandle : THandle;
FPath : string;
FIOResult : Pointer;
FFilter : Integer;
procedure SignalError(const ErrorMessage: string; ErrorCode: Cardinal = 0);
protected
procedure Execute; override;
public
constructor Create(const Path: string;
const WndHandle: HWND;
const BufferSize: Integer;
const AbortEvent: THandle;
const TypeFilter: Cardinal;
const aWatchSubTree: Boolean);
destructor Destroy; override;
end;
function _MilliSecondsBetween(const ANow, AThen: TDateTime): Int64;
begin
if ANow < AThen then
Result := Trunc(MSecsPerDay * (AThen - ANow))
else
Result := Trunc(MSecsPerDay * (ANow - AThen));
end;
procedure WaitForFileReady(const FileName: string; const Timeout: Cardinal);
var
hFile: THandle;
StartTime: TDateTime;
begin
StartTime := Now;
// wait to close
while (_MilliSecondsBetween(Now, StartTime) < Timeout) or (Timeout = 0) do
begin
hFile := CreateFile(PChar(FileName), GENERIC_READ, 0, nil, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
if hFile <> INVALID_HANDLE_VALUE then
begin
CloseHandle(hFile);
Break;
end;
// wait for file
Sleep(50);
end;
end;
procedure TIEFolderWatchThread.Execute;
var
NotifyData: PFILE_NOTIFY_INFORMATION;
Events: array [0..1] of THandle;
ErrorMessage: string;
WaitResult: DWORD;
NextEntry: Cardinal;
FileName: PWideChar;
Overlap: TOverlapped;
ResSize: Cardinal;
begin
FillChar(Overlap, SizeOf(TOverlapped), 0);
Overlap.hEvent := FChangeEvent;
// set the array of events
Events[0] := FChangeEvent;
Events[1] := FAbortEvent;
while not Terminated do
try
if ReadDirectoryChangesW(FDirHandle, FIOResult, FBufferSize, FWatchSubtree, FFilter, @ResSize, @Overlap, nil) then
begin
WaitResult := WaitForMultipleObjects(Length(Events), @Events, FALSE, INFINITE);
// check if we have terminated the thread
if WaitResult <> WAIT_OBJECT_0 then
begin
Terminate;
Exit;
end;
if WaitResult = WAIT_OBJECT_0 then
begin
if GetOverlappedResult(FDirHandle, Overlap, ResSize, False) then
begin
NotifyData := FIOResult;
// check overflow
if ResSize = 0 then
begin
ErrorMessage := SysErrorMessage(ERROR_NOTIFY_ENUM_DIR);
SignalError(ErrorMessage, ERROR_NOTIFY_ENUM_DIR);
end;
repeat
NextEntry := NotifyData^.NextEntryOffset;
// get memory for filename and fill it with data
GetMem(FileName, NotifyData^.FileNameLength + SizeOf(WideChar));
Move(NotifyData^.FileName, Pointer(FileName)^, NotifyData^.FileNameLength);
PWord(Cardinal(FileName) + NotifyData^.FileNameLength)^ := 0;
// send the message about the filename information and advance to the next entry
PostMessage(FWndHandle, WM_FOLDERWATCH_NOTIFY, NotifyData^.Action, LParam(FileName));
PByte(NotifyData) := PByte(DWORD(NotifyData) + NextEntry);
until (NextEntry = 0);
end
else
begin
ErrorMessage := SysErrorMessage(GetLastError);
SignalError(ErrorMessage);
end;
end;
end
else
begin
ErrorMessage := SysErrorMessage(GetLastError);
SignalError(ErrorMessage);
end;
except
on E:Exception do
begin
ErrorMessage := E.Message;
SignalError(ErrorMessage);
end;
end;
end;
procedure TIEFolderWatchThread.SignalError(const ErrorMessage: string; ErrorCode: Cardinal);
var
ErrorMsg: PChar;
MessageSize: Integer;
begin
if ErrorCode = 0 then
ErrorCode := GetLastError;
// calculate the size of the error message buffer
MessageSize := Length(ErrorMessage) * SizeOf(Char) + SizeOf(WideChar);
GetMem(ErrorMsg, MessageSize);
StrPCopy(ErrorMsg, ErrorMessage);
PostMessage(FWndHandle, WM_FOLDERWATCH_ERROR, ErrorCode, LPARAM(ErrorMsg));
end;
constructor TIEFolderWatchThread.Create(const Path: string;
const WndHandle: HWND;
const BufferSize: Integer;
const AbortEvent: THandle;
const TypeFilter: Cardinal;
const aWatchSubTree: Boolean);
begin
//
// Retrieve proc pointer, open directory to
// watch and allocate buffer for notification data.
// (note, it is done before calling inherited
// create (that calls BeginThread) so any exception
// will be still raised in caller's thread)
//
FDirHandle := CreateFile(PChar(Path),
FILE_LIST_DIRECTORY,
FILE_SHARE_READ OR
FILE_SHARE_DELETE OR
FILE_SHARE_WRITE,
nil, OPEN_EXISTING,
FILE_FLAG_BACKUP_SEMANTICS OR
FILE_FLAG_OVERLAPPED,
0);
if FDirHandle = INVALID_HANDLE_VALUE then
raise EIEException.CreateFmt(cErrorCreateWatchError, [Path, GetLastError]);
FChangeEvent := CreateEvent(nil, FALSE, FALSE, nil);
FAbortEvent := AbortEvent;
// allocate the buffer memory
FBufferSize := BufferSize * SizeOf(TFILE_NOTIFY_INFORMATION);
GetMem(FIOResult, FBufferSize);
FWatchSubTree := aWatchSubtree;
FWndHandle := WndHandle;
FPath := Path;
FFilter := TypeFilter;
inherited Create(False);
end;
destructor TIEFolderWatchThread.Destroy;
begin
CloseHandle(FChangeEvent);
if FDirHandle <> INVALID_HANDLE_VALUE then
CloseHandle(FDirHandle);
if Assigned(FIOResult) then
FreeMem(FIOResult);
inherited Destroy;
end;
procedure TIEFolderWatch.AllocWatchThread;
begin
if FWatchThread = nil then
begin
FAbortEvent := CreateEvent(nil, FALSE, FALSE, nil);
FWatchThread := TIEFolderWatchThread.Create(Path,
FWndHandle,
FBufferSize,
FAbortEvent,
MakeFilter,
WatchSubtree);
end;
end;
procedure TIEFolderWatch.ReleaseWatchThread;
var
AResult: Cardinal;
ThreadHandle: THandle;
begin
if FWatchThread <> nil then
begin
ThreadHandle := FWatchThread.Handle;
// set and close event
SetEvent(FAbortEvent);
// wait and block until thread is finished
AResult := WaitForSingleObject(ThreadHandle, cShutdownTimeout);
// check if we timed out
if AResult = WAIT_TIMEOUT then
TerminateThread(ThreadHandle, 0);
FreeAndNil(FWatchThread);
CloseHandle(FAbortEvent);
end;
end;
procedure TIEFolderWatch.RestartWatchThread;
begin
Stop;
Start;
end;
function TIEFolderWatch.Running: Boolean;
begin
Result := FWatchThread <> nil;
end;
procedure TIEFolderWatch.DeallocateHWnd(Wnd: HWND);
var
Instance: Pointer;
begin
Instance := Pointer(GetWindowLong(Wnd, GWL_WNDPROC));
if Instance <> @DefWindowProc then
begin
{ make sure we restore the default
windows procedure before freeing memory }
SetWindowLong(Wnd, GWL_WNDPROC, Longint(@DefWindowProc));
FreeObjectInstance(Instance);
end;
DestroyWindow(Wnd);
end;
destructor TIEFolderWatch.Destroy;
begin
Stop;
DeallocateHWnd(FWndHandle);
inherited Destroy;
end;
constructor TIEFolderWatch.Create;
begin
FWndHandle := AllocateHWnd(WatchWndProc);
FWatchSubtree := True;
FBufferSize := 32;
// construct the default watch actions and options
FWatchActions := [waAdded, waRemoved, waModified, waRenamedOld, waRenamedNew];
FWatchOptions := [woFileName, woFolderName, woAttributes, woSize, woLastWrite,
woLastAccess, woCreation, woSecurity];
end;
procedure TIEFolderWatch.SetWatchActions(const Value: TWatchActions);
begin
if FWatchActions <> Value then
begin
FWatchActions := Value;
if Running then
RestartWatchThread;
Change;
end;
end;
procedure TIEFolderWatch.SetWatchOptions(const Value: TWatchOptions);
begin
if FWatchOptions <> Value then
begin
FWatchOptions := Value;
if Running then
RestartWatchThread;
Change;
end;
end;
procedure TIEFolderWatch.WatchWndProc(var Msg : TMessage);
var
ErrorCode: Cardinal;
ErrorMessage: string;
begin
case Msg.msg of
WM_FOLDERWATCH_NOTIFY:
//
// Retrieve notify data and forward
// the event to TIEFolderWatch's notify
// handler. Free filename string (allocated
// in WatchThread's notify handler.)
//
begin
try
Notify(Msg.wParam, WideCharToString(PWideChar(Msg.lParam)));
finally
if Msg.lParam <> 0 then
FreeMem(Pointer(Msg.lParam));
end;
end;
WM_FOLDERWATCH_ERROR:
//
// Disable dir watch and re-raise
// exception on error
//
begin
try
ErrorMessage := StrPas(PChar(Msg.lParam));
ErrorCode := Msg.WParam;
if Assigned(FOnError) then
FOnError(Self, ErrorCode, ErrorMessage);
finally
if Msg.lParam <> 0 then
FreeMem(Pointer(Msg.lParam));
end;
end;
//
// pass all other messages down the line
//
else
begin
Msg.Result := DefWindowProc(FWndHandle, Msg.Msg, Msg.wParam, Msg.lParam);
Exit;
end;
end;
end;
function TIEFolderWatch.MakeFilter: Integer;
const
FilterFlags: array [TWatchOption] of Integer = (FILE_NOTIFY_CHANGE_FILE_NAME,
FILE_NOTIFY_CHANGE_DIR_NAME,
FILE_NOTIFY_CHANGE_ATTRIBUTES,
FILE_NOTIFY_CHANGE_SIZE,
FILE_NOTIFY_CHANGE_LAST_WRITE,
FILE_NOTIFY_CHANGE_LAST_ACCESS,
FILE_NOTIFY_CHANGE_CREATION,
FILE_NOTIFY_CHANGE_SECURITY);
{$IFDEF Delphi2005orNewer}
var
Flag: TWatchOption;
begin
Result := 0;
for Flag in FWatchOptions do
Result := Result or FilterFlags[Flag];
end;
{$ELSE}
begin
Result := 0;
if woFileName in FWatchOptions then
Result := Result or FILE_NOTIFY_CHANGE_FILE_NAME;
if woFolderName in FWatchOptions then
Result := Result or FILE_NOTIFY_CHANGE_DIR_NAME;
if woAttributes in FWatchOptions then
Result := Result or FILE_NOTIFY_CHANGE_ATTRIBUTES;
if woSize in FWatchOptions then
Result := Result or FILE_NOTIFY_CHANGE_SIZE;
if woLastWrite in FWatchOptions then
Result := Result or FILE_NOTIFY_CHANGE_LAST_WRITE;
if woLastAccess in FWatchOptions then
Result := Result or FILE_NOTIFY_CHANGE_LAST_ACCESS;
if woCreation in FWatchOptions then
Result := Result or FILE_NOTIFY_CHANGE_CREATION;
if woSecurity in FWatchOptions then
Result := Result or FILE_NOTIFY_CHANGE_SECURITY;
end;
{$ENDIF}
procedure TIEFolderWatch.SetWatchSubTree(const Value : Boolean);
begin
if Value <> FWatchSubtree then
begin
FWatchSubtree := Value;
if Running then
RestartWatchThread;
Change;
end;
end;
procedure TIEFolderWatch.Start;
begin
if FPath = '' then
raise EIEException.Create('No Path!');
if not Running then
begin
AllocWatchThread;
Change;
end;
end;
procedure TIEFolderWatch.Stop;
begin
if Running then
begin
ReleaseWatchThread;
Change;
end;
end;
procedure TIEFolderWatch.SetPath(const Value: string);
begin
if StrIComp(PChar(Trim(Value)), PChar(FPath)) <> 0 then
begin
FPath := Trim(Value);
if Running then
RestartWatchThread;
Change;
end;
end;
procedure TIEFolderWatch.Change;
begin
if Assigned(FOnChange) then
FOnChange(Self);
end;
procedure TIEFolderWatch.Notify(const Action: Integer; const FileName: string);
begin
if Assigned(FOnNotify) then
if TWatchAction(Action - 1) in FWatchActions then
FOnNotify(Self, TWatchAction(Action - 1), IEAddBackSlash(FPath) + FileName);
end;
initialization
OleInitialize(nil);
finalization
OleUninitialize;
{!!
<FS>iexWindowsFunctions
<FN>iexWindowsFunctions.pas provides access to Windows API methods for file and folder management. It is mainly used for <A TImageEnFolderMView>.
<FM>CLASSES<FN>
<TABLE2>
<R> <C_IMG_CLASS> <C><A TIEFileDragDrop></C> </R>
<R> <C_IMG_CLASS> <C><A TIEFolderWatch></C> </R>
</TABLE>
<FM>FILE OPERATION FUNCTIONS<FN>
<TABLE2>
<R> <C_IMG_GLOBMETHOD> <C><A WindowsCopy></C> </R>
<R> <C_IMG_GLOBMETHOD> <C><A WindowsMove></C> </R>
<R> <C_IMG_GLOBMETHOD> <C><A WindowsErase></C> </R>
<R> <C_IMG_GLOBMETHOD> <C><A WindowsLaunchFile></C> </R>
<R> <C_IMG_GLOBMETHOD> <C><A WindowsRename></C> </R>
</TABLE>
<FM>CLIPBOARD FUNCTIONS<FN>
<TABLE2>
<R> <C_IMG_GLOBMETHOD> <C><A CutFilesToClipboard></C> </R>
<R> <C_IMG_GLOBMETHOD> <C><A CopyFilesToClipboard></C> </R>
<R> <C_IMG_GLOBMETHOD> <C><A PasteFilesFromClipboard></C> </R>
<R> <C_IMG_GLOBMETHOD> <C><A CanPasteFilesFromClipboard></C> </R>
</TABLE>
<FM>SPECIAL FOLDER FUNCTIONS<FN>
<TABLE2>
<R> <C_IMG_GLOBMETHOD> <C><A WindowsDesktopFolder></C> </R>
<R> <C_IMG_GLOBMETHOD> <C><A WindowsMyVideosFolder></C> </R>
<R> <C_IMG_GLOBMETHOD> <C><A WindowsMyMusicFolder></C> </R>
<R> <C_IMG_GLOBMETHOD> <C><A WindowsMyPicturesFolder></C> </R>
<R> <C_IMG_GLOBMETHOD> <C><A WindowsMyDocumentsFolder></C> </R>
<R> <C_IMG_GLOBMETHOD> <C><A WindowsLocalAppDataFolder></C> </R>
<R> <C_IMG_GLOBMETHOD> <C><A WindowsProgramFilesFolder></C> </R>
<R> <C_IMG_GLOBMETHOD> <C><A GetWindowsSpecialFolder></C> </R>
</TABLE>
<FM>OTHER FUNCTIONS<FN>
<TABLE2>
<R> <C_IMG_GLOBMETHOD> <C><A ShowWindowsPrintWizard></C> </R>
<R> <C_IMG_GLOBMETHOD> <C><A WindowsSelectDirectory></C> </R>
<R> <C_IMG_GLOBMETHOD> <C><A WindowsAddToRecentDocs></C> </R>
<R> <C_IMG_GLOBMETHOD> <C><A PopupSystemMenu></C> </R>
</TABLE>
<FM>See Also<FN>
- <A IEFileSetDate>
- <A IEGetFileDetails>
- <A IEGetFileSize>
!!}
end.