📄 rm_jvvcl5utils.pas
字号:
{-----------------------------------------------------------------------------
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/MPL-1.1.html
Software distributed under the License is distributed on an "AS IS" basis,
WITHOUT WARRANTY OF ANY KIND, either expressed or implied. See the License for
the specific language governing rights and limitations under the License.
The Original Code is: JvTD5Compat.pas, released on 2005-05-23.
The Initial Developer of the Original Code is Andreas Hausladen <Andreas dott Hausladen att gmx dott de>
Portions created by Andreas Hausladen are Copyright (C) 2005 Andreas Hausladen.
All Rights Reserved.
Contributor(s):
You may retrieve the latest version of this file at the Project JEDI's JVCL home page,
located at http://jvcl.sourceforge.net
Known Issues:
-----------------------------------------------------------------------------}
// $Id: JvVCL5Utils.pas,v 1.10 2006/03/10 20:35:40 ahuser Exp $
unit rm_JvVCL5Utils;
{$I rm_jvcl.inc}
interface
{$IFDEF COMPILER5}
uses
Windows, SysUtils, Classes, TypInfo, ActiveX, MultiMon, Forms, Controls,
Graphics, ImgList, WinInet;
// Classes
type
TInterfacedPersistent = class(TPersistent);
TCollectionNotification = (cnAdded, cnExtracting, cnDeleting);
TCollection = class(Classes.TCollection)
// warning: DO NOT ADD FIELDS !!!
private
function GetNextID: Integer;
protected
procedure Added(var Item: TCollectionItem); virtual; {deprecated;}
procedure Deleting(Item: TCollectionItem); virtual; {deprecated;}
property NextID: Integer read GetNextID;
procedure Notify(Item: TCollectionItem; Action: TCollectionNotification); virtual;
procedure SetItemName(Item: TCollectionItem); override;
procedure Update(Item: TCollectionItem); override;
public
constructor Create(ItemClass: TCollectionItemClass);
function Owner: TPersistent;
procedure Delete(Index: Integer);
end;
TOwnedCollection = class(Classes.TOwnedCollection)
// warning: DO NOT ADD FIELDS !!!
private
function GetNextID: Integer;
protected
procedure Added(var Item: TCollectionItem); virtual; {deprecated;}
procedure Deleting(Item: TCollectionItem); virtual; {deprecated;}
property NextID: Integer read GetNextID;
procedure Notify(Item: TCollectionItem; Action: TCollectionNotification); virtual;
procedure SetItemName(Item: Classes.TCollectionItem); override;
public
constructor Create(AOwner: TPersistent; ItemClass: TCollectionItemClass);
function Owner: TPersistent;
procedure Delete(Index: Integer);
end;
function GetRelocAddress(ProcAddress: Pointer): Pointer;
function InstallProcHook(ProcAddress, HookProc, OrgCallProc: Pointer): Boolean;
function UninstallProcHook(OrgCallProc: Pointer): Boolean;
function AllocateHWnd(Method: TWndMethod): HWND;
procedure DeallocateHWnd(Wnd: HWND);
// SysUtils
const
PathDelim = '\';
DriveDelim = ';';
sLineBreak = #13#10;
function TryStrToInt(const S: string; out Value: Integer): Boolean;
function TryStrToDateTime(const S: string; out Date: TDateTime): Boolean;
function StrToDateTimeDef(const S: string; Default: TDateTime): TDateTime;
function StrToDateDef(const S: string; Default: TDateTime): TDateTime;
// function StrToFloatDef(const Str: string; Default: Extended): Extended;
procedure RaiseLastOSError;
function IncludeTrailingPathDelimiter(const APath: string): string;
function ExcludeTrailingPathDelimiter(const APath: string): string;
function DirectoryExists(const Name: string): Boolean;
function ForceDirectories(Dir: string): Boolean;
function SameFileName(const FN1, FN2: string): Boolean;
function GetEnvironmentVariable(const Name: string): string;
function Supports(Instance: TObject; const Intf: TGUID): Boolean; overload;
function Supports(AClass: TClass; const Intf: TGUID): Boolean; overload;
function FileIsReadOnly(const FileName: string): Boolean;
function WideCompareText(const S1, S2: WideString): Integer;
function WideUpperCase(const S: WideString): WideString;
function WideLowerCase(const S: WideString): WideString;
function CompareDateTime(const A, B: TDateTime): Integer;
// StrUtils
function AnsiStartsText(const SubText, Text: string): Boolean;
function AnsiEndsText(const SubText, Text: string): Boolean;
function AnsiStartsStr(const SubStr, Str: string): Boolean;
function AnsiEndsStr(const SubStr, Str: string): Boolean;
// Math
type
TValueSign = -1..1;
const
NegativeValue = Low(TValueSign);
ZeroValue = 0;
PositiveValue = High(TValueSign);
function Sign(const AValue: Integer): TValueSign; overload;
function Sign(const AValue: Int64): TValueSign; overload;
function Sign(const AValue: Double): TValueSign; overload;
// Variants
type
TVariantRelationship = (vrEqual, vrLessThan, vrGreaterThan, vrNotEqual);
function FindVarData(const V: Variant): PVarData;
function VarIsStr(const V: Variant): Boolean;
function VarIsType(const V: Variant; AVarType: TVarType): Boolean;
function VarCompareValue(const A, B: Variant): TVariantRelationship;
// Misc
function GetMonitorWorkareaRect(Monitor: TMonitor): TRect;
type
UTF8String = type string;
// System
type
TVarType = Word;
PPointer = ^Pointer;
// Controls
type
TTime = type TDateTime;
{$EXTERNALSYM TTime}
TDate = type TDateTime;
{$EXTERNALSYM TDate}
// Controls
// obones 2005/10/30: Commented out as it clashes in C++ Builder 5 at least.
// Symptoms are a message saying "Cannot load JvStdCtrlsC5D, a class named
// 'TCustomImageList' is already registered.".
// As it seems no one is using the new Draw method, there is no harm done.
{type
TCustomImageList = class(ImgList.TCustomImageList)
// warning: DO NOT ADD FIELDS !!!
public
procedure Draw(Canvas: TCanvas; X, Y, Index: Integer;
ADrawingStyle: TDrawingStyle; AImageType: TImageType;
Enabled: Boolean); overload;
end;}
// Grid
type
TEditStyle = (esSimple, esEllipsis, esPickList);
// DateUtils
function IncYear(const AValue: TDateTime; const ANumberOfYears: Integer): TDateTime;
// Graphics
const
clCream = TColor($F0FBFF);
// WinInet
function FtpGetFileSize(hFile: HINTERNET; lpdwFileSizeHigh: LPDWORD): DWORD; stdcall;
{$ENDIF COMPILER5}
{$IFNDEF COMPILER7_UP}
// For Delphi 5 / BCB 5 and those who will not install Delphi 6 Update 2
// Windows
const
{$EXTERNALSYM SPI_GETMENUSHOWDELAY}
SPI_GETMENUSHOWDELAY = 106;
{$EXTERNALSYM SPI_SETMENUSHOWDELAY}
SPI_SETMENUSHOWDELAY = 107;
{$EXTERNALSYM SPI_GETMENUFADE}
SPI_GETMENUFADE = $1012;
{$EXTERNALSYM SPI_SETMENUFADE}
SPI_SETMENUFADE = $1013;
{$EXTERNALSYM SPI_GETSELECTIONFADE}
SPI_GETSELECTIONFADE = $1014;
{$EXTERNALSYM SPI_SETSELECTIONFADE}
SPI_SETSELECTIONFADE = $1015;
{$EXTERNALSYM SPI_GETTOOLTIPANIMATION}
SPI_GETTOOLTIPANIMATION = $1016;
{$EXTERNALSYM SPI_SETTOOLTIPANIMATION}
SPI_SETTOOLTIPANIMATION = $1017;
{$EXTERNALSYM SPI_GETTOOLTIPFADE}
SPI_GETTOOLTIPFADE = $1018;
{$EXTERNALSYM SPI_SETTOOLTIPFADE}
SPI_SETTOOLTIPFADE = $1019;
{$EXTERNALSYM SPI_GETCURSORSHADOW}
SPI_GETCURSORSHADOW = $101A;
{$EXTERNALSYM SPI_SETCURSORSHADOW}
SPI_SETCURSORSHADOW = $101B;
{$EXTERNALSYM SPI_GETUIEFFECTS}
SPI_GETUIEFFECTS = $103E;
{$EXTERNALSYM SPI_SETUIEFFECTS}
SPI_SETUIEFFECTS = $103F;
{$EXTERNALSYM COLOR_MENUHILIGHT}
COLOR_MENUHILIGHT = 29;
{$EXTERNALSYM COLOR_MENUBAR}
COLOR_MENUBAR = 30;
{$EXTERNALSYM SPI_GETKEYBOARDCUES}
SPI_GETKEYBOARDCUES = $100A;
{$EXTERNALSYM SPI_SETKEYBOARDCUES}
SPI_SETKEYBOARDCUES = $100B;
{$ENDIF !COMPILER7_UP}
implementation
{$IFDEF COMPILER5}
uses
CommCtrl;
var
GlobalCollectionHooked: Boolean = False;
type
TPrivateCollection = class(TPersistent)
public
FItemClass: TCollectionItemClass;
FItems: TList;
FUpdateCount: Integer;
FNextID: Integer; // <-- we are interested in this field
end;
TPrivateCollectionItem = class(TPersistent)
public
FCollection: TCollection;
end;
TPublishedCollectionItem = class(TCollectionItem)
published
property Collection;
end;
procedure OrgTCollection_Delete(Self: Classes.TCollection; Index: Integer);
asm
DD 0, 0, 0, 0 // 16 Bytes
end;
procedure OrgTCollectionItem_SetCollection(Self: TCollectionItem; Value: Classes.TCollection);
asm
DD 0, 0, 0, 0 // 16 Bytes
end;
procedure TCollectionItem_SetCollection(Self: TCollectionItem; Value: Classes.TCollection);
var
Col: Classes.TCollection;
begin
Col := TPrivateCollectionItem(Self).FCollection;
if Col <> Value then
begin
if Col <> nil then
begin
if Col is TCollection then
TCollection(Col).Notify(Self, cnExtracting)
else
if Col is TOwnedCollection then
TOwnedCollection(Col).Notify(Self, cnExtracting);
end;
OrgTCollectionItem_SetCollection(Self, Value);
end;
end;
procedure TCollection_Delete(Self: Classes.TCollection; Index: Integer);
begin
if Self is TOwnedCollection then
TOwnedCollection(Self).Notify(Self.Items[Index], cnDeleting)
else
if Self is TCollection then
TCollection(Self).Notify(Self.Items[Index], cnDeleting);
TCollectionItem(Self.Items[Index]).Free;
end;
procedure HookCollection;
var
Info: PPropInfo;
begin
if not GlobalCollectionHooked then
begin
GlobalCollectionHooked := True;
InstallProcHook(@Classes.TCollection.Delete, @TCollection_Delete, @OrgTCollection_Delete);
Info := GetPropInfo(TPublishedCollectionItem, 'Collection');
InstallProcHook(Info.SetProc, @TCollectionItem_SetCollection, @OrgTCollectionItem_SetCollection);
end;
end;
procedure UnhookCollection;
begin
if GlobalCollectionHooked then
begin
GlobalCollectionHooked := False;
UninstallProcHook(@OrgTCollection_Delete);
UninstallProcHook(@OrgTCollectionItem_SetCollection);
end;
end;
//=== { TCollection } ========================================================
constructor TCollection.Create(ItemClass: Classes.TCollectionItemClass);
begin
inherited Create(ItemClass);
if not GlobalCollectionHooked then
HookCollection;
end;
procedure TCollection.Added(var Item: Classes.TCollectionItem);
begin
end;
procedure TCollection.Delete(Index: Integer);
begin
Notify(TCollectionItem(Items[Index]), cnDeleting);
inherited Delete(Index);
end;
procedure TCollection.Deleting(Item: Classes.TCollectionItem);
begin
end;
function TCollection.GetNextID: Integer;
begin
Result := TPrivateCollection(Self).FNextID;
end;
procedure TCollection.Notify(Item: Classes.TCollectionItem; Action: TCollectionNotification);
begin
case Action of
cnAdded:
Added(Item);
cnDeleting:
Deleting(Item);
end;
end;
function TCollection.Owner: TPersistent;
begin
Result := GetOwner;
end;
procedure TCollection.SetItemName(Item: Classes.TCollectionItem);
begin
inherited SetItemName(Item);
Notify(TCollectionItem(Item), cnAdded);
end;
//=== { TOwnedCollection } ===================================================
constructor TOwnedCollection.Create(AOwner: TPersistent; ItemClass: TCollectionItemClass);
begin
inherited Create(AOwner, ItemClass);
if not GlobalCollectionHooked then
HookCollection;
end;
procedure TOwnedCollection.Delete(Index: Integer);
begin
Notify(TCollectionItem(Items[Index]), cnDeleting);
inherited Delete(Index);
end;
procedure TOwnedCollection.Added(var Item: Classes.TCollectionItem);
begin
end;
procedure TOwnedCollection.Deleting(Item: Classes.TCollectionItem);
begin
end;
function TOwnedCollection.GetNextID: Integer;
begin
Result := TPrivateCollection(Self).FNextID;
end;
procedure TOwnedCollection.Notify(Item: Classes.TCollectionItem; Action: TCollectionNotification);
begin
case Action of
cnAdded:
Added(Item);
cnDeleting:
Deleting(Item);
end;
end;
procedure TCollection.Update(Item: TCollectionItem);
begin
inherited Update(Item);
Notify(Item, cnAdded);
end;
function TOwnedCollection.Owner: TPersistent;
begin
Result := GetOwner;
end;
procedure TOwnedCollection.SetItemName(Item: Classes.TCollectionItem);
begin
inherited SetItemName(Item);
Notify(TCollectionItem(Item), cnAdded);
end;
function ReadProtectedMemory(Address: Pointer; var Buffer; Count: Cardinal): Boolean;
var
N: Cardinal;
begin
Result := ReadProcessMemory(GetCurrentProcess, Address, @Buffer, Count, N);
Result := Result and (N = Count);
end;
function WriteProtectedMemory(Address: Pointer; const Buffer; Count: Cardinal): Boolean;
var
N: Cardinal;
begin
Result := WriteProcessMemory(GetCurrentProcess, Address, @Buffer, Count, N);
Result := Result and (N = Count);
end;
type
TJumpCode = packed record
Jmp: Byte; // jmp Offset
Offset: Integer;
end;
TOrgCallCode = packed record
Code: array[0..SizeOf(TJumpCode) + 4] of Byte;
Jmp: Byte; // jmp Offset
Offset: Integer;
Address: Pointer;
end;
function GetRelocAddress(ProcAddress: Pointer): Pointer;
type
TRelocationRec = packed record
Jump: Word;
Address: PPointer;
end;
var
Relocation: TRelocationRec;
Data: Byte;
begin
Result := ProcAddress;
// the relocation table might be protected
if ReadProtectedMemory(ProcAddress, Data, SizeOf(Data)) then
if Data = $FF then // ProcAddress is in a DLL or package
if ReadProtectedMemory(ProcAddress, Relocation, SizeOf(Relocation)) then
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -