- Mustangpeak Common Library - 1.7.0 - EasyListview - 1.7.0 git-svn-id: https://192.168.0.254/svn/Componentes.Terceros.Mustangpeak@2 60b41242-d4b9-2247-b156-4ccd40706241
1863 lines
52 KiB
ObjectPascal
1863 lines
52 KiB
ObjectPascal
unit MPCommonObjects;
|
|
|
|
// Version 1.7.0
|
|
//
|
|
// The contents of this file are subject to the Mozilla Public License
|
|
// Version 1.1 (the "License"); you may not use this file except in compliance
|
|
// with the License. You may obtain a copy of the License at http://www.mozilla.org/MPL/
|
|
//
|
|
// Alternatively, you may redistribute this library, use and/or modify it under the terms of the
|
|
// GNU Lesser General Public License as published by the Free Software Foundation;
|
|
// either version 2.1 of the License, or (at your option) any later version.
|
|
// You may obtain a copy of the LGPL at http://www.gnu.org/copyleft/.
|
|
//
|
|
// Software distributed under the License is distributed on an "AS IS" basis,
|
|
// WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for the
|
|
// specific language governing rights and limitations under the License.
|
|
//
|
|
// The initial developer of this code is Jim Kueneman <jimdk@mindspring.com>
|
|
// Special thanks to the following in no particular order for their help/support/code
|
|
// Danijel Malik, Robert Lee, Werner Lehmann, Alexey Torgashin, Milan Vandrovec
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
interface
|
|
|
|
{$I Compilers.inc}
|
|
{$I Options.inc}
|
|
{$I ..\Include\Addins.inc}
|
|
|
|
uses
|
|
Windows,
|
|
Messages,
|
|
Classes,
|
|
Controls,
|
|
Graphics,
|
|
SysUtils,
|
|
ActiveX,
|
|
{$IFDEF COMPILER_6_UP}
|
|
RTLConsts,
|
|
{$ELSE}
|
|
Consts,
|
|
{$ENDIF}
|
|
{$IFDEF COMPILER_7_UP}
|
|
Themes,
|
|
UxTheme,
|
|
{$ELSE}
|
|
{$IFDEF USETHEMES}
|
|
TmSchema,
|
|
UxTheme,
|
|
{$ENDIF}
|
|
{$ENDIF}
|
|
{$IFDEF TNTSUPPORT}
|
|
TntClasses,
|
|
TntWideStrings,
|
|
{$ENDIF}
|
|
ShlObj,
|
|
ShellAPI,
|
|
ImgList,
|
|
TypInfo,
|
|
MPShellTypes,
|
|
MPResources;
|
|
|
|
const
|
|
IID_ICommonExtractObj = '{7F667930-E47B-4474-BA62-B100D7DBDA70}';
|
|
|
|
type
|
|
TILIsParent = function(PIDL1: PItemIDList; PIDL2: PItemIDList;
|
|
ImmediateParent: LongBool): LongBool; stdcall;
|
|
TILIsEqual = function(PIDL1: PItemIDList; PIDL2: PItemIDList): LongBool; stdcall;
|
|
|
|
TCommonImageIndexInteger = type Integer;
|
|
|
|
|
|
TStringListEx = class(TStringList)
|
|
private
|
|
{$IFNDEF COMPILER_7_UP}
|
|
FNameValueSeparator: Char;
|
|
|
|
function GetNameValueSeparator: Char;
|
|
function GetValueFromIndex(Index: Integer): string;
|
|
procedure SetNameValueSeparator(const Value: Char);
|
|
procedure SetValueFromIndex(Index: Integer; const Value: string);
|
|
{$ENDIF}
|
|
public
|
|
{$IFNDEF COMPILER_7_UP}
|
|
property ValueFromIndex[Index: Integer]: string read GetValueFromIndex write SetValueFromIndex;
|
|
property NameValueSeparator: Char read GetNameValueSeparator write SetNameValueSeparator;
|
|
{$ENDIF}
|
|
end;
|
|
|
|
|
|
type
|
|
TCommonPIDLManager = class; // forward
|
|
TCommonPIDLList = class; // forward
|
|
|
|
TPIDLArray = array of PItemIDList;
|
|
TRelativePIDLArray = TPIDLArray;
|
|
TAbsolutePIDLArray = TPIDLArray;
|
|
|
|
ICommonExtractObj = interface
|
|
[IID_ICommonExtractObj]
|
|
function GetObj: TObject;
|
|
property Obj: TObject read GetObj;
|
|
end;
|
|
|
|
// In the ShellContextMenu items may be removed by not supplying the menu with
|
|
// these items. Note that by including them is DOES not mean that the items will
|
|
// in the menu. If the items do not support the action the shell with automatically
|
|
// remove the items.
|
|
TCommonShellContextMenuAction = (
|
|
cmaCopy,
|
|
cmaCut,
|
|
cmaPaste,
|
|
cmaDelete,
|
|
cmaRename,
|
|
cmaProperties,
|
|
cmaShortCut
|
|
);
|
|
TCommonShellContextMenuActions = set of TCommonShellContextMenuAction;
|
|
|
|
TCommonShellContextMenuExtension = (
|
|
cmeAllFilesystemObjects, // Add the Menu Extensions registered under HKEY_CLASSES_ROOT\AllFilesystemObjects such as Send To item
|
|
cmeDirectory, // Add the Menu Extensions registered under HKEY_CLASSES_ROOT\Directory
|
|
cmeDirBackground, // Add the Menu Extensions registered under HKEY_CLASSES_ROOT\Directory\Background
|
|
cmeFolder, // Add the Menu Extensions registered under HKEY_CLASSES_ROOT\Folder
|
|
cmeAsterik, // Add the Menu Extensions registered under HKEY_CLASSES_ROOT\*
|
|
cmeShellDefault, // Adds special actions like, Explore, Open, Search..., it depends on what other cme_ types are set, such as the Open/Explore Items
|
|
cmeFileSystemAssociations, // Add the Menu Extensions registered under HKEY_CLASSES_ROOT\FileSystemAssociations\{.ext}
|
|
cmePerceivedType // Checks for a PerceivedType string in the extension key {.ext} that points to a key in the HKEY_CLASSES_ROOT\FileSystemAssociations\SomePerceivedType such as "image". Will add the "Print" item
|
|
);
|
|
TCommonShellContextMenuExtensions = set of TCommonShellContextMenuExtension;
|
|
|
|
//
|
|
// Encapsulates Theme handles for various objects
|
|
//
|
|
{$IFDEF USETHEMES}
|
|
TCommonThemeManager = class
|
|
private
|
|
FButtonTheme: HTHEME; // Some useful Themes
|
|
FComboBoxTheme: HTHEME;
|
|
FEditTheme: HTHEME;
|
|
FExplorerBarTheme: HTHEME;
|
|
FHeaderTheme: HTHEME;
|
|
FListviewTheme: HTHEME;
|
|
FLoaded: Boolean;
|
|
FOwner: TWinControl;
|
|
FProgressTheme: HTHEME;
|
|
FRebarTheme: HTHEME;
|
|
FScrollbarTheme: HTheme;
|
|
FTaskBandTheme: HTHEME;
|
|
FTaskBarTheme: HTHEME;
|
|
FTreeviewTheme: HTHEME;
|
|
FWindowTheme: HTHEME;
|
|
public
|
|
constructor Create(AnOwner: TWinControl);
|
|
destructor Destroy; override;
|
|
|
|
procedure ThemesFree; dynamic;
|
|
procedure ThemesLoad; dynamic;
|
|
|
|
property ButtonTheme: HTHEME read FButtonTheme write FButtonTheme;
|
|
property ComboBoxTheme: HTHEME read FComboBoxTheme write FComboBoxTheme;
|
|
property EditThemeTheme: HTHEME read FEditTheme write FEditTheme;
|
|
property ExplorerBarTheme: HTHEME read FExplorerBarTheme write FExplorerBarTheme;
|
|
property HeaderTheme: HTHEME read FHeaderTheme write FHeaderTheme;
|
|
property ListviewTheme: HTHEME read FListviewTheme write FListviewTheme;
|
|
property Loaded: Boolean read FLoaded;
|
|
property Owner: TWinControl read FOwner;
|
|
property ProgressTheme: HTHEME read FProgressTheme write FProgressTheme;
|
|
property RebarTheme: HTHEME read FRebarTheme write FRebarTheme;
|
|
property ScrollbarTheme: HTheme read FScrollbarTheme write FScrollbarTheme;
|
|
property TaskBandTheme: HTHEME read FTaskBandTheme write FTaskBandTheme;
|
|
property TaskBarTheme: HTHEME read FTaskBarTheme write FTaskBarTheme;
|
|
property TreeviewTheme: HTHEME read FTreeviewTheme write FTreeviewTheme;
|
|
property WindowTheme: HTHEME read FWindowTheme write FWindowTheme;
|
|
end;
|
|
{$ENDIF USETHEMES}
|
|
|
|
//
|
|
// TWinControl that has a canvas and a few methods/properites for
|
|
// locking the canvas for higher performance drawing. Also handles
|
|
// XP and above theme support
|
|
//
|
|
TCommonCanvasControl = class(TCustomControl)
|
|
private
|
|
FCanvas: TControlCanvas;
|
|
FImagesExtraLarge: TImageList;
|
|
FImagesLarge: TImageList;
|
|
FImagesSmall: TImageList;
|
|
FOnEndUpdate: TNotifyEvent;
|
|
FThemed: Boolean;
|
|
{$IFDEF USETHEMES}FThemes: TCommonThemeManager;{$ENDIF USETHEMES}
|
|
function GetCanvas: TControlCanvas;
|
|
function GetThemed: Boolean;
|
|
procedure SetThemed(const Value: Boolean);
|
|
protected
|
|
FUpdateCount: Integer;
|
|
procedure CreateWnd; override;
|
|
procedure DoEndUpdate;
|
|
procedure DoUpdate; virtual;
|
|
function DrawWithThemes: Boolean;
|
|
procedure Notification(AComponent: TComponent; Operation: TOperation); override;
|
|
procedure WMDestroy(var Msg: TMessage); message WM_DESTROY;
|
|
{$IFDEF USETHEMES}procedure WMThemeChanged(var Message: TMessage); message WM_THEMECHANGED;{$ENDIF USETHEMES}
|
|
property OnEndUpdate: TNotifyEvent read FOnEndUpdate write FOnEndUpdate;
|
|
property Themed: Boolean read GetThemed write SetThemed default True;
|
|
public
|
|
constructor Create(AOwner: TComponent); override;
|
|
destructor Destroy; override;
|
|
|
|
procedure BeginUpdate; virtual;
|
|
procedure EndUpdate(Invalidate: Boolean = True); virtual;
|
|
procedure SafeInvalidateRect(ARect: PRect; ImmediateUpdate: Boolean);
|
|
|
|
property Canvas: TControlCanvas read GetCanvas write FCanvas;
|
|
property Color;
|
|
property DragCursor;
|
|
property DragMode;
|
|
{$IFDEF USETHEMES}property Themes: TCommonThemeManager read FThemes;{$ENDIF USETHEMES}
|
|
property UpdateCount: Integer read FUpdateCount;
|
|
end;
|
|
|
|
//
|
|
// Stores the state of a TCanvas so it may be restored later
|
|
//
|
|
TCommonDefaultCanvasState = class
|
|
private
|
|
FBkMode: Longword;
|
|
FFont: TFont;
|
|
FBrush: TBrush;
|
|
FPen: TPen;
|
|
FCanvasStored: Boolean;
|
|
FCopyMode: TCopyMode;
|
|
FPenPos: TPoint;
|
|
FTextFlags: Integer;
|
|
function GetBrush: TBrush;
|
|
function GetFont: TFont;
|
|
function GetPen: TPen;
|
|
public
|
|
destructor Destroy; override;
|
|
|
|
procedure StoreCanvas(ACanvas: TCanvas);
|
|
procedure RestoreCanvas(ACanvas: TCanvas);
|
|
|
|
property BkMode: Longword read FBkMode;
|
|
property CanvasStored: Boolean read FCanvasStored;
|
|
property CopyMode: TCopyMode read FCopyMode;
|
|
property Font: TFont read GetFont;
|
|
property Brush: TBrush read GetBrush;
|
|
property Pen: TPen read GetPen;
|
|
property PenPos: TPoint read FPenPos;
|
|
property TextFlags: Integer read FTextFlags;
|
|
end;
|
|
|
|
//
|
|
// A specialized TList that contains PItemID's
|
|
//
|
|
PCommonPIDLList = ^TCommonPIDLList;
|
|
TCommonPIDLList = class(TList)
|
|
private
|
|
FLocalPIDLMgr: TCommonPIDLManager; // this can be in an IDataObject that the shell holds on to, causing our global PIDLMgr to be freed on application destroy before the shell releases the IDataObject
|
|
FOwnsPIDLMgr: Boolean;
|
|
FSharePIDLs: Boolean; // If true the class will not free the PIDL's automaticlly when destroyed
|
|
FDestroying: Boolean; // Instance of a PIDLManager used to easily deal with the PIDL's
|
|
function GetLocalPIDLMgr: TCommonPIDLManager;
|
|
function GetPIDL(Index: integer): PItemIDList;
|
|
procedure SetLocalPIDLMgr(const Value: TCommonPIDLManager);
|
|
protected
|
|
property Destroying: Boolean read FDestroying;
|
|
property OwnsPIDLMgr: Boolean read FOwnsPIDLMgr write FOwnsPIDLMgr;
|
|
public
|
|
constructor Create;
|
|
destructor Destroy; override;
|
|
|
|
procedure Clear; override;
|
|
procedure CloneList(PIDLList: TCommonPIDLList);
|
|
function CopyAdd(PIDL: PItemIDList): Integer;
|
|
function FindPIDL(TestPIDL: PItemIDList): Integer;
|
|
function LoadFromStream( Stream: TStream): Boolean; virtual;
|
|
function SaveToStream( Stream: TStream): Boolean; virtual;
|
|
|
|
property LocalPIDLMgr: TCommonPIDLManager read GetLocalPIDLMgr write SetLocalPIDLMgr;
|
|
property SharePIDLs: Boolean read FSharePIDLs write FSharePIDLs;
|
|
end;
|
|
|
|
//
|
|
// TCoolPIDLManager is a class the encapsulates PIDLs and makes them easier to
|
|
// handle.
|
|
//
|
|
TCommonPIDLManager = class
|
|
private
|
|
protected
|
|
FMalloc: IMalloc; // The global Memory allocator
|
|
public
|
|
constructor Create;
|
|
destructor Destroy; override;
|
|
|
|
function AllocStrGlobal(SourceStr: WideString): POleStr;
|
|
function AppendPIDL(DestPIDL, SrcPIDL: PItemIDList): PItemIDList;
|
|
function BindToParent(AbsolutePIDL: PItemIDList; var Folder: IShellFolder): Boolean;
|
|
function CopyPIDL(APIDL: PItemIDList): PItemIDList;
|
|
function EqualPIDL(PIDL1, PIDL2: PItemIDList): Boolean;
|
|
procedure FreeAndNilPIDL(var PIDL: PItemIDList);
|
|
procedure FreeOLEStr(OLEStr: LPWSTR);
|
|
procedure FreePIDL(PIDL: PItemIDList);
|
|
function CopyLastID(IDList: PItemIDList): PItemIDList;
|
|
function GetPointerToLastID(IDList: PItemIDList): PItemIDList;
|
|
function IDCount(APIDL: PItemIDList): integer;
|
|
function IsDesktopFolder(APIDL: PItemIDList): Boolean;
|
|
function IsSubPIDL(FullPIDL, SubPIDL: PItemIDList): Boolean;
|
|
function NextID(APIDL: PItemIDList): PItemIDList;
|
|
function PIDLSize(APIDL: PItemIDList): integer;
|
|
function LoadFromStream(Stream: TStream): PItemIDList;
|
|
procedure ParsePIDL(AbsolutePIDL: PItemIDList; var PIDLList: TCommonPIDLList; AllAbsolutePIDLs: Boolean);
|
|
function StringToPIDL(PIDLStr: string): PItemIDList;
|
|
function StripLastID(IDList: PItemIDList): PItemIDList; overload;
|
|
function StripLastID(IDList: PItemIDList; var Last_CB: Word; var LastID: PItemIDList): PItemIDList; overload;
|
|
procedure SaveToStream(Stream: TStream; PIDL: PItemIdList);
|
|
|
|
property Malloc: IMalloc read FMalloc;
|
|
end;
|
|
|
|
|
|
//
|
|
// Helper object to write basic property types to a Stream
|
|
//
|
|
TCommonMemoryStreamHelper = class
|
|
public
|
|
function ReadBoolean(S: TStream): Boolean;
|
|
function ReadColor(S: TStream): TColor;
|
|
function ReadInt64(S: TStream): Int64;
|
|
function ReadInteger(S: TStream): Integer;
|
|
function ReadString(S: TStream): string;
|
|
function ReadWideString(S: TStream): WideString;
|
|
function ReadExtended(S: TStream): Extended;
|
|
procedure ReadStream(SourceStream, TargetStream: TStream);
|
|
// procedure ReadPublishedProperties(S: TStream; Instance: TObject; RecurseSubClasses: Boolean);
|
|
procedure WriteBoolean(S: TStream; Value: Boolean);
|
|
procedure WriteColor(S: TStream; Value: TColor);
|
|
procedure WriteExtended(S: TStream; Value: Extended);
|
|
procedure WriteInt64(S: TStream; Value: Int64);
|
|
procedure WriteInteger(S: TStream; Value: Integer);
|
|
procedure WriteStream(SourceStream, TargetStream: TStream);
|
|
// procedure WritePublishedProperties(S: TStream; Instance: TObject; RecurseSubClasses: Boolean);
|
|
procedure WriteString(S: TStream; Value: string);
|
|
procedure WriteWideString(S: TStream; Value: WideString);
|
|
end;
|
|
|
|
//
|
|
// MemoryStream that knows how to write/read basic data types
|
|
//
|
|
TCommonStream = class(TMemoryStream)
|
|
public
|
|
function ReadBoolean: Boolean;
|
|
function ReadByte: Byte;
|
|
function ReadInteger: Integer;
|
|
function ReadString: string;
|
|
function ReadStringList: TStringList;
|
|
function ReadWideString: WideString;
|
|
|
|
procedure WriteBoolean(Value: Boolean);
|
|
procedure WriteByte(Value: Byte);
|
|
procedure WriteInteger(Value: Integer);
|
|
procedure WriteString(const Value: string);
|
|
procedure WriteStringList(Value: TStringList);
|
|
procedure WriteWideString(const Value: WideString);
|
|
end;
|
|
|
|
//
|
|
// The dimension of the Marlett Checkbox Font
|
|
//
|
|
TCommonCheckBound = class
|
|
private
|
|
FBounds: TRect;
|
|
FSize: Integer;
|
|
public
|
|
property Size: Integer read FSize write FSize;
|
|
property Bounds: TRect read FBounds write FBounds;
|
|
end;
|
|
|
|
//
|
|
// The Stores the dimensions for various sizes of the Marlett Checkbox Font
|
|
//
|
|
TCommonCheckBoundManager = class
|
|
private
|
|
FList: TList;
|
|
function GetBound(Size: Integer): TRect;
|
|
function GetCheckBound(Index: Integer): TCommonCheckBound;
|
|
protected
|
|
procedure Clear;
|
|
function Find(Size: Integer): TCommonCheckBound;
|
|
|
|
property List: TList read FList write FList;
|
|
property CheckBound[Index: Integer]: TCommonCheckBound read GetCheckBound;
|
|
public
|
|
constructor Create;
|
|
destructor Destroy; override;
|
|
|
|
property Bound[Size: Integer]: TRect read GetBound;
|
|
end;
|
|
|
|
//
|
|
// Encapsulates the System image lists
|
|
//
|
|
TSysImageListSize = (
|
|
sisSmall, // Large System Images
|
|
sisLarge, // Small System Images
|
|
sisExtraLarge // Extra Large Images (48x48)
|
|
);
|
|
|
|
TCommonSysImages = class(TImageList)
|
|
private
|
|
FImageSize: TSysImageListSize;
|
|
FJumboImages: IImageList;
|
|
procedure SetImageSize(const Value: TSysImageListSize);
|
|
protected
|
|
procedure RecreateHandle;
|
|
procedure Flush;
|
|
property JumboImages: IImageList read FJumboImages;
|
|
public
|
|
constructor Create(AOwner: TComponent); override;
|
|
destructor Destroy; override;
|
|
|
|
property ImageSize: TSysImageListSize read FImageSize write SetImageSize;
|
|
end;
|
|
|
|
function ExtraLargeSysImages: TCommonSysImages;
|
|
function LargeSysImages: TCommonSysImages;
|
|
function SmallSysImages: TCommonSysImages;
|
|
|
|
procedure FlushImageLists;
|
|
procedure CreateFullyQualifiedShellDataObject(AbsolutePIDLs: TAbsolutePIDLArray; var ADataObject: IDataObject);
|
|
var
|
|
StreamHelper: TCommonMemoryStreamHelper;
|
|
ILIsParent: TILIsParent = nil;
|
|
ILIsEqual: TILIsEqual = nil;
|
|
Checks: TCommonCheckBoundManager;
|
|
MarlettFont: TFont;
|
|
|
|
|
|
implementation
|
|
|
|
uses
|
|
MPCommonUtilities,
|
|
MPDataObject;
|
|
|
|
var
|
|
FreeShellLib: Boolean = False;
|
|
ShellDLL: HMODULE = 0;
|
|
FExtraLargeSysImages: TCommonSysImages = nil;
|
|
FLargeSysImages: TCommonSysImages = nil;
|
|
FSmallSysImages: TCommonSysImages = nil;
|
|
PIDLMgr: TCommonPIDLManager = nil;
|
|
|
|
{$IFNDEF COMPILER_6_UP}
|
|
function GUIDToString(const GUID: TGUID): string;
|
|
var
|
|
P: PWideChar;
|
|
begin
|
|
Result := '';
|
|
if Succeeded(StringFromCLSID(GUID, P)) then
|
|
begin
|
|
Result := P;
|
|
CoTaskMemFree(P);
|
|
end
|
|
end;
|
|
{$ENDIF}
|
|
|
|
procedure FlushImageLists;
|
|
begin
|
|
if Assigned(FSmallSysImages) then
|
|
FSmallSysImages.Flush;
|
|
if Assigned(FLargeSysImages) then
|
|
FLargeSysImages.Flush;
|
|
if Assigned(FExtraLargeSysImages) then
|
|
FExtraLargeSysImages.Flush
|
|
end;
|
|
|
|
function ExtraLargeSysImages: TCommonSysImages;
|
|
begin
|
|
if not Assigned(FExtraLargeSysImages) then
|
|
begin
|
|
FExtraLargeSysImages := TCommonSysImages.Create(nil);
|
|
FExtraLargeSysImages.ImageSize := sisExtraLarge;
|
|
end;
|
|
Result := FExtraLargeSysImages
|
|
end;
|
|
|
|
function LargeSysImages: TCommonSysImages;
|
|
begin
|
|
if not Assigned(FLargeSysImages) then
|
|
begin
|
|
FLargeSysImages := TCommonSysImages.Create(nil);
|
|
FLargeSysImages.ImageSize := sisLarge;
|
|
end;
|
|
Result := FLargeSysImages
|
|
end;
|
|
|
|
function SmallSysImages: TCommonSysImages;
|
|
begin
|
|
if not Assigned(FSmallSysImages) then
|
|
begin
|
|
FSmallSysImages := TCommonSysImages.Create(nil);
|
|
FSmallSysImages.ImageSize := sisSmall;
|
|
end;
|
|
Result := FSmallSysImages
|
|
end;
|
|
|
|
function SHGetImageList(iImageList: Integer; const RefID: TGUID; out ppvOut): HRESULT;
|
|
// Retrieves the system ImageList interface
|
|
var
|
|
ImageList: TSHGetImageList;
|
|
begin
|
|
Result := E_NOTIMPL;
|
|
if (Win32Platform = VER_PLATFORM_WIN32_NT) then
|
|
begin
|
|
ShellDLL := LoadLibrary(Shell32);
|
|
if ShellDLL <> 0 then
|
|
begin
|
|
ImageList := GetProcAddress(ShellDLL, PChar(727));
|
|
if (Assigned(ImageList)) then
|
|
Result := ImageList(iImageList, RefID, ppvOut);
|
|
end
|
|
end;
|
|
end;
|
|
|
|
procedure CreateFullyQualifiedShellDataObject(AbsolutePIDLs: TAbsolutePIDLArray; var ADataObject: IDataObject);
|
|
var
|
|
ShellIDList: TCommonShellIDList;
|
|
APIDLList: TCommonPIDLList;
|
|
i: Integer;
|
|
HDrop: TCommonHDrop;
|
|
DragLoop: TCommonInShellDragLoop;
|
|
{$IFDEF TNTSUPPORT}
|
|
FileListW: TTntStringList;
|
|
{$ENDIF}
|
|
FileListA: TStringList;
|
|
DesktopPIDL, LastID: PItemIDList;
|
|
DesktopFolder, Folder: IShellFolder;
|
|
Flags: UINT;
|
|
StrRet: TStrRet;
|
|
begin
|
|
ADataObject := TCommonDataObject.Create;
|
|
if Assigned(AbsolutePIDLs) then
|
|
begin
|
|
APIDLList := TCommonPIDLList.Create;
|
|
APIDLList.SharePIDLs := True;
|
|
ShellIDList := TCommonShellIDList.Create;
|
|
DragLoop := TCommonInShellDragLoop.Create;
|
|
HDrop := TCommonHDrop.Create;
|
|
{$IFDEF TNTSUPPORT}
|
|
FileListW := TTntStringList.Create;
|
|
{$ENDIF}
|
|
FileListA := TStringList.Create;
|
|
try
|
|
SHGetSpecialFolderLocation(0, CSIDL_DESKTOP, DesktopPIDL);
|
|
SHGetDesktopFolder(DesktopFolder);
|
|
APIDLList.Add(DesktopPIDL);
|
|
// Add all the PIDL's from all the DataObjects based off the desktop (Absolute PIDLs)
|
|
for i := 0 to Length(AbsolutePIDLs) - 1 do
|
|
begin
|
|
APIDLList.Add(AbsolutePIDLs[i]);
|
|
|
|
if PIDLMgr.BindToParent(AbsolutePIDLs[i], Folder) then
|
|
begin
|
|
LastID := PIDLMgr.GetPointerToLastID(AbsolutePIDLs[i]);
|
|
Flags := SFGAO_FILESYSTEM;
|
|
if Succeeded(Folder.GetAttributesOf(1, LastID, Flags)) then
|
|
if SFGAO_FILESYSTEM and Flags <> 0 then
|
|
begin
|
|
FillChar(StrRet, SizeOf(StrRet), #0);
|
|
Flags := SHGDN_FORPARSING;
|
|
if Succeeded(Folder.GetDisplayNameOf(LastID, Flags, StrRet)) then
|
|
begin
|
|
{$IFDEF TNTSUPPORT}
|
|
if IsUnicode then
|
|
FileListW.Add(StrRetToStr(StrRet, LastID))
|
|
else
|
|
FileListA.Add(StrRetToStr(StrRet, LastID));
|
|
{$ELSE}
|
|
FileListA.Add(StrRetToStr(StrRet, LastID));
|
|
{$ENDIF}
|
|
end;
|
|
end
|
|
end
|
|
end;
|
|
ShellIDList.AssignPIDLs(APIDLList);
|
|
{$IFDEF TNTSUPPORT}
|
|
if IsUnicode then
|
|
HDrop.AssignFilesW(FileListW)
|
|
else
|
|
HDrop.AssignFilesA(FileListA);
|
|
{$ELSE}
|
|
HDrop.AssignFilesA(FileListA);
|
|
{$ENDIF}
|
|
ShellIDList.SaveToDataObject(ADataObject);
|
|
HDrop.SaveToDataObject(ADataObject);
|
|
DragLoop.SaveToDataObject(ADataObject)
|
|
finally
|
|
ShellIDList.Free;
|
|
HDrop.Free;
|
|
{$IFDEF TNTSUPPORT}
|
|
FileListW.Free;
|
|
{$ENDIF}
|
|
FileListA.Free;
|
|
DragLoop.Free;
|
|
APIDLList.Free;
|
|
PIDLMgr.FreePIDL(DesktopPIDL)
|
|
end
|
|
end
|
|
end;
|
|
|
|
{ TCoolDefaultCanvasState }
|
|
|
|
destructor TCommonDefaultCanvasState.Destroy;
|
|
begin
|
|
inherited;
|
|
FreeAndNil(FBrush);
|
|
FreeAndNil(FFont);
|
|
FreeAndNil(FPen);
|
|
end;
|
|
|
|
function TCommonDefaultCanvasState.GetBrush: TBrush;
|
|
begin
|
|
if not Assigned(FBrush) then
|
|
FBrush := TBrush.Create;
|
|
Result := FBrush
|
|
end;
|
|
|
|
function TCommonDefaultCanvasState.GetFont: TFont;
|
|
begin
|
|
if not Assigned(FFont) then
|
|
FFont := TFont.Create;
|
|
Result := FFont
|
|
end;
|
|
|
|
function TCommonDefaultCanvasState.GetPen: TPen;
|
|
begin
|
|
if not Assigned(FPen) then
|
|
FPen := TPen.Create;
|
|
Result := FPen
|
|
end;
|
|
|
|
procedure TCommonDefaultCanvasState.RestoreCanvas(ACanvas: TCanvas);
|
|
begin
|
|
Assert(CanvasStored, 'Trying to restore a canvas that has not been saved');
|
|
SetBkMode(ACanvas.Handle, FBkMode);
|
|
ACanvas.CopyMode := FCopyMode;
|
|
ACanvas.Font.Assign(Font);
|
|
ACanvas.Brush.Assign(Brush);
|
|
ACanvas.Pen.Assign(Pen);
|
|
ACanvas.PenPos := FPenPos;
|
|
ACanvas.TextFlags := FTextFlags;
|
|
SelectClipRgn(ACanvas.Handle, 0);
|
|
end;
|
|
|
|
procedure TCommonDefaultCanvasState.StoreCanvas(ACanvas: TCanvas);
|
|
begin
|
|
FCanvasStored := True;
|
|
FBkMode := GetBkMode(ACanvas.Handle);
|
|
FCopyMode := ACanvas.CopyMode;
|
|
Font.Assign(ACanvas.Font);
|
|
Brush.Assign(ACanvas.Brush);
|
|
Pen.Assign(ACanvas.Pen);
|
|
FPenPos := ACanvas.PenPos;
|
|
FTextFlags := ACanvas.TextFlags;
|
|
end;
|
|
|
|
{ TCommonCanvasControl }
|
|
|
|
function TCommonCanvasControl.DrawWithThemes: Boolean;
|
|
begin
|
|
{$IFDEF USETHEMES}
|
|
Result := Themed and Themes.Loaded;
|
|
{$ELSE}
|
|
Result := False;
|
|
{$ENDIF USETHEMES}
|
|
end;
|
|
|
|
function TCommonCanvasControl.GetThemed: Boolean;
|
|
begin
|
|
Result := False;
|
|
{$IFDEF USETHEMES}
|
|
if not (csLoading in ComponentState) then
|
|
Result := FThemed and UseThemes;
|
|
{$ENDIF USETHEMES}
|
|
end;
|
|
|
|
procedure TCommonCanvasControl.BeginUpdate;
|
|
//
|
|
// If ReIndex = False it is up to the user to understand when it is necessary
|
|
// to ReIndex different objects. By doing so performance may be enhanced
|
|
// drasticlly on large data sets.
|
|
begin
|
|
Inc(FUpdateCount);
|
|
end;
|
|
|
|
constructor TCommonCanvasControl.Create(AOwner: TComponent);
|
|
begin
|
|
inherited;
|
|
FCanvas := TControlCanvas.Create;
|
|
Canvas.Control := Self;
|
|
// No notifications for font change
|
|
Font.OnChange := nil;
|
|
{$IFDEF USETHEMES}FThemes := TCommonThemeManager.Create(Self);{$ENDIF USETHEMES}
|
|
FThemed := True;
|
|
end;
|
|
|
|
destructor TCommonCanvasControl.Destroy;
|
|
begin
|
|
inherited;
|
|
{$IFDEF USETHEMES}FreeAndNil(FThemes);{$ENDIF USETHEMES}
|
|
FreeAndNil(FCanvas);
|
|
end;
|
|
|
|
procedure TCommonCanvasControl.CreateWnd;
|
|
begin
|
|
inherited CreateWnd;
|
|
{$IFDEF USETHEMES}Themes.ThemesLoad;{$ENDIF USETHEMES}
|
|
end;
|
|
|
|
procedure TCommonCanvasControl.DoEndUpdate;
|
|
begin
|
|
if Assigned(OnEndUpdate) then
|
|
OnEndUpdate(Self)
|
|
end;
|
|
|
|
procedure TCommonCanvasControl.DoUpdate;
|
|
begin
|
|
end;
|
|
|
|
procedure TCommonCanvasControl.EndUpdate(Invalidate: Boolean = True);
|
|
begin
|
|
Dec(FUpdateCount);
|
|
if (UpdateCount <= 0) then
|
|
begin
|
|
FUpdateCount := 0;
|
|
DoUpdate;
|
|
if Invalidate and HandleAllocated then
|
|
UpdateWindow(Handle);
|
|
DoEndUpdate;
|
|
end
|
|
end;
|
|
|
|
function TCommonCanvasControl.GetCanvas: TControlCanvas;
|
|
begin
|
|
FCanvas.Font.Assign(Font);
|
|
FCanvas.Brush.Assign(Brush);
|
|
Result := FCanvas;
|
|
end;
|
|
|
|
procedure TCommonCanvasControl.Notification(AComponent: TComponent;
|
|
Operation: TOperation);
|
|
begin
|
|
inherited;
|
|
if Operation = opRemove then
|
|
begin
|
|
if AComponent = FImagesExtraLarge then
|
|
FImagesExtraLarge := nil
|
|
else
|
|
if AComponent = FImagesLarge then
|
|
FImagesLarge := nil
|
|
else
|
|
if AComponent = FImagesSmall then
|
|
FImagesSmall := nil
|
|
end
|
|
end;
|
|
|
|
procedure TCommonCanvasControl.SafeInvalidateRect(ARect: PRect; ImmediateUpdate: Boolean);
|
|
begin
|
|
if HandleAllocated then
|
|
begin
|
|
InvalidateRect(Handle, ARect, False);
|
|
if ImmediateUpdate then
|
|
UpdateWindow(Handle)
|
|
end
|
|
end;
|
|
|
|
procedure TCommonCanvasControl.SetThemed(const Value: Boolean);
|
|
begin
|
|
if Value <> FThemed then
|
|
begin
|
|
FThemed := Value;
|
|
{$IFDEF USETHEMES}
|
|
if Value then
|
|
Themes.ThemesLoad
|
|
else
|
|
Themes.ThemesFree;
|
|
if HandleAllocated then
|
|
begin
|
|
// This is the only way I could get the window to redraw the NonClient areas
|
|
// RedrawWindow did not work either.
|
|
Visible := not Visible;
|
|
Visible := not Visible;
|
|
SafeInvalidateRect(nil, True);
|
|
end;
|
|
{$ENDIF USETHEMES}
|
|
end
|
|
end;
|
|
|
|
procedure TCommonCanvasControl.WMDestroy(var Msg: TMessage);
|
|
begin
|
|
{$IFDEF USETHEMES}Themes.ThemesFree;{$ENDIF USETHEMES}
|
|
inherited;
|
|
end;
|
|
|
|
{$IFDEF USETHEMES}
|
|
procedure TCommonCanvasControl.WMThemeChanged(var Message: TMessage);
|
|
begin
|
|
inherited;
|
|
Themes.ThemesFree;
|
|
Themes.ThemesLoad;
|
|
end;
|
|
{$ENDIF USETHEMES}
|
|
|
|
{ TCoolPIDLList }
|
|
|
|
constructor TCommonPIDLList.Create;
|
|
begin
|
|
inherited Create;
|
|
end;
|
|
|
|
function TCommonPIDLList.GetLocalPIDLMgr: TCommonPIDLManager;
|
|
begin
|
|
if not Assigned(FLocalPIDLMgr) then
|
|
begin
|
|
FLocalPIDLMgr := TCommonPIDLManager.Create;
|
|
OwnsPIDLMgr := True;
|
|
end;
|
|
Result := FLocalPIDLMgr
|
|
end;
|
|
|
|
procedure TCommonPIDLList.Clear;
|
|
var
|
|
i: integer;
|
|
begin
|
|
if {(not Destroying) or} Assigned(PIDLMgr) then
|
|
begin
|
|
if not SharePIDLs and Assigned(PIDLMgr)then
|
|
for i := 0 to Count - 1 do
|
|
LocalPIDLMgr.FreePIDL( PItemIDList( Items[i]));
|
|
end;
|
|
inherited;
|
|
end;
|
|
|
|
procedure TCommonPIDLList.CloneList(PIDLList: TCommonPIDLList);
|
|
var
|
|
i: Integer;
|
|
begin
|
|
if Assigned(PIDLList) then
|
|
for i := 0 to Count - 1 do
|
|
PIDLList.CopyAdd(Items[i])
|
|
end;
|
|
|
|
function TCommonPIDLList.CopyAdd(PIDL: PItemIDList): integer;
|
|
// Adds a Copy of the passed PIDL to the list
|
|
begin
|
|
Result := Add( LocalPIDLMgr.CopyPIDL(PIDL));
|
|
end;
|
|
|
|
destructor TCommonPIDLList.Destroy;
|
|
begin
|
|
FDestroying := True;
|
|
if OwnsPIDLMgr then
|
|
FreeAndNil(FLocalPIDLMgr);
|
|
inherited;
|
|
end;
|
|
|
|
function TCommonPIDLList.FindPIDL(TestPIDL: PItemIDList): Integer;
|
|
// Finds the index of the PIDL that is equivalent to the passed PIDL. This is not
|
|
// the same as an byte for byte equivalent comparison
|
|
var
|
|
i: Integer;
|
|
begin
|
|
i := 0;
|
|
Result := -1;
|
|
while (i < Count) and (Result < 0) do
|
|
begin
|
|
if LocalPIDLMgr.EqualPIDL(TestPIDL, GetPIDL(i)) then
|
|
Result := i;
|
|
Inc(i);
|
|
end;
|
|
end;
|
|
|
|
function TCommonPIDLList.GetPIDL(Index: integer): PItemIDList;
|
|
begin
|
|
Result := PItemIDList( Items[Index]);
|
|
end;
|
|
|
|
function TCommonPIDLList.LoadFromStream(Stream: TStream): Boolean;
|
|
// Loads the PIDL list from a stream
|
|
var
|
|
PIDLCount, i: integer;
|
|
begin
|
|
Result := True;
|
|
try
|
|
Stream.ReadBuffer(PIDLCount, SizeOf(Integer));
|
|
for i := 0 to PIDLCount - 1 do
|
|
Add( LocalPIDLMgr.LoadFromStream(Stream));
|
|
except
|
|
Result := False;
|
|
end;
|
|
end;
|
|
|
|
function TCommonPIDLList.SaveToStream(Stream: TStream): Boolean;
|
|
// Saves the PIDL list to a stream
|
|
var
|
|
i: integer;
|
|
begin
|
|
Result := True;
|
|
try
|
|
Stream.WriteBuffer(Count, SizeOf(Count));
|
|
for i := 0 to Count - 1 do
|
|
LocalPIDLMgr.SaveToStream(Stream, Items[i]);
|
|
except
|
|
Result := False;
|
|
end;
|
|
end;
|
|
|
|
{ TCommonPIDLManager }
|
|
|
|
procedure TCommonPIDLList.SetLocalPIDLMgr(const Value: TCommonPIDLManager);
|
|
begin
|
|
if Value <> FLocalPIDLMgr then
|
|
begin
|
|
if not OwnsPIDLMgr then
|
|
FreeAndNil(FLocalPIDLMgr);
|
|
OwnsPIDLMgr := False;
|
|
FLocalPIDLMgr := Value;
|
|
end
|
|
end;
|
|
|
|
// Routines to do most anything you would want to do with a PIDL
|
|
|
|
function TCommonPIDLManager.AppendPIDL(DestPIDL, SrcPIDL: PItemIDList): PItemIDList;
|
|
// Returns the concatination of the two PIDLs. Neither passed PIDLs are
|
|
// freed so it is up to the caller to free them.
|
|
var
|
|
DestPIDLSize, SrcPIDLSize: integer;
|
|
begin
|
|
DestPIDLSize := 0;
|
|
SrcPIDLSize := 0;
|
|
// Appending a PIDL to the DesktopPIDL is invalid so don't allow it.
|
|
if Assigned(DestPIDL) then
|
|
if not IsDesktopFolder(DestPIDL) then
|
|
DestPIDLSize := PIDLSize(DestPIDL) - SizeOf(DestPIDL^.mkid.cb);
|
|
|
|
if Assigned(SrcPIDL) then
|
|
SrcPIDLSize := PIDLSize(SrcPIDL);
|
|
|
|
Result := FMalloc.Alloc(DestPIDLSize + SrcPIDLSize);
|
|
if Assigned(Result) then
|
|
begin
|
|
if Assigned(DestPIDL) and (DestPIDLSize > 0) then
|
|
CopyMemory(Result, DestPIDL, DestPIDLSize);
|
|
if Assigned(SrcPIDL) and (SrcPIDLSize > 0) then
|
|
CopyMemory(Pchar(Result) + DestPIDLSize, SrcPIDL, SrcPIDLSize);
|
|
end;
|
|
end;
|
|
|
|
function TCommonPIDLManager.BindToParent(AbsolutePIDL: PItemIDList; var Folder: IShellFolder): Boolean;
|
|
var
|
|
Desktop: IShellFolder;
|
|
Last_CB: Word;
|
|
LastID: PItemIDList;
|
|
begin
|
|
SHGetDesktopFolder(Desktop);
|
|
if PIDLMgr.IDCount(AbsolutePIDL) = 1 then
|
|
begin
|
|
Folder := Desktop;
|
|
Result := True
|
|
end else
|
|
begin
|
|
StripLastID(AbsolutePIDL, Last_CB, LastID);
|
|
try
|
|
Result := Succeeded(Desktop.BindToObject(AbsolutePIDL, nil, IShellFolder, Pointer(Folder)))
|
|
finally
|
|
LastID.mkid.cb := Last_CB
|
|
end
|
|
end
|
|
end;
|
|
|
|
function TCommonPIDLManager.CopyPIDL(APIDL: PItemIDList): PItemIDList;
|
|
// Copies the PIDL and returns a newly allocated PIDL. It is not associated
|
|
// with any instance of TCoolPIDLManager so it may be assigned to any instance.
|
|
var
|
|
Size: integer;
|
|
begin
|
|
if Assigned(APIDL) then
|
|
begin
|
|
Size := PIDLSize(APIDL);
|
|
Result := FMalloc.Alloc(Size);
|
|
if Result <> nil then
|
|
CopyMemory(Result, APIDL, Size);
|
|
end else
|
|
Result := nil
|
|
end;
|
|
|
|
constructor TCommonPIDLManager.Create;
|
|
begin
|
|
inherited Create;
|
|
if SHGetMalloc(FMalloc) = E_FAIL then
|
|
fail
|
|
end;
|
|
|
|
destructor TCommonPIDLManager.Destroy;
|
|
begin
|
|
FMalloc := nil;
|
|
inherited
|
|
end;
|
|
|
|
function TCommonPIDLManager.EqualPIDL(PIDL1, PIDL2: PItemIDList): Boolean;
|
|
begin
|
|
if Assigned(PIDL1) and Assigned(PIDL2) then
|
|
Result := Boolean( ILIsEqual(PIDL1, PIDL2))
|
|
else
|
|
Result := False
|
|
end;
|
|
|
|
procedure TCommonPIDLManager.FreeOLEStr(OLEStr: LPWSTR);
|
|
// Frees an OLE string created by the Shell; as in StrRet
|
|
begin
|
|
FMalloc.Free(OLEStr)
|
|
end;
|
|
|
|
procedure TCommonPIDLManager.FreePIDL(PIDL: PItemIDList);
|
|
// Frees the PIDL using the shell memory allocator
|
|
begin
|
|
if Assigned(PIDL) then
|
|
FMalloc.Free(PIDL)
|
|
end;
|
|
|
|
function TCommonPIDLManager.CopyLastID(IDList: PItemIDList): PItemIDList;
|
|
// Returns a copy of the last PID in the list
|
|
var
|
|
Count, i: integer;
|
|
PIDIndex: PItemIDList;
|
|
begin
|
|
PIDIndex := IDList;
|
|
Count := IDCount(IDList);
|
|
if Count > 1 then
|
|
for i := 0 to Count - 2 do
|
|
PIDIndex := NextID(PIDIndex);
|
|
Result := CopyPIDL(PIDIndex);
|
|
end;
|
|
|
|
function TCommonPIDLManager.GetPointerToLastID(IDList: PItemIDList): PItemIDList;
|
|
// Return a pointer to the last PIDL in the complex PIDL passed to it.
|
|
// Useful to overlap an Absolute complex PIDL with the single level
|
|
// Relative PIDL.
|
|
var
|
|
Count, i: integer;
|
|
PIDIndex: PItemIDList;
|
|
begin
|
|
if Assigned(IDList) then
|
|
begin
|
|
PIDIndex := IDList;
|
|
Count := IDCount(IDList);
|
|
if Count > 1 then
|
|
for i := 0 to Count - 2 do
|
|
PIDIndex := NextID(PIDIndex);
|
|
Result := PIDIndex;
|
|
end else
|
|
Result := nil
|
|
end;
|
|
|
|
function TCommonPIDLManager.IDCount(APIDL: PItemIDList): integer;
|
|
// Counts the number of Simple PIDLs contained in a Complex PIDL.
|
|
var
|
|
Next: PItemIDList;
|
|
begin
|
|
Result := 0;
|
|
Next := APIDL;
|
|
if Assigned(Next) then
|
|
begin
|
|
while Next^.mkid.cb <> 0 do
|
|
begin
|
|
Inc(Result);
|
|
Next := NextID(Next);
|
|
end
|
|
end
|
|
end;
|
|
|
|
function TCommonPIDLManager.IsDesktopFolder(APIDL: PItemIDList): Boolean;
|
|
// Tests the passed PIDL to see if it is the root Desktop Folder
|
|
begin
|
|
if Assigned(APIDL) then
|
|
Result := APIDL.mkid.cb = 0
|
|
else
|
|
Result := False
|
|
end;
|
|
|
|
function TCommonPIDLManager.NextID(APIDL: PItemIDList): PItemIDList;
|
|
// Returns a pointer to the next Simple PIDL in a Complex PIDL.
|
|
begin
|
|
Result := APIDL;
|
|
Inc(PChar(Result), APIDL^.mkid.cb);
|
|
end;
|
|
|
|
function TCommonPIDLManager.PIDLSize(APIDL: PItemIDList): integer;
|
|
// Returns the total Memory in bytes the PIDL occupies.
|
|
begin
|
|
Result := 0;
|
|
if Assigned(APIDL) then
|
|
begin
|
|
Result := SizeOf( Word); // add the null terminating last ItemID
|
|
while APIDL.mkid.cb <> 0 do
|
|
begin
|
|
Result := Result + APIDL.mkid.cb;
|
|
APIDL := NextID(APIDL);
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
function TCommonPIDLManager.LoadFromStream(Stream: TStream): PItemIDList;
|
|
// Loads the PIDL from a Stream
|
|
var
|
|
Size: integer;
|
|
begin
|
|
Result := nil;
|
|
if Assigned(Stream) then
|
|
begin
|
|
Stream.ReadBuffer(Size, SizeOf(Integer));
|
|
if Size > 0 then
|
|
begin
|
|
Result := FMalloc.Alloc(Size);
|
|
Stream.ReadBuffer(Result^, Size);
|
|
end
|
|
end
|
|
end;
|
|
|
|
function TCommonPIDLManager.StringToPIDL(PIDLStr: string): PItemIDList;
|
|
var
|
|
P: PChar;
|
|
begin
|
|
Result := FMalloc.Alloc(Length(PIDLStr));
|
|
P := @PIDLStr[1];
|
|
Move(P^, Result^, Length(PIDLStr));
|
|
end;
|
|
|
|
function TCommonPIDLManager.StripLastID(IDList: PItemIDList): PItemIDList;
|
|
// Removes the last PID from the list. Returns the same, shortened, IDList passed
|
|
// to the function
|
|
var
|
|
MarkerID: PItemIDList;
|
|
begin
|
|
Result := IDList;
|
|
MarkerID := IDList;
|
|
if Assigned(IDList) then
|
|
begin
|
|
while IDList.mkid.cb <> 0 do
|
|
begin
|
|
MarkerID := IDList;
|
|
IDList := NextID(IDList);
|
|
end;
|
|
MarkerID.mkid.cb := 0;
|
|
end;
|
|
end;
|
|
|
|
procedure TCommonPIDLManager.SaveToStream(Stream: TStream; PIDL: PItemIdList);
|
|
// Saves the PIDL from a Stream
|
|
var
|
|
Size: Integer;
|
|
begin
|
|
Size := PIDLSize(PIDL);
|
|
Stream.WriteBuffer(Size, SizeOf(Size));
|
|
Stream.WriteBuffer(PIDL^, Size);
|
|
end;
|
|
|
|
|
|
function TCommonPIDLManager.StripLastID(IDList: PItemIDList; var Last_CB: Word;
|
|
var LastID: PItemIDList): PItemIDList;
|
|
// Strips the last ID but also returns the pointer to where the last CB was and the
|
|
// value that was there before setting it to 0 to shorten the PIDL. All that is necessary
|
|
// is to do a LastID^ := Last_CB.mkid.cb to return the PIDL to its previous state. Used to
|
|
// temporarily strip the last ID of a PIDL
|
|
var
|
|
MarkerID: PItemIDList;
|
|
begin
|
|
Last_CB := 0;
|
|
LastID := nil;
|
|
Result := IDList;
|
|
MarkerID := IDList;
|
|
if Assigned(IDList) then
|
|
begin
|
|
while IDList.mkid.cb <> 0 do
|
|
begin
|
|
MarkerID := IDList;
|
|
IDList := NextID(IDList);
|
|
end;
|
|
Last_CB := MarkerID.mkid.cb;
|
|
LastID := MarkerID;
|
|
MarkerID.mkid.cb := 0;
|
|
end;
|
|
end;
|
|
|
|
function TCommonPIDLManager.IsSubPIDL(FullPIDL, SubPIDL: PItemIDList): Boolean;
|
|
// Tests to see if the SubPIDL can be expanded into the passed FullPIDL
|
|
var
|
|
i, PIDLLen, SubPIDLLen: integer;
|
|
PIDL: PItemIDList;
|
|
OldCB: Word;
|
|
begin
|
|
Result := False;
|
|
if Assigned(FullPIDL) and Assigned(SubPIDL) then
|
|
begin
|
|
SubPIDLLen := IDCount(SubPIDL);
|
|
PIDLLen := IDCount(FullPIDL);
|
|
if SubPIDLLen <= PIDLLen then
|
|
begin
|
|
PIDL := FullPIDL;
|
|
for i := 0 to SubPIDLLen - 1 do
|
|
PIDL := NextID(PIDL);
|
|
OldCB := PIDL.mkid.cb;
|
|
PIDL.mkid.cb := 0;
|
|
try
|
|
Result := ILIsEqual(FullPIDL, SubPIDL);
|
|
finally
|
|
PIDL.mkid.cb := OldCB
|
|
end
|
|
end
|
|
end
|
|
end;
|
|
|
|
procedure TCommonPIDLManager.FreeAndNilPIDL(var PIDL: PItemIDList);
|
|
var
|
|
OldPIDL: PItemIDList;
|
|
begin
|
|
OldPIDL := PIDL;
|
|
PIDL := nil;
|
|
FreePIDL(OldPIDL)
|
|
end;
|
|
|
|
function TCommonPIDLManager.AllocStrGlobal(SourceStr: WideString): POleStr;
|
|
begin
|
|
Result := Malloc.Alloc((Length(SourceStr) + 1) * 2); // Add the null
|
|
if Result <> nil then
|
|
CopyMemory(Result, PWideChar(SourceStr), (Length(SourceStr) + 1) * 2);
|
|
end;
|
|
|
|
procedure TCommonPIDLManager.ParsePIDL(AbsolutePIDL: PItemIDList; var PIDLList: TCommonPIDLList;
|
|
AllAbsolutePIDLs: Boolean);
|
|
// Parses the AbsolutePIDL in to its single level PIDLs, if AllAbsolutePIDLs is true
|
|
// then each item is not a single level PIDL but an AbsolutePIDL but walking from the
|
|
// Desktop up to the passed AbsolutePIDL
|
|
var
|
|
OldCB: Word;
|
|
Head, Tail: PItemIDList;
|
|
begin
|
|
Head := AbsolutePIDL;
|
|
Tail := Head;
|
|
if Assigned(PIDLList) and Assigned(Head) then
|
|
begin
|
|
while Tail.mkid.cb <> 0 do
|
|
begin
|
|
Tail := NextID(Tail);
|
|
OldCB := Tail.mkid.cb;
|
|
try
|
|
Tail.mkid.cb := 0;
|
|
PIDLList.Add(CopyPIDL(Head));
|
|
finally
|
|
Tail.mkid.cb := OldCB;
|
|
end;
|
|
if not AllAbsolutePIDLs then
|
|
Head := Tail
|
|
end
|
|
end
|
|
end;
|
|
|
|
procedure LoadShell32Functions;
|
|
begin
|
|
ShellDLL := GetModuleHandle(PChar(Shell32));
|
|
if ShellDLL = 0 then
|
|
begin
|
|
ShellDLL := LoadLibrary(PChar(Shell32));
|
|
FreeShellLib := True;
|
|
end;
|
|
if ShellDll <> 0 then
|
|
begin
|
|
ILIsEqual := GetProcAddress(ShellDLL, PChar(21));
|
|
ILIsParent := GetProcAddress(ShellDLL, PChar(23));
|
|
end
|
|
end;
|
|
|
|
{ TCommonMemoryStream}
|
|
function TCommonMemoryStreamHelper.ReadBoolean(S: TStream): Boolean;
|
|
begin
|
|
S.Read(Result, SizeOf(Result));
|
|
end;
|
|
|
|
function TCommonMemoryStreamHelper.ReadColor(S: TStream): TColor;
|
|
begin
|
|
S.Read(Result, SizeOf(Result));
|
|
end;
|
|
|
|
function TCommonMemoryStreamHelper.ReadInt64(S: TStream): Int64;
|
|
begin
|
|
S.Read(Result, SizeOf(Result));
|
|
end;
|
|
|
|
function TCommonMemoryStreamHelper.ReadInteger(S: TStream): Integer;
|
|
begin
|
|
S.Read(Result, SizeOf(Result))
|
|
end;
|
|
|
|
function TCommonMemoryStreamHelper.ReadString(S: TStream): string;
|
|
var
|
|
i: Integer;
|
|
begin
|
|
i := ReadInteger(S);
|
|
SetLength(Result, i);
|
|
S.Read(PChar(Result)^, i);
|
|
end;
|
|
|
|
function TCommonMemoryStreamHelper.ReadWideString(S: TStream): WideString;
|
|
var
|
|
i: Integer;
|
|
begin
|
|
i := ReadInteger(S);
|
|
SetLength(Result, i);
|
|
S.Read(PWideChar(Result)^, i * 2);
|
|
end;
|
|
|
|
function TCommonMemoryStreamHelper.ReadExtended(S: TStream): Extended;
|
|
begin
|
|
S.Read(Result, SizeOf(Result))
|
|
end;
|
|
|
|
procedure TCommonMemoryStreamHelper.ReadStream(SourceStream, TargetStream: TStream);
|
|
var
|
|
Len: Integer;
|
|
X: array of Byte;
|
|
begin
|
|
TargetStream.Size := 0;
|
|
SourceStream.Read(Len, SizeOf(Len));
|
|
if Len > 0 then
|
|
begin
|
|
SetLength(X, Len);
|
|
SourceStream.Read(X[0], Len);
|
|
TargetStream.Write(X[0], Len);
|
|
end
|
|
end;
|
|
|
|
{
|
|
|
|
Needs to be modified for D5 and D4
|
|
|
|
procedure TCommonMemoryStreamHelper.ReadPublishedProperties(S: TStream; Instance: TObject; RecurseSubClasses: Boolean);
|
|
var
|
|
TypeInfo: PTypeInfo;
|
|
TypeData: PTypeData;
|
|
PropList: PPropList;
|
|
i: Integer;
|
|
Obj: TObject;
|
|
begin
|
|
if Assigned(Instance) then
|
|
begin
|
|
TypeInfo := PTypeInfo(Instance.ClassInfo);
|
|
TypeData := GetTypeData(TypeInfo);
|
|
GetMem(PropList, TypeData.PropCount * SizeOf(Pointer));
|
|
try
|
|
GetPropInfos(TypeInfo, PropList);
|
|
for i := 0 to TypeData.PropCount - 1 do
|
|
begin
|
|
case PropList[i].PropType^^.Kind of
|
|
tkClass:
|
|
begin
|
|
if RecurseSubClasses then
|
|
begin
|
|
Obj := GetObjectProp(Instance, PropList[i]);
|
|
ReadPublishedProperties(S, Obj, RecurseSubClasses);
|
|
end
|
|
end;
|
|
tkInteger, tkChar, tkWChar, tkEnumeration, tkSet:
|
|
begin
|
|
SetOrdProp(Instance, PropList[i], ReadInteger(S));
|
|
end;
|
|
tkFloat:
|
|
begin
|
|
SetFloatProp(Instance, PropList[i], ReadExtended(S));
|
|
end;
|
|
tkString:
|
|
begin
|
|
SetStrProp(Instance, PropList[i], ReadString(S));
|
|
end;
|
|
tkWString, tkLString:
|
|
begin
|
|
// It looks like the VCL messes this up completely.
|
|
SetWideStrProp(Instance, PropList[i], ReadWideString(S));
|
|
end;
|
|
tkInt64:
|
|
begin
|
|
SetInt64Prop(Instance, PropList[i], ReadInt64(S));
|
|
end;
|
|
end
|
|
end;
|
|
finally
|
|
FreeMem(PropList);
|
|
end
|
|
end
|
|
end;
|
|
}
|
|
procedure TCommonMemoryStreamHelper.WriteBoolean(S: TStream; Value: Boolean);
|
|
begin
|
|
S.Write(Value, SizeOf(Value))
|
|
end;
|
|
|
|
procedure TCommonMemoryStreamHelper.WriteColor(S: TStream; Value: TColor);
|
|
begin
|
|
S.Write(Value, SizeOf(Value))
|
|
end;
|
|
|
|
procedure TCommonMemoryStreamHelper.WriteExtended(S: TStream; Value: Extended);
|
|
begin
|
|
S.Write(Value, SizeOf(Value))
|
|
end;
|
|
|
|
procedure TCommonMemoryStreamHelper.WriteInt64(S: TStream; Value: Int64);
|
|
begin
|
|
S.Write(Value, SizeOf(Value))
|
|
end;
|
|
|
|
procedure TCommonMemoryStreamHelper.WriteInteger(S: TStream; Value: Integer);
|
|
begin
|
|
S.Write(Value, SizeOf(Value))
|
|
end;
|
|
|
|
procedure TCommonMemoryStreamHelper.WriteStream(SourceStream,
|
|
TargetStream: TStream);
|
|
var
|
|
Len: Integer;
|
|
X: array of Byte;
|
|
begin
|
|
Len := SourceStream.Size;
|
|
TargetStream.Write(Len, SizeOf(Len));
|
|
if Len > 0 then
|
|
begin
|
|
SetLength(X, Len);
|
|
SourceStream.Seek(0, 0);
|
|
SourceStream.Read(X[0], Len);
|
|
TargetStream.Write(X[0], Len);
|
|
end
|
|
end;
|
|
|
|
{
|
|
|
|
Needs to be modified for D5 and D4
|
|
|
|
procedure TCommonMemoryStreamHelper.WritePublishedProperties(S: TStream; Instance: TObject; RecurseSubClasses: Boolean);
|
|
var
|
|
TypeInfo: PTypeInfo;
|
|
TypeData: PTypeData;
|
|
PropList: PPropList;
|
|
i: Integer;
|
|
begin
|
|
if Assigned(Instance) then
|
|
begin
|
|
TypeInfo := PTypeInfo(Instance.ClassInfo);
|
|
TypeData := GetTypeData(TypeInfo);
|
|
GetMem(PropList, TypeData.PropCount * SizeOf(Pointer));
|
|
try
|
|
GetPropInfos(TypeInfo, PropList);
|
|
for i := 0 to TypeData.PropCount - 1 do
|
|
begin
|
|
case PropList[i].PropType^^.Kind of
|
|
tkClass:
|
|
begin
|
|
if RecurseSubClasses then
|
|
WritePublishedProperties(S, GetObjectProp(Instance, PropList[i].Name), RecurseSubClasses);
|
|
end;
|
|
tkInteger, tkChar, tkWChar, tkEnumeration, tkSet:
|
|
begin
|
|
WriteInteger(S, GetOrdProp(Instance, PropList[i]))
|
|
end;
|
|
tkFloat:
|
|
begin
|
|
WriteExtended(S, GetFloatProp(Instance, PropList[i]))
|
|
end;
|
|
tkString:
|
|
begin
|
|
WriteString(S, GetStrProp(Instance, PropList[i]))
|
|
end;
|
|
tkWString, tkLString:
|
|
begin
|
|
WriteWideString(S, GetWideStrProp(Instance, PropList[i]));
|
|
end;
|
|
tkInt64:
|
|
begin
|
|
WriteInt64(S, GetInt64Prop(Instance, PropList[i]))
|
|
end;
|
|
end
|
|
end;
|
|
finally
|
|
FreeMem(PropList);
|
|
end
|
|
end
|
|
end;
|
|
}
|
|
|
|
procedure TCommonMemoryStreamHelper.WriteString(S: TStream; Value: string);
|
|
begin
|
|
WriteInteger(S, Length(Value));
|
|
S.Write(PChar(Value)^, Length(Value))
|
|
end;
|
|
|
|
procedure TCommonMemoryStreamHelper.WriteWideString(S: TStream; Value: WideString);
|
|
begin
|
|
WriteInteger(S, Length(Value));
|
|
S.Write(PWideChar(Value)^, Length(Value) * 2)
|
|
end;
|
|
|
|
{$IFDEF USETHEMES}
|
|
{ TCommonThemeManager }
|
|
constructor TCommonThemeManager.Create(AnOwner: TWinControl);
|
|
begin
|
|
inherited Create;
|
|
FOwner := AnOwner;
|
|
end;
|
|
|
|
destructor TCommonThemeManager.Destroy;
|
|
begin
|
|
ThemesFree;
|
|
inherited;
|
|
end;
|
|
|
|
procedure TCommonThemeManager.ThemesFree;
|
|
begin
|
|
FLoaded := False;
|
|
if FButtonTheme <> 0 then
|
|
CloseThemeData(FButtonTheme);
|
|
FButtonTheme := 0;
|
|
if FListviewTheme <> 0 then
|
|
CloseThemeData(FListviewTheme);
|
|
FListviewTheme := 0;
|
|
if FHeaderTheme <> 0 then
|
|
CloseThemeData(FHeaderTheme);
|
|
FHeaderTheme := 0;
|
|
if FTreeviewTheme <> 0 then
|
|
CloseThemeData(FTreeviewTheme);
|
|
FTreeviewTheme := 0;
|
|
if FExplorerBarTheme <> 0 then
|
|
CloseThemeData(FExplorerBarTheme);
|
|
FExplorerBarTheme := 0;
|
|
if FComboBoxTheme <> 0 then
|
|
CloseThemeData(FComboBoxTheme);
|
|
FComboBoxTheme := 0;
|
|
if FEditTheme <> 0 then
|
|
CloseThemeData(FEditTheme);
|
|
FEditTheme := 0;
|
|
if FRebarTheme <> 0 then
|
|
CloseThemeData(FRebarTheme);
|
|
FRebarTheme := 0;
|
|
if FWindowTheme <> 0 then
|
|
CloseThemeData(FWindowTheme);
|
|
FWindowTheme := 0;
|
|
if FTaskBandTheme <> 0 then
|
|
CloseThemeData(FTaskBandTheme);
|
|
FTaskBandTheme := 0;
|
|
if FTaskBarTheme <> 0 then
|
|
CloseThemeData(FTaskBarTheme);
|
|
FTaskBarTheme := 0;
|
|
if FScrollbarTheme <> 0 then
|
|
CloseThemeData(FScrollbarTheme);
|
|
FScrollbarTheme := 0;
|
|
if FProgressTheme <> 0 then
|
|
CloseThemeData(FProgressTheme);
|
|
FProgressTheme := 0;
|
|
end;
|
|
|
|
procedure TCommonThemeManager.ThemesLoad;
|
|
begin
|
|
InitThemeLibrary;
|
|
if Owner.HandleAllocated then
|
|
begin
|
|
if UseThemes then
|
|
begin
|
|
ThemesFree;
|
|
FButtonTheme := OpenThemeData(Owner.Handle, 'button');
|
|
FListviewTheme := OpenThemeData(Owner.Handle, 'listview');
|
|
FHeaderTheme := OpenThemeData(Owner.Handle, 'header');
|
|
FTreeviewTheme := OpenThemeData(Owner.Handle, 'treeview');
|
|
FExplorerBarTheme := OpenThemeData(Owner.Handle, 'explorerbar');
|
|
FComboBoxTheme := OpenThemeData(Owner.Handle, 'combobox');
|
|
FEditTheme := OpenThemeData(Owner.Handle, 'edit');
|
|
FRebarTheme := OpenThemeData(Owner.Handle, 'rebar');
|
|
FWindowTheme := OpenThemeData(Owner.Handle, 'window');
|
|
FTaskBandTheme := OpenThemeData(Owner.Handle, 'taskband');
|
|
FTaskBarTheme := OpenThemeData(Owner.Handle, 'taskbar');
|
|
FScrollbarTheme := OpenThemeData(Owner.Handle, 'scrollbar');
|
|
FProgressTheme := OpenThemeData(Owner.Handle, 'progress');
|
|
FLoaded := True
|
|
end;
|
|
RedrawWindow(Owner.Handle, nil, 0, RDW_FRAME or RDW_INVALIDATE or RDW_NOERASE or RDW_NOCHILDREN);
|
|
end
|
|
end;
|
|
{$ENDIF USETHEMES}
|
|
|
|
|
|
|
|
{ TCommonStream}
|
|
|
|
function TCommonStream.ReadBoolean: Boolean;
|
|
begin
|
|
ReadBuffer(Result, SizeOf(Boolean))
|
|
end;
|
|
|
|
function TCommonStream.ReadByte: Byte;
|
|
begin
|
|
ReadBuffer(Result, SizeOf(Byte))
|
|
end;
|
|
|
|
function TCommonStream.ReadInteger: Integer;
|
|
begin
|
|
ReadBuffer(Result, SizeOf(Integer))
|
|
end;
|
|
|
|
function TCommonStream.ReadString: string;
|
|
var
|
|
Size: LongWord;
|
|
begin
|
|
ReadBuffer(Size, SizeOf(LongWord));
|
|
SetLength(Result, Size);
|
|
ReadBuffer(PChar(Result)^, Size)
|
|
end;
|
|
|
|
function TCommonStream.ReadStringList: TStringList;
|
|
var
|
|
i, Count: LongWord;
|
|
begin
|
|
Result := TStringList.Create;
|
|
ReadBuffer(Count, SizeOf(LongWord));
|
|
for i := 0 to Count - 1 do
|
|
Result.Add(ReadString)
|
|
end;
|
|
|
|
function TCommonStream.ReadWideString: WideString;
|
|
var
|
|
Size: LongWord;
|
|
begin
|
|
ReadBuffer(Size, SizeOf(LongWord));
|
|
SetLength(Result, Size);
|
|
ReadBuffer(PWideChar(Result)^, Size * 2)
|
|
end;
|
|
|
|
procedure TCommonStream.WriteBoolean(Value: Boolean);
|
|
begin
|
|
WriteBuffer(Value, SizeOf(Boolean))
|
|
end;
|
|
|
|
procedure TCommonStream.WriteByte(Value: Byte);
|
|
begin
|
|
WriteBuffer(Value, SizeOf(Byte))
|
|
end;
|
|
|
|
procedure TCommonStream.WriteInteger(Value: Integer);
|
|
begin
|
|
WriteBuffer(Value, SizeOf(Integer))
|
|
end;
|
|
|
|
procedure TCommonStream.WriteString(const Value: string);
|
|
var
|
|
Size: LongWord;
|
|
begin
|
|
Size := Length(Value);
|
|
WriteBuffer(Size, SizeOf(Size));
|
|
WriteBuffer(PChar(Value)^, Size);
|
|
end;
|
|
|
|
procedure TCommonStream.WriteStringList(Value: TStringList);
|
|
var
|
|
i, Count: LongWord;
|
|
begin
|
|
Count := Value.Count;
|
|
WriteBuffer(Count, SizeOf(Count));
|
|
for i := 0 to Count - 1 do
|
|
WriteString(Value[i])
|
|
end;
|
|
|
|
procedure TCommonStream.WriteWideString(const Value: WideString);
|
|
var
|
|
Size: LongWord;
|
|
begin
|
|
Size := Length(Value);
|
|
WriteBuffer(Size, SizeOf(Size));
|
|
WriteBuffer(PWideChar(Value)^, Size * 2);
|
|
end;
|
|
|
|
{ CheckBoundManager}
|
|
constructor TCommonCheckBoundManager.Create;
|
|
begin
|
|
List := TList.Create;
|
|
end;
|
|
|
|
destructor TCommonCheckBoundManager.Destroy;
|
|
begin
|
|
Clear;
|
|
FreeAndNil(FList);
|
|
end;
|
|
|
|
function TCommonCheckBoundManager.Find(Size: Integer): TCommonCheckBound;
|
|
var
|
|
i: Integer;
|
|
Done: Boolean;
|
|
begin
|
|
i := 0;
|
|
Done := False;
|
|
Result := nil;
|
|
while (i < List.Count) and not Done do
|
|
begin
|
|
if CheckBound[i].Size = Size then
|
|
begin
|
|
Done := True;
|
|
Result := CheckBound[i]
|
|
end;
|
|
Inc(i)
|
|
end
|
|
end;
|
|
|
|
function TCommonCheckBoundManager.GetBound(Size: Integer): TRect;
|
|
var
|
|
Bounds: TCommonCheckBound;
|
|
begin
|
|
Bounds := Find(Size);
|
|
if not Assigned(Bounds) then
|
|
begin
|
|
Bounds := TCommonCheckBound.Create;
|
|
List.Add(Bounds);
|
|
Bounds.Size := Size;
|
|
Bounds.Bounds := CheckBounds(Size);
|
|
end;
|
|
Result := Bounds.Bounds;
|
|
end;
|
|
|
|
function TCommonCheckBoundManager.GetCheckBound(Index: Integer): TCommonCheckBound;
|
|
begin
|
|
Result := TCommonCheckBound( List[Index])
|
|
end;
|
|
|
|
procedure TCommonCheckBoundManager.Clear;
|
|
var
|
|
i: Integer;
|
|
begin
|
|
for i := 0 to List.Count - 1 do
|
|
TObject(List[i]).Free;
|
|
List.Clear;
|
|
end;
|
|
|
|
{ TCommonSysImages }
|
|
constructor TCommonSysImages.Create(AOwner: TComponent);
|
|
begin
|
|
inherited;
|
|
ShareImages := True;
|
|
ImageSize := sisSmall;
|
|
DrawingStyle := dsTransparent
|
|
end;
|
|
|
|
destructor TCommonSysImages.Destroy;
|
|
begin
|
|
inherited;
|
|
end;
|
|
|
|
procedure TCommonSysImages.Flush;
|
|
begin
|
|
RecreateHandle
|
|
end;
|
|
|
|
procedure TCommonSysImages.RecreateHandle;
|
|
var
|
|
PIDL: PItemIDList;
|
|
Malloc: IMalloc;
|
|
FileInfo: TSHFileInfo;
|
|
Flags: Longword;
|
|
begin
|
|
Handle := 0;
|
|
if FImageSize = sisExtraLarge then
|
|
begin
|
|
if Succeeded(SHGetImageList(SHIL_EXTRALARGE, IImageList, FJumboImages)) then
|
|
Handle := THandle(FJumboImages)
|
|
else begin
|
|
Flags := SHGFI_PIDL or SHGFI_SYSICONINDEX or SHGFI_LARGEICON;
|
|
SHGetSpecialFolderLocation(0, CSIDL_DESKTOP, PIDL);
|
|
SHGetMalloc(Malloc);
|
|
Handle := SHGetFileInfo(PChar(PIDL), 0, FileInfo, SizeOf(FileInfo), Flags);
|
|
Malloc.Free(PIDL);
|
|
end
|
|
end else
|
|
begin
|
|
SHGetSpecialFolderLocation(0, CSIDL_DESKTOP, PIDL);
|
|
SHGetMalloc(Malloc);
|
|
if FImageSize = sisSmall then
|
|
Flags := SHGFI_PIDL or SHGFI_SYSICONINDEX or SHGFI_SMALLICON
|
|
else
|
|
Flags := SHGFI_PIDL or SHGFI_SYSICONINDEX or SHGFI_LARGEICON;
|
|
Handle := SHGetFileInfo(PChar(PIDL), 0, FileInfo, SizeOf(FileInfo), Flags);
|
|
Malloc.Free(PIDL);
|
|
end;
|
|
end;
|
|
|
|
procedure TCommonSysImages.SetImageSize(const Value: TSysImageListSize);
|
|
begin
|
|
FImageSize := Value;
|
|
RecreateHandle;
|
|
end;
|
|
|
|
|
|
{$IFNDEF COMPILER_7_UP}
|
|
{ TStringListEx }
|
|
|
|
function TStringListEx.GetNameValueSeparator: Char;
|
|
begin
|
|
if FNameValueSeparator = '' then
|
|
NameValueSeparator := '=';
|
|
Result := FNameValueSeparator;
|
|
end;
|
|
|
|
function TStringListEx.GetValueFromIndex(Index: Integer): string;
|
|
begin
|
|
if Index >= 0 then
|
|
Result := Copy(Get(Index), Length(Names[Index]) + 2, MaxInt) else
|
|
Result := '';
|
|
end;
|
|
|
|
procedure TStringListEx.SetNameValueSeparator(const Value: Char);
|
|
begin
|
|
if (FNameValueSeparator <> Value) then
|
|
FNameValueSeparator := Value;
|
|
end;
|
|
|
|
procedure TStringListEx.SetValueFromIndex(Index: Integer;
|
|
const Value: string);
|
|
begin
|
|
if Value <> '' then
|
|
begin
|
|
if Index < 0 then Index := Add('');
|
|
Put(Index, Names[Index] + NameValueSeparator + Value);
|
|
end
|
|
else
|
|
if Index >= 0 then Delete(Index);
|
|
end;
|
|
{$ENDIF}
|
|
|
|
initialization
|
|
LoadShell32Functions;
|
|
StreamHelper := TCommonMemoryStreamHelper.Create;
|
|
MarlettFont := TFont.Create;
|
|
MarlettFont.Name := 'marlett';
|
|
Checks := TCommonCheckBoundManager.Create;
|
|
PIDLMgr := TCommonPIDLManager.Create;
|
|
|
|
|
|
finalization
|
|
if FreeShellLib then
|
|
FreeLibrary(ShellDLL);
|
|
StreamHelper.Free;
|
|
FreeAndNil(Checks);
|
|
FreeAndNil(MarlettFont);
|
|
FLargeSysImages.Free;
|
|
FSmallSysImages.Free;
|
|
FExtraLargeSysImages.Free;
|
|
FreeAndNil(PIDLMgr);
|
|
|
|
end.
|