3100 lines
86 KiB
ObjectPascal
3100 lines
86 KiB
ObjectPascal
|
|
{-----------------------------------------------------------------------------
|
|||
|
|
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: JvUtils.PAS, released on 2002-07-04.
|
|||
|
|
|
|||
|
|
The Initial Developers of the Original Code are: Andrei Prygounkov <a dott prygounkov att gmx dott de>
|
|||
|
|
Roman Tkachev <whiteman@infa.ru>
|
|||
|
|
Copyright (c) 1999, 2002 Andrei Prygounkov, Roman Tkachev
|
|||
|
|
All Rights Reserved.
|
|||
|
|
|
|||
|
|
Contributor(s):
|
|||
|
|
|
|||
|
|
Last Modified: 2002-07-04
|
|||
|
|
|
|||
|
|
You may retrieve the latest version of this file at the Project JEDI's JVCL home page,
|
|||
|
|
located at http://jvcl.sourceforge.net
|
|||
|
|
|
|||
|
|
Description : common routines
|
|||
|
|
|
|||
|
|
Known Issues:
|
|||
|
|
* Some functions are also in JvStrUtil
|
|||
|
|
* Some russian comments were translated to english; these comments are marked
|
|||
|
|
with [translated]
|
|||
|
|
-----------------------------------------------------------------------------}
|
|||
|
|
|
|||
|
|
{$I JVCL.INC}
|
|||
|
|
{$I WINDOWSONLY.INC}
|
|||
|
|
|
|||
|
|
unit JvUtils;
|
|||
|
|
|
|||
|
|
interface
|
|||
|
|
|
|||
|
|
{$DEFINE INCLUDE_RAUTILSW}
|
|||
|
|
|
|||
|
|
uses
|
|||
|
|
Windows, Forms, Controls, Graphics, SysUtils, Classes,
|
|||
|
|
StdCtrls, ExtCtrls, Dialogs, Menus, Clipbrd,
|
|||
|
|
{$IFDEF COMPILER3_UP}
|
|||
|
|
ShlObj,
|
|||
|
|
{$ENDIF}
|
|||
|
|
{$IFDEF COMPILER3_UP}
|
|||
|
|
ActiveX,
|
|||
|
|
{$ELSE}
|
|||
|
|
Ole2,
|
|||
|
|
{$ENDIF}
|
|||
|
|
{$IFDEF COMPILER6_UP}
|
|||
|
|
Variants,
|
|||
|
|
{$ENDIF}
|
|||
|
|
TypInfo;
|
|||
|
|
|
|||
|
|
{$IFNDEF COMPILER4_UP}
|
|||
|
|
type
|
|||
|
|
Longword = Integer;
|
|||
|
|
{$ENDIF}
|
|||
|
|
|
|||
|
|
type
|
|||
|
|
TTickCount = Cardinal;
|
|||
|
|
|
|||
|
|
{**** string handling routines}
|
|||
|
|
|
|||
|
|
const
|
|||
|
|
Separators: set of Char = [#00, ' ', '-', #13, #10, '.', ',', '/', '\', '#', '"', '''',
|
|||
|
|
':', '+', '%', '*', '(', ')', ';', '=', '{', '}', '[', ']', '{', '}', '<', '>'];
|
|||
|
|
{const Separators is used in GetWordOnPos, JvUtils.ReplaceStrings and SubWord}
|
|||
|
|
|
|||
|
|
{$IFDEF DELPHI}
|
|||
|
|
type
|
|||
|
|
TSetOfChar = set of Char;
|
|||
|
|
{$ENDIF DELPHI}
|
|||
|
|
{$IFDEF BCB}
|
|||
|
|
type
|
|||
|
|
TSetOfChar = string;
|
|||
|
|
{$ENDIF BCB}
|
|||
|
|
|
|||
|
|
{ GetWordOnPos returns Word from string, S, on the cursor position, P}
|
|||
|
|
function GetWordOnPos(const S: string; const P: Integer): string;
|
|||
|
|
{ GetWordOnPosEx working like GetWordOnPos function, but
|
|||
|
|
also returns Word position in iBeg, iEnd variables }
|
|||
|
|
function GetWordOnPosEx(const S: string; const P: Integer; var iBeg, iEnd: Integer): string;
|
|||
|
|
{ SubStr returns substring from string, S, separated with Separator string}
|
|||
|
|
function SubStr(const S: string; const Index: Integer; const Separator: string): string;
|
|||
|
|
{ SubStrEnd same to previous function but Index numerated from the end of string }
|
|||
|
|
function SubStrEnd(const S: string; const Index: Integer; const Separator: string): string;
|
|||
|
|
{ SubWord returns next Word from string, P, and offsets Pointer to the end of Word, P2 }
|
|||
|
|
function SubWord(P: PChar; var P2: PChar): string;
|
|||
|
|
{ NumberByWord returns the text representation of
|
|||
|
|
the number, N, in normal russian language. Was typed from Monitor magazine }
|
|||
|
|
function NumberByWord(const N: Longint): string;
|
|||
|
|
// function CurrencyByWord(Value : Currency) : string;
|
|||
|
|
{ GetLineByPos returns the Line number, there
|
|||
|
|
the symbol Pos is pointed. Lines separated with #13 symbol }
|
|||
|
|
function GetLineByPos(const S: string; const Pos: Integer): Integer;
|
|||
|
|
{ GetXYByPos is same to previous function, but returns X position in line too}
|
|||
|
|
procedure GetXYByPos(const S: string; const Pos: Integer; var X, Y: Integer);
|
|||
|
|
{ ReplaceString searches for all substrings, OldPattern,
|
|||
|
|
in a string, S, and replaces them with NewPattern }
|
|||
|
|
function ReplaceString(S: string; const OldPattern, NewPattern: string): string;
|
|||
|
|
{ ConcatSep concatenate S and S2 strings with Separator.
|
|||
|
|
if S = '', separator don't included }
|
|||
|
|
function ConcatSep(const S, S2, Separator: string): string;
|
|||
|
|
{ ConcatLeftSep is same to previous function, but
|
|||
|
|
strings concatenate right to left }
|
|||
|
|
function ConcatLeftSep(const S, S2, Separator: string): string;
|
|||
|
|
{ MinimizeString trunactes long string, S, and appends
|
|||
|
|
'...' symbols, if Length of S is more than MaxLen }
|
|||
|
|
function MinimizeString(const S: string; const MaxLen: Integer): string;
|
|||
|
|
{ Next 4 function for russian chars transliterating.
|
|||
|
|
This functions are needed because Oem2Ansi and Ansi2Oem functions
|
|||
|
|
sometimes works sucks }
|
|||
|
|
procedure Dos2Win(var S: string);
|
|||
|
|
procedure Win2Dos(var S: string);
|
|||
|
|
function Dos2WinRes(const S: string): string;
|
|||
|
|
function Win2DosRes(const S: string): string;
|
|||
|
|
function Win2Koi(const S: string): string;
|
|||
|
|
{ Spaces returns string consists on N space chars }
|
|||
|
|
function Spaces(const N: Integer): string;
|
|||
|
|
{ AddSpaces add spaces to string, S, if it Length is smaller than N }
|
|||
|
|
function AddSpaces(const S: string; const N: Integer): string;
|
|||
|
|
{ function LastDate for russian users only }
|
|||
|
|
// { returns date relative to current date: '<27><><EFBFBD> <20><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>' }
|
|||
|
|
function LastDate(const Dat: TDateTime): string;
|
|||
|
|
{ CurrencyToStr format currency, Cur, using ffCurrency float format}
|
|||
|
|
function CurrencyToStr(const Cur: currency): string;
|
|||
|
|
{ Cmp compares two strings and returns True if they
|
|||
|
|
are equal. Case-insensitive.}
|
|||
|
|
function Cmp(const S1, S2: string): Boolean;
|
|||
|
|
{ StringCat add S2 string to S1 and returns this string }
|
|||
|
|
function StringCat(var S1: string; S2: string): string;
|
|||
|
|
{ HasChar returns True, if Char, Ch, contains in string, S }
|
|||
|
|
function HasChar(const Ch: Char; const S: string): Boolean;
|
|||
|
|
function HasAnyChar(const Chars: string; const S: string): Boolean;
|
|||
|
|
function CharInSet(const Ch: Char; const SetOfChar: TSetOfChar): Boolean;
|
|||
|
|
function CountOfChar(const Ch: Char; const S: string): Integer;
|
|||
|
|
function DefStr(const S: string; Default: string): string;
|
|||
|
|
|
|||
|
|
{**** files routines}
|
|||
|
|
|
|||
|
|
{ GetWinDir returns Windows folder name }
|
|||
|
|
function GetWinDir: TFileName;
|
|||
|
|
{ GetTempDir returns Windows temporary folder name }
|
|||
|
|
function GetTempDir: string;
|
|||
|
|
{ GenTempFileName returns temporary file name on
|
|||
|
|
drive, there FileName is placed }
|
|||
|
|
function GenTempFileName(FileName: string): string;
|
|||
|
|
{ GenTempFileNameExt same to previous function, but
|
|||
|
|
returning filename has given extension, FileExt }
|
|||
|
|
function GenTempFileNameExt(FileName: string; const FileExt: string): string;
|
|||
|
|
{ ClearDir clears folder Dir }
|
|||
|
|
function ClearDir(const Dir: string): Boolean;
|
|||
|
|
{ DeleteDir clears and than delete folder Dir }
|
|||
|
|
function DeleteDir(const Dir: string): Boolean;
|
|||
|
|
{ FileEquMask returns True if file, FileName,
|
|||
|
|
is compatible with given dos file mask, Mask }
|
|||
|
|
function FileEquMask(FileName, Mask: TFileName): Boolean;
|
|||
|
|
{ FileEquMasks returns True if file, FileName,
|
|||
|
|
is compatible with given Masks.
|
|||
|
|
Masks must be separated with comma (';') }
|
|||
|
|
function FileEquMasks(FileName, Masks: TFileName): Boolean;
|
|||
|
|
procedure DeleteFiles(const Folder: TFileName; const Masks: string);
|
|||
|
|
{ LZFileExpand expand file, FileSource,
|
|||
|
|
into FileDest. Given file must be compressed, using MS Compress program }
|
|||
|
|
function LZFileExpand(const FileSource, FileDest: string): Boolean;
|
|||
|
|
{ FileGetInfo fills SearchRec record for specified file attributes}
|
|||
|
|
function FileGetInfo(FileName: TFileName; var SearchRec: TSearchRec): Boolean;
|
|||
|
|
{ HasSubFolder returns True, if folder APath contains other folders }
|
|||
|
|
function HasSubFolder(APath: TFileName): Boolean;
|
|||
|
|
{ IsEmptyFolder returns True, if there are no files or
|
|||
|
|
folders in given folder, APath}
|
|||
|
|
function IsEmptyFolder(APath: TFileName): Boolean;
|
|||
|
|
{ AddSlash add slash Char to Dir parameter, if needed }
|
|||
|
|
procedure AddSlash(var Dir: TFileName);
|
|||
|
|
{ AddSlash returns string with added slash Char to Dir parameter, if needed }
|
|||
|
|
function AddSlash2(const Dir: TFileName): string;
|
|||
|
|
{ AddPath returns FileName with Path, if FileName not contain any path }
|
|||
|
|
function AddPath(const FileName, Path: TFileName): TFileName;
|
|||
|
|
function AddPaths(const PathList, Path: string): string;
|
|||
|
|
function ParentPath(const Path: TFileName): TFileName;
|
|||
|
|
function FindInPath(const FileName, PathList: string): TFileName;
|
|||
|
|
{$IFNDEF BCB1}
|
|||
|
|
{ BrowseForFolder displays Browse For Folder dialog }
|
|||
|
|
function BrowseForFolder(const Handle: HWND; const Title: string; var Folder: string): Boolean;
|
|||
|
|
{$ENDIF BCB1}
|
|||
|
|
{ DeleteReadOnlyFile clears R/O file attribute and delete file }
|
|||
|
|
function DeleteReadOnlyFile(const FileName: TFileName): Boolean;
|
|||
|
|
{ HasParam returns True, if program running with specified parameter, Param }
|
|||
|
|
function HasParam(const Param: string): Boolean;
|
|||
|
|
function HasSwitch(const Param: string): Boolean;
|
|||
|
|
function Switch(const Param: string): string;
|
|||
|
|
{ ExePath returns ExtractFilePath(ParamStr(0)) }
|
|||
|
|
function ExePath: TFileName;
|
|||
|
|
function CopyDir(const SourceDir, DestDir: TFileName): Boolean;
|
|||
|
|
function FileTimeToDateTime(const FT: TFileTime): TDateTime;
|
|||
|
|
function MakeValidFileName(const FileName: TFileName; const ReplaceBadChar: Char): TFileName;
|
|||
|
|
|
|||
|
|
{**** Graphic routines }
|
|||
|
|
|
|||
|
|
{ TTFontSelected returns True, if True Type font
|
|||
|
|
is selected in specified device context }
|
|||
|
|
function TTFontSelected(const DC: HDC): Boolean;
|
|||
|
|
{ TrueInflateRect inflates rect in other method, than InflateRect API function }
|
|||
|
|
function TrueInflateRect(const R: TRect; const I: Integer): TRect;
|
|||
|
|
|
|||
|
|
{**** Windows routines }
|
|||
|
|
|
|||
|
|
{ SetWindowTop put window to top without recreating window }
|
|||
|
|
procedure SetWindowTop(const Handle: HWND; const Top: Boolean);
|
|||
|
|
|
|||
|
|
{**** other routines }
|
|||
|
|
|
|||
|
|
{ KeyPressed returns True, if Key VK is now pressed }
|
|||
|
|
function KeyPressed(VK: Integer): Boolean;
|
|||
|
|
procedure SwapInt(var Int1, Int2: Integer);
|
|||
|
|
function IntPower(Base, Exponent: Integer): Integer;
|
|||
|
|
function ChangeTopException(E: TObject): TObject;
|
|||
|
|
function StrToBool(const S: string): Boolean;
|
|||
|
|
|
|||
|
|
{$IFNDEF COMPILER3_UP}
|
|||
|
|
{ AnsiStrLIComp compares S1 to S2, without case-sensitivity, up to a maximum
|
|||
|
|
Length of MaxLen bytes. The compare operation is controlled by the
|
|||
|
|
current Windows locale. The return value is the same as for CompareStr. }
|
|||
|
|
function AnsiStrLIComp(S1, S2: PChar; MaxLen: Cardinal): Integer;
|
|||
|
|
function AnsiStrIComp(S1, S2: PChar): Integer;
|
|||
|
|
{$ENDIF}
|
|||
|
|
function Var2Type(V: Variant; const VarType: Integer): Variant;
|
|||
|
|
function VarToInt(V: Variant): Integer;
|
|||
|
|
function VarToFloat(V: Variant): Double;
|
|||
|
|
{ following functions are not documented
|
|||
|
|
because they are don't work properly sometimes, so don't use them }
|
|||
|
|
function ReplaceStrings1(S: string; const Word, Frase: string): string;
|
|||
|
|
{ ReplaceStrings1 is full equal to ReplaceString function
|
|||
|
|
- only for compatibility - don't use }
|
|||
|
|
{ GetSubStr is full equal to SubStr function
|
|||
|
|
- only for compatibility - don't use }
|
|||
|
|
function GetSubStr(const S: string; const Index: Integer; const Separator: Char): string;
|
|||
|
|
function GetParameter: string;
|
|||
|
|
function GetLongFileName(FileName: string): string;
|
|||
|
|
{* from unit FileCtrl}
|
|||
|
|
function DirectoryExists(const Name: string): Boolean;
|
|||
|
|
procedure ForceDirectories(Dir: string);
|
|||
|
|
{# from unit FileCtrl}
|
|||
|
|
function FileNewExt(const FileName, NewExt: TFileName): TFileName;
|
|||
|
|
function GetComputerID: string;
|
|||
|
|
function GetComputerName: string;
|
|||
|
|
|
|||
|
|
{**** string routines }
|
|||
|
|
|
|||
|
|
{ ReplaceAllStrings searches for all substrings, Words,
|
|||
|
|
in a string, S, and replaces them with Frases with the same Index.
|
|||
|
|
Also see RAUtilsW.ReplaceStrings1 function }
|
|||
|
|
function ReplaceAllStrings(S: string; Words, Frases: TStrings): string;
|
|||
|
|
{ ReplaceStrings searches the Word in a string, S, on PosBeg position,
|
|||
|
|
in the list, Words, and if founds, replaces this Word
|
|||
|
|
with string from another list, Frases, with the same Index,
|
|||
|
|
and then update NewSelStart variable }
|
|||
|
|
function ReplaceStrings(S: string; PosBeg, Len: Integer; Words, Frases: TStrings; var NewSelStart: Integer): string;
|
|||
|
|
{ CountOfLines calculates the lines count in a string, S,
|
|||
|
|
each line must be separated from another with CrLf sequence }
|
|||
|
|
function CountOfLines(const S: string): Integer;
|
|||
|
|
{ DeleteEmptyLines deletes all empty lines from strings, Ss.
|
|||
|
|
Lines contained only spaces also deletes. }
|
|||
|
|
procedure DeleteEmptyLines(Ss: TStrings);
|
|||
|
|
{ SQLAddWhere addes or modifies existing where-statement, where,
|
|||
|
|
to the strings, SQL.
|
|||
|
|
Note: If strings SQL allready contains where-statement,
|
|||
|
|
it must be started on the begining of any line }
|
|||
|
|
procedure SQLAddWhere(SQL: TStrings; const Where: string);
|
|||
|
|
|
|||
|
|
{**** files routines - }
|
|||
|
|
|
|||
|
|
{ ResSaveToFile save resource named as Name with Typ type into file FileName.
|
|||
|
|
Resource can be compressed using MS Compress program}
|
|||
|
|
function ResSaveToFile(const Typ, Name: string; const Compressed: Boolean; const FileName: string): Boolean;
|
|||
|
|
function ResSaveToFileEx(Instance: HINST; Typ, Name: PChar;
|
|||
|
|
const Compressed: Boolean; const FileName: string): Boolean;
|
|||
|
|
function ResSaveToString(Instance: HINST; const Typ, Name: string;
|
|||
|
|
var S: string): Boolean;
|
|||
|
|
{ Execute executes other program and waiting for it
|
|||
|
|
terminating, then return its Exit Code }
|
|||
|
|
function Execute(const CommandLine, WorkingDirectory: string): Integer;
|
|||
|
|
{ IniReadSection read section, Section, from ini-file,
|
|||
|
|
IniFileName, into strings, Ss.
|
|||
|
|
This function reads ALL strings from specified section.
|
|||
|
|
Note: TIninFile.ReadSection function reads only strings with '=' symbol.}
|
|||
|
|
function IniReadSection(const IniFileName: TFileName; const Section: string; Ss: TStrings): Boolean;
|
|||
|
|
{ LoadTextFile load text file, FileName, into string }
|
|||
|
|
function LoadTextFile(const FileName: TFileName): string;
|
|||
|
|
procedure SaveTextFile(const FileName: TFileName; const Source: string);
|
|||
|
|
{ ReadFolder reads files list from disk folder, Folder,
|
|||
|
|
that are equal to mask, Mask, into strings, FileList}
|
|||
|
|
function ReadFolder(const Folder, Mask: TFileName; FileList: TStrings): Integer;
|
|||
|
|
function ReadFolders(const Folder: TFileName; FolderList: TStrings): Integer;
|
|||
|
|
|
|||
|
|
{$IFDEF COMPILER3_UP}
|
|||
|
|
{ TargetFileName - if FileName is ShortCut returns filename ShortCut linked to }
|
|||
|
|
function TargetFileName(const FileName: TFileName): TFileName;
|
|||
|
|
{ return filename ShortCut linked to }
|
|||
|
|
function ResolveLink(const hWnd: HWND; const LinkFile: TFileName;
|
|||
|
|
var FileName: TFileName): HRESULT;
|
|||
|
|
{$ENDIF COMPILER3_UP}
|
|||
|
|
|
|||
|
|
{**** Graphic routines - }
|
|||
|
|
|
|||
|
|
{ LoadIcoToImage loads two icons from resource named NameRes,
|
|||
|
|
into two image lists ALarge and ASmall}
|
|||
|
|
procedure LoadIcoToImage(ALarge, ASmall: TImageList; const NameRes: string);
|
|||
|
|
{ RATextOut same with TCanvas.TextOut procedure, but
|
|||
|
|
can clipping drawing with rectangle, RClip. }
|
|||
|
|
procedure RATextOut(Canvas: TCanvas; const R, RClip: TRect; const S: string);
|
|||
|
|
{ RATextOutEx same with RATextOut function, but
|
|||
|
|
can calculate needed height for correct output }
|
|||
|
|
function RATextOutEx(Canvas: TCanvas; const R, RClip: TRect; const S: string; const CalcHeight: Boolean): Integer;
|
|||
|
|
{ RATextCalcHeight calculate needed height for
|
|||
|
|
correct output, using RATextOut or RATextOutEx functions }
|
|||
|
|
function RATextCalcHeight(Canvas: TCanvas; const R: TRect; const S: string): Integer;
|
|||
|
|
{ Cinema draws some visual effect }
|
|||
|
|
procedure Cinema(Canvas: TCanvas; rS {Source}, rD {Dest}: TRect);
|
|||
|
|
{ Roughed fills rect with special 3D pattern }
|
|||
|
|
procedure Roughed(ACanvas: TCanvas; const ARect: TRect; const AVert: Boolean);
|
|||
|
|
{ BitmapFromBitmap creates new small bitmap from part
|
|||
|
|
of source bitmap, SrcBitmap, with specified width and height,
|
|||
|
|
AWidth, AHeight and placed on a specified Index, Index in the
|
|||
|
|
source bitmap }
|
|||
|
|
function BitmapFromBitmap(SrcBitmap: TBitmap; const AWidth, AHeight, Index: Integer): TBitmap;
|
|||
|
|
{ TextWidth calculate text with for writing using standard desktop font }
|
|||
|
|
function TextWidth(AStr: string): Integer;
|
|||
|
|
{ DefineCursor load cursor from resource, and return
|
|||
|
|
available cursor number, assigned to it }
|
|||
|
|
function DefineCursor(Identifier: PChar): TCursor;
|
|||
|
|
|
|||
|
|
{**** other routines - }
|
|||
|
|
{ FindFormByClass returns first form with specified
|
|||
|
|
class, FormClass, owned by Application global variable }
|
|||
|
|
function FindFormByClass(FormClass: TFormClass): TForm;
|
|||
|
|
function FindFormByClassName(FormClassName: string): TForm;
|
|||
|
|
{ FindByTag returns the control with specified class,
|
|||
|
|
ComponentClass, from WinContol.Controls property,
|
|||
|
|
having Tag property value, equaled to Tag parameter }
|
|||
|
|
function FindByTag(WinControl: TWinControl; ComponentClass: TComponentClass; const Tag: Integer): TComponent;
|
|||
|
|
{ ControlAtPos2 equal to TWinControl.ControlAtPos function,
|
|||
|
|
but works better }
|
|||
|
|
function ControlAtPos2(Parent: TWinControl; X, Y: Integer): TControl;
|
|||
|
|
{ RBTag searches WinControl.Controls for checked
|
|||
|
|
RadioButton and returns its Tag property value }
|
|||
|
|
function RBTag(Parent: TWinControl): Integer;
|
|||
|
|
{ AppMinimized returns True, if Application is minimized }
|
|||
|
|
function AppMinimized: Boolean;
|
|||
|
|
{ MessageBox is Application.MessageBox with string (not PChar) parameters.
|
|||
|
|
if Caption parameter = '', it replaced with Application.Title }
|
|||
|
|
function MessageBox(const Msg: string; Caption: string;
|
|||
|
|
const Flags: Integer): Integer;
|
|||
|
|
function MsgDlg2(const Msg, ACaption: string; DlgType: TMsgDlgType;
|
|||
|
|
Buttons: TMsgDlgButtons; HelpContext: Integer; Control: TWinControl): Integer;
|
|||
|
|
function MsgDlgDef(const Msg, ACaption: string; DlgType: TMsgDlgType;
|
|||
|
|
Buttons: TMsgDlgButtons; DefButton: TMsgDlgBtn; HelpContext: Integer;
|
|||
|
|
Control: TWinControl): Integer;
|
|||
|
|
{ Delay stop program execution to MSec msec }
|
|||
|
|
procedure Delay(MSec: Longword);
|
|||
|
|
procedure CenterHor(Parent: TControl; MinLeft: Integer; Controls: array of TControl);
|
|||
|
|
procedure EnableControls(Control: TWinControl; const Enable: Boolean);
|
|||
|
|
procedure EnableMenuItems(MenuItem: TMenuItem; const Tag: Integer; const Enable: Boolean);
|
|||
|
|
procedure ExpandWidth(Parent: TControl; MinWidth: Integer; Controls: array of TControl);
|
|||
|
|
function PanelBorder(Panel: TCustomPanel): Integer;
|
|||
|
|
function Pixels(Control: TControl; APixels: Integer): Integer;
|
|||
|
|
procedure SetChildPropOrd(Owner: TComponent; PropName: string; Value: Longint);
|
|||
|
|
procedure Error(const Msg: string);
|
|||
|
|
procedure ItemHtDrawEx(Canvas: TCanvas; Rect: TRect;
|
|||
|
|
const State: TOwnerDrawState; const Text: string;
|
|||
|
|
const HideSelColor: Boolean; var PlainItem: string;
|
|||
|
|
var Width: Integer; CalcWidth: Boolean);
|
|||
|
|
{ example for Text parameter :
|
|||
|
|
'Item 1 <b>bold</b> <i>italic ITALIC <c:Red>red <c:Green>green <c:blue>blue </i>' }
|
|||
|
|
function ItemHtDraw(Canvas: TCanvas; Rect: TRect;
|
|||
|
|
const State: TOwnerDrawState; const Text: string;
|
|||
|
|
const HideSelColor: Boolean): string;
|
|||
|
|
function ItemHtWidth(Canvas: TCanvas; Rect: TRect;
|
|||
|
|
const State: TOwnerDrawState; const Text: string;
|
|||
|
|
const HideSelColor: Boolean): Integer;
|
|||
|
|
function ItemHtPlain(const Text: string): string;
|
|||
|
|
{ ClearList - clears list of TObject }
|
|||
|
|
procedure ClearList(List: TList);
|
|||
|
|
|
|||
|
|
procedure MemStreamToClipBoard(MemStream: TMemoryStream; const Format: Word);
|
|||
|
|
procedure ClipBoardToMemStream(MemStream: TMemoryStream; const Format: Word);
|
|||
|
|
|
|||
|
|
{ RTTI support }
|
|||
|
|
function GetPropType(Obj: TObject; const PropName: string): TTypeKind;
|
|||
|
|
function GetPropStr(Obj: TObject; const PropName: string): string;
|
|||
|
|
function GetPropOrd(Obj: TObject; const PropName: string): Integer;
|
|||
|
|
function GetPropMethod(Obj: TObject; const PropName: string): TMethod;
|
|||
|
|
|
|||
|
|
procedure PrepareIniSection(SS: TStrings);
|
|||
|
|
{ following functions are not documented because
|
|||
|
|
they are don't work properly, so don't use them }
|
|||
|
|
{$IFDEF COMPILER2}
|
|||
|
|
function CompareMem(P1, P2: Pointer; Length: Integer): Boolean; assembler;
|
|||
|
|
{$ENDIF}
|
|||
|
|
|
|||
|
|
type
|
|||
|
|
TMenuAnimation = (maNone, maRandom, maUnfold, maSlide);
|
|||
|
|
|
|||
|
|
procedure ShowMenu(Form: TForm; MenuAni: TMenuAnimation);
|
|||
|
|
|
|||
|
|
type
|
|||
|
|
TProcObj = procedure of object;
|
|||
|
|
|
|||
|
|
procedure ExecAfterPause(Proc: TProcObj; Pause: Integer);
|
|||
|
|
|
|||
|
|
const
|
|||
|
|
NoHelp = 0; { for MsgDlg2 }
|
|||
|
|
MsgDlgCharSet: Integer = DEFAULT_CHARSET;
|
|||
|
|
|
|||
|
|
// (rom) from JvBandWindows to make it obsolete
|
|||
|
|
function PointL(const X, Y: Longint): TPointL;
|
|||
|
|
// (rom) from JvBandUtils to make it obsolete
|
|||
|
|
function iif(const Test: Boolean; const ATrue, AFalse: Variant): Variant;
|
|||
|
|
|
|||
|
|
implementation
|
|||
|
|
|
|||
|
|
uses
|
|||
|
|
Math,
|
|||
|
|
JvCtlConst;
|
|||
|
|
|
|||
|
|
function GetLineByPos(const S: string; const Pos: Integer): Integer;
|
|||
|
|
var
|
|||
|
|
I: Integer;
|
|||
|
|
begin
|
|||
|
|
if Length(S) < Pos then
|
|||
|
|
Result := -1
|
|||
|
|
else
|
|||
|
|
begin
|
|||
|
|
I := 1;
|
|||
|
|
Result := 0;
|
|||
|
|
while I <= Pos do
|
|||
|
|
begin
|
|||
|
|
if S[I] = #13 then
|
|||
|
|
Inc(Result);
|
|||
|
|
Inc(I);
|
|||
|
|
end;
|
|||
|
|
end;
|
|||
|
|
end;
|
|||
|
|
|
|||
|
|
procedure GetXYByPos(const S: string; const Pos: Integer; var X, Y: Integer);
|
|||
|
|
var
|
|||
|
|
I, iB: Integer;
|
|||
|
|
begin
|
|||
|
|
X := -1;
|
|||
|
|
Y := -1;
|
|||
|
|
iB := 0;
|
|||
|
|
if (Length(S) >= Pos) and (Pos >= 0) then
|
|||
|
|
begin
|
|||
|
|
I := 1;
|
|||
|
|
Y := 0;
|
|||
|
|
while I <= Pos do
|
|||
|
|
begin
|
|||
|
|
if S[I] = #13 then
|
|||
|
|
begin
|
|||
|
|
Inc(Y);
|
|||
|
|
iB := I + 1;
|
|||
|
|
end;
|
|||
|
|
Inc(I);
|
|||
|
|
end;
|
|||
|
|
X := Pos - iB;
|
|||
|
|
end;
|
|||
|
|
end;
|
|||
|
|
|
|||
|
|
function GetWordOnPos(const S: string; const P: Integer): string;
|
|||
|
|
var
|
|||
|
|
I, Beg: Integer;
|
|||
|
|
begin
|
|||
|
|
Result := '';
|
|||
|
|
if (P > Length(S)) or (P < 1) then
|
|||
|
|
Exit;
|
|||
|
|
for I := P downto 1 do
|
|||
|
|
if S[I] in Separators then
|
|||
|
|
Break;
|
|||
|
|
Beg := I + 1;
|
|||
|
|
for I := P to Length(S) do
|
|||
|
|
if S[I] in Separators then
|
|||
|
|
Break;
|
|||
|
|
if I > Beg then
|
|||
|
|
Result := Copy(S, Beg, I - Beg)
|
|||
|
|
else
|
|||
|
|
Result := S[P];
|
|||
|
|
end;
|
|||
|
|
|
|||
|
|
function GetWordOnPosEx(const S: string; const P: Integer; var iBeg, iEnd: Integer): string;
|
|||
|
|
begin
|
|||
|
|
Result := '';
|
|||
|
|
if (P > Length(S)) or (P < 1) then
|
|||
|
|
Exit;
|
|||
|
|
iBeg := P;
|
|||
|
|
if P > 1 then
|
|||
|
|
if S[P] in Separators then
|
|||
|
|
if (P < 1) or ((P - 1 > 0) and (S[P - 1] in Separators)) then
|
|||
|
|
Inc(iBeg)
|
|||
|
|
else
|
|||
|
|
if not ((P - 1 > 0) and (S[P - 1] in Separators)) then
|
|||
|
|
Dec(iBeg);
|
|||
|
|
while iBeg >= 1 do
|
|||
|
|
if S[iBeg] in Separators then
|
|||
|
|
Break
|
|||
|
|
else
|
|||
|
|
Dec(iBeg);
|
|||
|
|
Inc(iBeg);
|
|||
|
|
iEnd := P;
|
|||
|
|
while iEnd <= Length(S) do
|
|||
|
|
if S[iEnd] in Separators then
|
|||
|
|
Break
|
|||
|
|
else
|
|||
|
|
Inc(iEnd);
|
|||
|
|
if iEnd > iBeg then
|
|||
|
|
Result := Copy(S, iBeg, iEnd - iBeg)
|
|||
|
|
else
|
|||
|
|
Result := S[P];
|
|||
|
|
end;
|
|||
|
|
|
|||
|
|
function GetWinDir: TFileName;
|
|||
|
|
var
|
|||
|
|
WinDir: array [0..MAX_PATH] of Char;
|
|||
|
|
begin
|
|||
|
|
WinDir[GetWindowsDirectory(WinDir, MAX_PATH)] := #0;
|
|||
|
|
Result := WinDir;
|
|||
|
|
end;
|
|||
|
|
|
|||
|
|
function GenTempFileName(FileName: string): string;
|
|||
|
|
var
|
|||
|
|
TempDir: array [0..MAX_PATH] of Char;
|
|||
|
|
TempFile: array [0..MAX_PATH] of Char;
|
|||
|
|
STempDir: TFileName;
|
|||
|
|
Res: Integer;
|
|||
|
|
begin
|
|||
|
|
TempDir[GetTempPath(260, TempDir)] := #0;
|
|||
|
|
if FileName <> '' then
|
|||
|
|
begin
|
|||
|
|
if Length(FileName) < 4 then
|
|||
|
|
FileName := ExpandFileName(FileName);
|
|||
|
|
if (Length(FileName) > 4) and (FileName[2] = ':') and
|
|||
|
|
(StrLen(@TempDir[0]) > 4) and
|
|||
|
|
(AnsiCompareText(TempDir[0], FileName[1]) <> 0) then
|
|||
|
|
begin
|
|||
|
|
STempDir := ExtractFilePath(FileName);
|
|||
|
|
Move(STempDir[1], TempDir, Length(STempDir) + 1);
|
|||
|
|
end;
|
|||
|
|
end;
|
|||
|
|
Res := GetTempFileName(
|
|||
|
|
TempDir, { address of directory name for temporary file}
|
|||
|
|
'~RA', { address of filename prefix}
|
|||
|
|
0, { number used to create temporary filename}
|
|||
|
|
TempFile); { address of buffer that receives the new filename}
|
|||
|
|
if Res <> 0 then
|
|||
|
|
Result := TempFile
|
|||
|
|
else
|
|||
|
|
Result := '~JVCLTemp.tmp';
|
|||
|
|
DeleteFile(Result);
|
|||
|
|
end;
|
|||
|
|
|
|||
|
|
function GenTempFileNameExt(FileName: string; const FileExt: string): string;
|
|||
|
|
begin
|
|||
|
|
Result := ChangeFileExt(GenTempFileName(FileName), FileExt);
|
|||
|
|
end;
|
|||
|
|
|
|||
|
|
function GetTempDir: string;
|
|||
|
|
var
|
|||
|
|
TempDir: array [0..MAX_PATH] of Char;
|
|||
|
|
begin
|
|||
|
|
TempDir[GetTempPath(260, TempDir)] := #0;
|
|||
|
|
Result := TempDir;
|
|||
|
|
end;
|
|||
|
|
|
|||
|
|
function ClearDir(const Dir: string): Boolean;
|
|||
|
|
var
|
|||
|
|
SearchRec: TSearchRec;
|
|||
|
|
DosError: Integer;
|
|||
|
|
Path: TFileName;
|
|||
|
|
begin
|
|||
|
|
Result := True;
|
|||
|
|
Path := Dir;
|
|||
|
|
AddSlash(Path);
|
|||
|
|
DosError := FindFirst(Path + '*.*', faAnyFile, SearchRec);
|
|||
|
|
while DosError = 0 do
|
|||
|
|
begin
|
|||
|
|
if (SearchRec.Name <> '.') and (SearchRec.Name <> '..') then
|
|||
|
|
begin
|
|||
|
|
if (SearchRec.Attr and faDirectory) = faDirectory then
|
|||
|
|
Result := Result and DeleteDir(Path + SearchRec.Name)
|
|||
|
|
else
|
|||
|
|
Result := Result and DeleteFile(Path + SearchRec.Name);
|
|||
|
|
// if not Result then Exit;
|
|||
|
|
end;
|
|||
|
|
DosError := FindNext(SearchRec);
|
|||
|
|
end;
|
|||
|
|
FindClose(SearchRec);
|
|||
|
|
end;
|
|||
|
|
|
|||
|
|
function DeleteDir(const Dir: string): Boolean;
|
|||
|
|
begin
|
|||
|
|
ClearDir(Dir);
|
|||
|
|
{ if Dir[Length(Dir)] = '\' then Dir[Length(Dir)] := #0;}
|
|||
|
|
Result := RemoveDir(Dir);
|
|||
|
|
end;
|
|||
|
|
|
|||
|
|
procedure DeleteFiles(const Folder: TFileName; const Masks: string);
|
|||
|
|
var
|
|||
|
|
SearchRec: TSearchRec;
|
|||
|
|
DosError: Integer;
|
|||
|
|
Path: TFileName;
|
|||
|
|
begin
|
|||
|
|
Path := AddSlash2(Folder);
|
|||
|
|
DosError := FindFirst(Path + '*.*', faAnyFile and not faDirectory, SearchRec);
|
|||
|
|
while DosError = 0 do
|
|||
|
|
begin
|
|||
|
|
if FileEquMasks(Path + SearchRec.Name, Masks) then
|
|||
|
|
DeleteFile(Path + SearchRec.Name);
|
|||
|
|
DosError := FindNext(SearchRec);
|
|||
|
|
end;
|
|||
|
|
FindClose(SearchRec);
|
|||
|
|
end;
|
|||
|
|
|
|||
|
|
function GetParameter: string;
|
|||
|
|
var
|
|||
|
|
FN, FN1: PChar;
|
|||
|
|
begin
|
|||
|
|
if ParamCount = 0 then
|
|||
|
|
begin
|
|||
|
|
Result := '';
|
|||
|
|
Exit
|
|||
|
|
end;
|
|||
|
|
FN := cmdLine;
|
|||
|
|
if FN[0] = '"' then
|
|||
|
|
begin
|
|||
|
|
FN := StrScan(FN + 1, '"');
|
|||
|
|
if (FN[0] = #00) or (FN[1] = #00) then
|
|||
|
|
Result := ''
|
|||
|
|
else
|
|||
|
|
begin
|
|||
|
|
Inc(FN, 2);
|
|||
|
|
if FN[0] = '"' then
|
|||
|
|
begin
|
|||
|
|
Inc(FN, 1);
|
|||
|
|
FN1 := StrScan(FN + 1, '"');
|
|||
|
|
if FN1[0] <> #00 then
|
|||
|
|
FN1[0] := #00;
|
|||
|
|
end;
|
|||
|
|
Result := FN;
|
|||
|
|
end;
|
|||
|
|
end
|
|||
|
|
else
|
|||
|
|
Result := Copy(CmdLine, Length(ParamStr(0)) + 1, 260);
|
|||
|
|
while (Length(Result) > 0) and (Result[1] = ' ') do
|
|||
|
|
Delete(Result, 1, 1);
|
|||
|
|
Result := ReplaceString(Result, '"', '');
|
|||
|
|
if FileExists(Result) then
|
|||
|
|
Result := GetLongFileName(Result);
|
|||
|
|
end;
|
|||
|
|
|
|||
|
|
function GetLongFileName(FileName: string): string;
|
|||
|
|
var
|
|||
|
|
SearchRec: TSearchRec;
|
|||
|
|
begin
|
|||
|
|
if FileGetInfo(FileName, SearchRec) then
|
|||
|
|
Result := ExtractFilePath(ExpandFileName(FileName)) + SearchRec.FindData.cFileName
|
|||
|
|
else
|
|||
|
|
Result := FileName;
|
|||
|
|
end;
|
|||
|
|
|
|||
|
|
function FileEquMask(FileName, Mask: TFileName): Boolean;
|
|||
|
|
var
|
|||
|
|
I: Integer;
|
|||
|
|
C: Char;
|
|||
|
|
P: PChar;
|
|||
|
|
begin
|
|||
|
|
FileName := AnsiUpperCase(ExtractFileName(FileName));
|
|||
|
|
Mask := AnsiUpperCase(Mask);
|
|||
|
|
Result := False;
|
|||
|
|
if Pos('.', FileName) = 0 then
|
|||
|
|
FileName := FileName + '.';
|
|||
|
|
I := 1;
|
|||
|
|
P := PChar(FileName);
|
|||
|
|
while I <= Length(Mask) do
|
|||
|
|
begin
|
|||
|
|
C := Mask[I];
|
|||
|
|
if (P[0] = #0) and (C <> '*') then
|
|||
|
|
Exit;
|
|||
|
|
case C of
|
|||
|
|
'*':
|
|||
|
|
if I = Length(Mask) then
|
|||
|
|
begin
|
|||
|
|
Result := True;
|
|||
|
|
Exit;
|
|||
|
|
end
|
|||
|
|
else
|
|||
|
|
begin
|
|||
|
|
P := StrScan(P, Mask[I + 1]);
|
|||
|
|
if P = nil then
|
|||
|
|
Exit;
|
|||
|
|
end;
|
|||
|
|
'?':
|
|||
|
|
Inc(P);
|
|||
|
|
else
|
|||
|
|
if C = P[0] then
|
|||
|
|
Inc(P)
|
|||
|
|
else
|
|||
|
|
Exit;
|
|||
|
|
end;
|
|||
|
|
Inc(I);
|
|||
|
|
end;
|
|||
|
|
if P[0] = #0 then
|
|||
|
|
Result := True;
|
|||
|
|
end;
|
|||
|
|
|
|||
|
|
function FileEquMasks(FileName, Masks: TFileName): Boolean;
|
|||
|
|
var
|
|||
|
|
I: Integer;
|
|||
|
|
Mask: string;
|
|||
|
|
begin
|
|||
|
|
Result := False;
|
|||
|
|
I := 0;
|
|||
|
|
Mask := Trim(GetSubStr(Masks, I, ';'));
|
|||
|
|
while Length(Mask) <> 0 do
|
|||
|
|
if FileEquMask(FileName, Mask) then
|
|||
|
|
begin
|
|||
|
|
Result := True;
|
|||
|
|
Break;
|
|||
|
|
end
|
|||
|
|
else
|
|||
|
|
begin
|
|||
|
|
Inc(I);
|
|||
|
|
Mask := Trim(GetSubStr(Masks, I, ';'));
|
|||
|
|
end;
|
|||
|
|
end;
|
|||
|
|
|
|||
|
|
function NumberByWord(const N: Longint): string;
|
|||
|
|
const
|
|||
|
|
Ten: array [0..9] of string =
|
|||
|
|
('zero', 'one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine');
|
|||
|
|
Hun: array [1..9] of string =
|
|||
|
|
('onehundred', 'twohundred', 'threehundred', 'fourhundred', 'fivehundred',
|
|||
|
|
'sixhundred', 'sevenhundred', 'eighthundred', 'ninehundred');
|
|||
|
|
OnTen: array [10..19] of string =
|
|||
|
|
('ten', 'eleven', 'twelve', 'thirteen', 'fourteen',
|
|||
|
|
'fifteen', 'sixteen', 'seventeen', 'eighteen', 'nineteen');
|
|||
|
|
HunIn: array [2..9] of string =
|
|||
|
|
('twothousand', 'threethousand', 'fourthousand', 'fivethousand',
|
|||
|
|
'sixthousand', 'seventhousand', 'eightthousand', 'ninethousand');
|
|||
|
|
var
|
|||
|
|
StrVsp: string;
|
|||
|
|
NumStr: string;
|
|||
|
|
StrVsp2: string;
|
|||
|
|
I: Byte;
|
|||
|
|
|
|||
|
|
function IndNumber(Stri: string; Place: Byte): Byte;
|
|||
|
|
begin
|
|||
|
|
IndNumber := Ord(Stri[Place]) - 48;
|
|||
|
|
end;
|
|||
|
|
|
|||
|
|
function Back(Stri: string): Longint;
|
|||
|
|
var
|
|||
|
|
Code: Integer;
|
|||
|
|
LI: Longint;
|
|||
|
|
begin
|
|||
|
|
Result := 0;
|
|||
|
|
Val(Stri, LI, Code);
|
|||
|
|
if Code = 0 then
|
|||
|
|
Result := LI;
|
|||
|
|
end;
|
|||
|
|
|
|||
|
|
begin
|
|||
|
|
NumStr := IntToStr(N);
|
|||
|
|
if Length(NumStr) > 9 then
|
|||
|
|
begin
|
|||
|
|
Result := '*****';
|
|||
|
|
Exit;
|
|||
|
|
end;
|
|||
|
|
case Length(NumStr) of
|
|||
|
|
1:
|
|||
|
|
StrVsp := Ten[N];
|
|||
|
|
2: case NumStr[1] of
|
|||
|
|
'1':
|
|||
|
|
StrVsp := OnTen[N];
|
|||
|
|
'0':
|
|||
|
|
StrVsp := NumberByWord(IndNumber(NumStr, 2));
|
|||
|
|
'2'..'9':
|
|||
|
|
begin
|
|||
|
|
StrVsp := HunIn[IndNumber(NumStr, 1)];
|
|||
|
|
if NumStr[2] <> '0' then
|
|||
|
|
StrVsp := StrVsp + ' ' + NumberByWord(IndNumber(NumStr, 2));
|
|||
|
|
end;
|
|||
|
|
end;
|
|||
|
|
3:
|
|||
|
|
begin
|
|||
|
|
StrVsp := Hun[IndNumber(NumStr, 1)];
|
|||
|
|
StrVsp := StrVsp + ' ' + NumberByWord(Back(Copy(NumStr, 2, 2)));
|
|||
|
|
end;
|
|||
|
|
4:
|
|||
|
|
begin
|
|||
|
|
StrVsp := Ten[IndNumber(NumStr, 1)];
|
|||
|
|
// (rom) needs translation
|
|||
|
|
case NumStr[1] of
|
|||
|
|
'1':
|
|||
|
|
StrVsp := '<27><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>';
|
|||
|
|
'2':
|
|||
|
|
StrVsp := '<27><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>';
|
|||
|
|
'3', '4':
|
|||
|
|
StrVsp := StrVsp + ' <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>';
|
|||
|
|
'5'..'9':
|
|||
|
|
StrVsp := StrVsp + ' <20><><EFBFBD><EFBFBD><EFBFBD>';
|
|||
|
|
end;
|
|||
|
|
StrVsp := StrVsp + ' ' + NumberByWord(Back(Copy(NumStr, 2, 3)));
|
|||
|
|
end;
|
|||
|
|
5:
|
|||
|
|
begin
|
|||
|
|
StrVsp2 := NumberByWord(Back(Copy(NumStr, 1, 2)));
|
|||
|
|
I := Pos(' <20><><EFBFBD>', StrVsp2);
|
|||
|
|
if Pos(' <20><><EFBFBD>', StrVsp2) = I then
|
|||
|
|
I := 0;
|
|||
|
|
if I <> 0 then
|
|||
|
|
StrVsp2[I + 3] := 'e';
|
|||
|
|
I := Pos(' <20><><EFBFBD><EFBFBD>', StrVsp2);
|
|||
|
|
if Pos(' <20><><EFBFBD><EFBFBD><EFBFBD>', StrVsp2) = I then
|
|||
|
|
I := 0;
|
|||
|
|
if I <> 0 then
|
|||
|
|
begin
|
|||
|
|
StrVsp2[I + 3] := '<27>';
|
|||
|
|
StrVsp2[I + 4] := '<27>';
|
|||
|
|
end;
|
|||
|
|
if NumStr[1] <> '1' then
|
|||
|
|
case NumStr[2] of
|
|||
|
|
'1':
|
|||
|
|
StrVsp := ' <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> ';
|
|||
|
|
'2'..'4':
|
|||
|
|
StrVsp := ' <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> ';
|
|||
|
|
'5'..'9':
|
|||
|
|
StrVsp := ' <20><><EFBFBD><EFBFBD><EFBFBD> ';
|
|||
|
|
end
|
|||
|
|
else
|
|||
|
|
StrVsp := ' <20><><EFBFBD><EFBFBD><EFBFBD> ';
|
|||
|
|
StrVsp := StrVsp2 + StrVsp + NumberByWord(Back(Copy(NumStr, 3, 3)));
|
|||
|
|
end;
|
|||
|
|
6:
|
|||
|
|
begin
|
|||
|
|
StrVsp2 := NumberByWord(Back(Copy(NumStr, 1, 3)));
|
|||
|
|
I := Pos(' <20><><EFBFBD>', StrVsp2);
|
|||
|
|
if Pos(' <20><><EFBFBD><EFBFBD>', StrVsp2) = I then
|
|||
|
|
I := 0;
|
|||
|
|
if I <> 0 then
|
|||
|
|
StrVsp2[I + 3] := '<27>';
|
|||
|
|
I := Pos(' <20><><EFBFBD><EFBFBD>', Strvsp2);
|
|||
|
|
if Pos(' <20><><EFBFBD><EFBFBD><EFBFBD>', StrVsp2) = I then
|
|||
|
|
I := 0;
|
|||
|
|
if I <> 0 then
|
|||
|
|
begin
|
|||
|
|
StrVsp2[I + 3] := '<27>';
|
|||
|
|
StrVsp2[I + 4] := '<27>';
|
|||
|
|
end;
|
|||
|
|
if NumStr[2] <> '1' then
|
|||
|
|
case NumStr[3] of
|
|||
|
|
'1':
|
|||
|
|
StrVsp := ' <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> ';
|
|||
|
|
'2'..'4':
|
|||
|
|
StrVsp := ' <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> ';
|
|||
|
|
'5'..'9':
|
|||
|
|
StrVsp := ' <20><><EFBFBD><EFBFBD><EFBFBD> ';
|
|||
|
|
end
|
|||
|
|
else
|
|||
|
|
StrVsp := ' <20><><EFBFBD><EFBFBD><EFBFBD> ';
|
|||
|
|
StrVsp := StrVsp2 + StrVsp + NumberByWord(Back(Copy(NumStr, 4, 3)));
|
|||
|
|
end;
|
|||
|
|
7:
|
|||
|
|
begin
|
|||
|
|
StrVsp := Ten[IndNumber(NumStr, 1)];
|
|||
|
|
case NumStr[1] of
|
|||
|
|
'1':
|
|||
|
|
StrVsp := '<27><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>';
|
|||
|
|
'2'..'4':
|
|||
|
|
StrVsp := StrVsp + ' <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>';
|
|||
|
|
'5'..'9':
|
|||
|
|
StrVsp := StrVsp + ' <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>';
|
|||
|
|
end;
|
|||
|
|
StrVsp := StrVsp + ' ' + NumberByWord(Back(Copy(NumStr, 2, 6)));
|
|||
|
|
end;
|
|||
|
|
8:
|
|||
|
|
begin
|
|||
|
|
StrVsp := NumberByWord(Back(Copy(NumStr, 1, 2)));
|
|||
|
|
StrVsp := StrVsp + ' <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>';
|
|||
|
|
if NumStr[1] <> '1' then
|
|||
|
|
case NumStr[2] of
|
|||
|
|
'2'..'4':
|
|||
|
|
StrVsp := StrVsp + '<27>';
|
|||
|
|
'0', '5'..'9':
|
|||
|
|
StrVsp := StrVsp + '<27><>';
|
|||
|
|
end
|
|||
|
|
else
|
|||
|
|
StrVsp := StrVsp + '<27><>';
|
|||
|
|
StrVsp := StrVsp + ' ' + NumberByWord(Back(Copy(NumStr, 3, 6)));
|
|||
|
|
end;
|
|||
|
|
9:
|
|||
|
|
begin
|
|||
|
|
StrVsp := NumberByWord(Back(Copy(Numstr, 1, 3)));
|
|||
|
|
StrVsp := StrVsp + ' <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>';
|
|||
|
|
if NumStr[2] <> '1' then
|
|||
|
|
case NumStr[3] of
|
|||
|
|
'2'..'4':
|
|||
|
|
StrVsp := StrVsp + '<27>';
|
|||
|
|
'0', '5'..'9':
|
|||
|
|
StrVsp := StrVsp + '<27><>';
|
|||
|
|
end
|
|||
|
|
else
|
|||
|
|
StrVsp := StrVsp + '<27><>';
|
|||
|
|
StrVsp := StrVsp + ' ' + NumberByWord(Back(Copy(NumStr, 4, 6)));
|
|||
|
|
end;
|
|||
|
|
end;
|
|||
|
|
if (Length(StrVsp) > 4) and (Copy(StrVsp, Length(StrVsp) - 3, 4) = Ten[0]) then
|
|||
|
|
StrVsp := Copy(StrVsp, 1, Length(StrVsp) - 4);
|
|||
|
|
Result := StrVsp;
|
|||
|
|
end;
|
|||
|
|
|
|||
|
|
function GetSubStr(const S: string; const Index: Integer; const Separator: Char): string;
|
|||
|
|
begin
|
|||
|
|
Result := SubStr(S, Index, Separator);
|
|||
|
|
end;
|
|||
|
|
|
|||
|
|
function SubStr(const S: string; const Index: Integer; const Separator: string): string;
|
|||
|
|
{ Returns a substring. Substrings are divided by Sep character [translated] }
|
|||
|
|
var
|
|||
|
|
I: Integer;
|
|||
|
|
pB, pE: PChar;
|
|||
|
|
begin
|
|||
|
|
Result := '';
|
|||
|
|
if ((Index < 0) or ((Index = 0) and (Length(S) > 0) and (S[1] = Separator))) or
|
|||
|
|
(Length(S) = 0) then
|
|||
|
|
Exit;
|
|||
|
|
pB := PChar(S);
|
|||
|
|
for I := 1 to Index do
|
|||
|
|
begin
|
|||
|
|
pB := StrPos(pB, PChar(Separator));
|
|||
|
|
if pB = nil then
|
|||
|
|
Exit;
|
|||
|
|
pB := pB + Length(Separator);
|
|||
|
|
if pB[0] = #0 then
|
|||
|
|
Exit;
|
|||
|
|
end;
|
|||
|
|
pE := StrPos(pB + 1, PChar(Separator));
|
|||
|
|
if pE = nil then
|
|||
|
|
pE := PChar(S) + Length(S);
|
|||
|
|
if not (AnsiStrLIComp(pB, PChar(Separator), Length(Separator)) = 0) then
|
|||
|
|
SetString(Result, pB, pE - pB);
|
|||
|
|
end;
|
|||
|
|
|
|||
|
|
function SubStrEnd(const S: string; const Index: Integer; const Separator: string): string;
|
|||
|
|
{ The same as SubStr, but substrings are numbered from the end [translated]}
|
|||
|
|
var
|
|||
|
|
MaxIndex: Integer;
|
|||
|
|
pB: PChar;
|
|||
|
|
begin
|
|||
|
|
{ Not optimal implementation [translated] }
|
|||
|
|
MaxIndex := 0;
|
|||
|
|
pB := StrPos(PChar(S), PChar(Separator));
|
|||
|
|
while pB <> nil do
|
|||
|
|
begin
|
|||
|
|
Inc(MaxIndex);
|
|||
|
|
pB := StrPos(pB + Length(Separator), PChar(Separator));
|
|||
|
|
end;
|
|||
|
|
Result := SubStr(S, MaxIndex - Index, Separator);
|
|||
|
|
end;
|
|||
|
|
|
|||
|
|
function FileGetInfo(FileName: TFileName; var SearchRec: TSearchRec): Boolean;
|
|||
|
|
var
|
|||
|
|
DosError: Integer;
|
|||
|
|
Path: TFileName;
|
|||
|
|
begin
|
|||
|
|
Result := False;
|
|||
|
|
Path := ExtractFilePath(ExpandFileName(FileName)) + '*.*';
|
|||
|
|
FileName := AnsiUpperCase(ExtractFileName(FileName));
|
|||
|
|
DosError := FindFirst(Path, faAnyFile, SearchRec);
|
|||
|
|
while DosError = 0 do
|
|||
|
|
begin
|
|||
|
|
if (AnsiCompareText(SearchRec.FindData.cFileName, FileName) = 0) or
|
|||
|
|
(AnsiCompareText(SearchRec.FindData.cAlternateFileName, FileName) = 0) then
|
|||
|
|
begin
|
|||
|
|
Result := True;
|
|||
|
|
Break;
|
|||
|
|
end;
|
|||
|
|
DosError := FindNext(SearchRec);
|
|||
|
|
end;
|
|||
|
|
FindClose(SearchRec);
|
|||
|
|
end;
|
|||
|
|
|
|||
|
|
function HasSubFolder(APath: TFileName): Boolean;
|
|||
|
|
var
|
|||
|
|
SearchRec: TSearchRec;
|
|||
|
|
DosError: Integer;
|
|||
|
|
begin
|
|||
|
|
Result := False;
|
|||
|
|
AddSlash(APath);
|
|||
|
|
APath := Concat(APath, '*.*');
|
|||
|
|
DosError := FindFirst(APath, faDirectory, SearchRec);
|
|||
|
|
while DosError = 0 do
|
|||
|
|
begin
|
|||
|
|
if (SearchRec.Attr and faDirectory = faDirectory) and (SearchRec.Name[1] <> '.') then
|
|||
|
|
begin
|
|||
|
|
Result := True;
|
|||
|
|
Break;
|
|||
|
|
end;
|
|||
|
|
DosError := FindNext(SearchRec);
|
|||
|
|
end;
|
|||
|
|
FindClose(SearchRec);
|
|||
|
|
end;
|
|||
|
|
|
|||
|
|
function IsEmptyFolder(APath: TFileName): Boolean;
|
|||
|
|
var
|
|||
|
|
SearchRec: TSearchRec;
|
|||
|
|
DosError: Integer;
|
|||
|
|
begin
|
|||
|
|
Result := True;
|
|||
|
|
AddSlash(APath);
|
|||
|
|
APath := Concat(APath, '*.*');
|
|||
|
|
DosError := FindFirst(APath, faDirectory, SearchRec);
|
|||
|
|
while DosError = 0 do
|
|||
|
|
begin
|
|||
|
|
if SearchRec.Name[1] <> '.' then
|
|||
|
|
begin
|
|||
|
|
Result := False;
|
|||
|
|
Break;
|
|||
|
|
end;
|
|||
|
|
DosError := FindNext(SearchRec);
|
|||
|
|
end;
|
|||
|
|
FindClose(SearchRec);
|
|||
|
|
end;
|
|||
|
|
|
|||
|
|
function TTFontSelected(const DC: HDC): Boolean;
|
|||
|
|
var
|
|||
|
|
TM: TTEXTMETRIC;
|
|||
|
|
begin
|
|||
|
|
GetTextMetrics(DC, TM);
|
|||
|
|
Result := TM.tmPitchAndFamily and TMPF_TRUETYPE <> 0;
|
|||
|
|
end;
|
|||
|
|
|
|||
|
|
function SubWord(P: PChar; var P2: PChar): string;
|
|||
|
|
var
|
|||
|
|
I: Integer;
|
|||
|
|
begin
|
|||
|
|
I := 0;
|
|||
|
|
while not (P[I] in Separators) do
|
|||
|
|
Inc(I);
|
|||
|
|
SetString(Result, P, I);
|
|||
|
|
P2 := P + I;
|
|||
|
|
end;
|
|||
|
|
|
|||
|
|
function ReplaceString(S: string; const OldPattern, NewPattern: string): string;
|
|||
|
|
var
|
|||
|
|
LW: Integer;
|
|||
|
|
P: PChar;
|
|||
|
|
Sm: Integer;
|
|||
|
|
begin
|
|||
|
|
LW := Length(OldPattern);
|
|||
|
|
P := StrPos(PChar(S), PChar(OldPattern));
|
|||
|
|
while P <> nil do
|
|||
|
|
begin
|
|||
|
|
Sm := P - PChar(S);
|
|||
|
|
S := Copy(S, 1, Sm) + NewPattern + Copy(S, Sm + LW + 1, Length(S));
|
|||
|
|
P := StrPos(PChar(S) + Sm + Length(NewPattern), PChar(OldPattern));
|
|||
|
|
end;
|
|||
|
|
Result := S;
|
|||
|
|
end;
|
|||
|
|
|
|||
|
|
function ReplaceStrings1(S: string; const Word, Frase: string): string;
|
|||
|
|
begin
|
|||
|
|
Result := ReplaceString(S, Word, Frase);
|
|||
|
|
end;
|
|||
|
|
|
|||
|
|
function ConcatSep(const S, S2, Separator: string): string;
|
|||
|
|
begin
|
|||
|
|
Result := S;
|
|||
|
|
if Result <> '' then
|
|||
|
|
Result := Result + Separator;
|
|||
|
|
Result := Result + S2;
|
|||
|
|
end;
|
|||
|
|
|
|||
|
|
function ConcatLeftSep(const S, S2, Separator: string): string;
|
|||
|
|
begin
|
|||
|
|
Result := S;
|
|||
|
|
if Result <> '' then
|
|||
|
|
Result := Separator + Result;
|
|||
|
|
Result := S2 + Result;
|
|||
|
|
end;
|
|||
|
|
|
|||
|
|
function MinimizeString(const S: string; const MaxLen: Integer): string;
|
|||
|
|
begin
|
|||
|
|
if Length(S) > MaxLen then
|
|||
|
|
if MaxLen < 3 then
|
|||
|
|
Result := Copy(S, 1, MaxLen)
|
|||
|
|
else
|
|||
|
|
Result := Copy(S, 1, MaxLen - 3) + '...'
|
|||
|
|
else
|
|||
|
|
Result := S;
|
|||
|
|
end;
|
|||
|
|
|
|||
|
|
function TrueInflateRect(const R: TRect; const I: Integer): TRect;
|
|||
|
|
begin
|
|||
|
|
with R do
|
|||
|
|
SetRect(Result, Left - I, Top - I, Right + I, Bottom + I);
|
|||
|
|
end;
|
|||
|
|
|
|||
|
|
procedure SetWindowTop(const Handle: HWND; const Top: Boolean);
|
|||
|
|
const
|
|||
|
|
TopFlag: array [Boolean] of Longword = (HWND_NOTOPMOST, HWND_TOPMOST);
|
|||
|
|
begin
|
|||
|
|
SetWindowPos(Handle, TopFlag[Top], 0, 0, 0, 0, SWP_NOMOVE or
|
|||
|
|
SWP_NOSIZE or SWP_NOACTIVATE);
|
|||
|
|
end;
|
|||
|
|
|
|||
|
|
{* from unit FileCtrl}
|
|||
|
|
|
|||
|
|
function DirectoryExists(const Name: string): Boolean;
|
|||
|
|
var
|
|||
|
|
Code: Integer;
|
|||
|
|
begin
|
|||
|
|
Code := Integer(GetFileAttributes(PChar(Name)));
|
|||
|
|
Result := (Code <> -1) and (FILE_ATTRIBUTE_DIRECTORY and Code <> 0);
|
|||
|
|
end;
|
|||
|
|
|
|||
|
|
procedure ForceDirectories(Dir: string);
|
|||
|
|
begin
|
|||
|
|
if Dir[Length(Dir)] = '\' then
|
|||
|
|
Delete(Dir, Length(Dir), 1);
|
|||
|
|
if (Length(Dir) < 3) or DirectoryExists(Dir) or (ExtractFilePath(Dir) = Dir) then
|
|||
|
|
Exit; { avoid 'xyz:\' problem.}
|
|||
|
|
ForceDirectories(ExtractFilePath(Dir));
|
|||
|
|
CreateDir(Dir);
|
|||
|
|
end;
|
|||
|
|
|
|||
|
|
{# from unit FileCtrl}
|
|||
|
|
|
|||
|
|
function LZFileExpand(const FileSource, FileDest: string): Boolean;
|
|||
|
|
type
|
|||
|
|
TLZCopy = function(Source, Dest: Integer): Longint; stdcall;
|
|||
|
|
TLZOpenFile = function(Filename: PChar; var ReOpenBuff: TOFStruct; Style: Word): Integer; stdcall;
|
|||
|
|
TLZClose = procedure(hFile: Integer); stdcall;
|
|||
|
|
var
|
|||
|
|
Source, Dest: Integer;
|
|||
|
|
OSSource, OSDest: TOFSTRUCT;
|
|||
|
|
Res: Integer;
|
|||
|
|
Ins: Integer;
|
|||
|
|
LZCopy: TLZCopy;
|
|||
|
|
LZOpenFile: TLZOpenFile;
|
|||
|
|
LZClose: TLZClose;
|
|||
|
|
begin
|
|||
|
|
Result := False;
|
|||
|
|
Ins := LoadLibrary('LZ32.dll');
|
|||
|
|
try
|
|||
|
|
LZCopy := GetProcAddress(Ins, 'LZCopy');
|
|||
|
|
LZOpenFile := GetProcAddress(Ins, 'LZOpenFileA');
|
|||
|
|
LZClose := GetProcAddress(Ins, 'LZClose');
|
|||
|
|
OSSource.cBytes := SizeOf(TOFSTRUCT);
|
|||
|
|
OSDest.cBytes := SizeOf(TOFSTRUCT);
|
|||
|
|
Source := LZOpenFile(
|
|||
|
|
PChar(FileSource), // address of name of file to be opened
|
|||
|
|
OSSource, // address of open file structure
|
|||
|
|
OF_READ or OF_SHARE_DENY_NONE);// action to take
|
|||
|
|
if Source < 0 then
|
|||
|
|
begin
|
|||
|
|
DeleteFile(FileDest);
|
|||
|
|
Dest := LZOpenFile(
|
|||
|
|
PChar(FileDest), // address of name of file to be opened
|
|||
|
|
OSDest, // address of open file structure
|
|||
|
|
OF_CREATE or OF_WRITE or OF_SHARE_EXCLUSIVE); // action to take
|
|||
|
|
if Dest >= 0 then
|
|||
|
|
begin
|
|||
|
|
Res := LZCopy(Source, Dest);
|
|||
|
|
if Res >= 0 then
|
|||
|
|
Result := True;
|
|||
|
|
end;
|
|||
|
|
LZClose(Source);
|
|||
|
|
LZClose(Dest);
|
|||
|
|
end;
|
|||
|
|
finally
|
|||
|
|
FreeLibrary(Ins);
|
|||
|
|
end;
|
|||
|
|
end;
|
|||
|
|
|
|||
|
|
procedure Dos2Win(var S: string);
|
|||
|
|
var
|
|||
|
|
I: Integer;
|
|||
|
|
begin
|
|||
|
|
for I := 1 to Length(S) do
|
|||
|
|
case S[I] of
|
|||
|
|
#$80..#$AF:
|
|||
|
|
S[I] := Char(Byte(S[I]) + (192 - $80));
|
|||
|
|
#$E0..#$EF:
|
|||
|
|
S[I] := Char(Byte(S[I]) + (240 - $E0));
|
|||
|
|
end;
|
|||
|
|
end;
|
|||
|
|
|
|||
|
|
procedure Win2Dos(var S: string);
|
|||
|
|
var
|
|||
|
|
I: Integer;
|
|||
|
|
begin
|
|||
|
|
for I := 1 to Length(S) do
|
|||
|
|
case S[I] of
|
|||
|
|
#$C0..#$EF:
|
|||
|
|
S[I] := Char(Byte(S[I]) - (192 - $80));
|
|||
|
|
#$F0..#$FF:
|
|||
|
|
S[I] := Char(Byte(S[I]) - (240 - $E0));
|
|||
|
|
end;
|
|||
|
|
end;
|
|||
|
|
|
|||
|
|
function Dos2WinRes(const S: string): string;
|
|||
|
|
begin
|
|||
|
|
Result := S;
|
|||
|
|
Dos2Win(Result);
|
|||
|
|
end;
|
|||
|
|
|
|||
|
|
function Win2DosRes(const S: string): string;
|
|||
|
|
begin
|
|||
|
|
Result := S;
|
|||
|
|
Win2Dos(Result);
|
|||
|
|
end;
|
|||
|
|
|
|||
|
|
function Win2Koi(const S: string): string;
|
|||
|
|
const
|
|||
|
|
W = '<27><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ũ<EFBFBD><C5A8><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>';
|
|||
|
|
K = '<27><><EFBFBD><EFBFBD><EFBFBD>ţ<EFBFBD><C5A3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>';
|
|||
|
|
var
|
|||
|
|
I, J: Integer;
|
|||
|
|
begin
|
|||
|
|
Result := S;
|
|||
|
|
for I := 1 to Length(Result) do
|
|||
|
|
begin
|
|||
|
|
J := Pos(Result[I], W);
|
|||
|
|
if J > 0 then
|
|||
|
|
Result[I] := K[J];
|
|||
|
|
end;
|
|||
|
|
end;
|
|||
|
|
|
|||
|
|
function Spaces(const N: Integer): string;
|
|||
|
|
begin
|
|||
|
|
// (rom) reimplemented
|
|||
|
|
Result := AddSpaces('', N);
|
|||
|
|
end;
|
|||
|
|
|
|||
|
|
function AddSpaces(const S: string; const N: Integer): string;
|
|||
|
|
begin
|
|||
|
|
// (rom) SLOOOOW implementation
|
|||
|
|
Result := S;
|
|||
|
|
while Length(Result) < N do
|
|||
|
|
Result := Result + ' ';
|
|||
|
|
end;
|
|||
|
|
|
|||
|
|
function KeyPressed(VK: Integer): Boolean;
|
|||
|
|
begin
|
|||
|
|
Result := GetKeyState(VK) and $8000 = $8000;
|
|||
|
|
end;
|
|||
|
|
|
|||
|
|
{$IFNDEF BCB1}
|
|||
|
|
function BrowseForFolder(const Handle: HWND; const Title: string; var Folder: string): Boolean;
|
|||
|
|
{$IFDEF COMPILER2}
|
|||
|
|
type
|
|||
|
|
TSHItemID = packed record { mkid }
|
|||
|
|
cb: Word; { Size of the ID (including cb itself) }
|
|||
|
|
abID: array [0..0] of Byte; { The item ID (variable Length) }
|
|||
|
|
end;
|
|||
|
|
PItemIDList = ^TItemIDList;
|
|||
|
|
TItemIDList = packed record { idl }
|
|||
|
|
mkid: TSHItemID;
|
|||
|
|
end;
|
|||
|
|
TFNBFFCallBack = function(Wnd: HWND; uMsg: UINT; lParam, lpData: LPARAM): Integer stdcall;
|
|||
|
|
TBrowseInfo = packed record
|
|||
|
|
hwndOwner: HWND;
|
|||
|
|
pidlRoot: PItemIDList;
|
|||
|
|
pszDisplayName: PAnsiChar; { Return display name of item selected. }
|
|||
|
|
lpszTitle: PAnsiChar; { text to go in the banner over the tree. }
|
|||
|
|
ulFlags: UINT; { Flags that control the return stuff }
|
|||
|
|
lpfn: TFNBFFCallBack;
|
|||
|
|
lParam: LPARAM; { extra info that's passed back in callbacks }
|
|||
|
|
iImage: Integer; { output var: where to return the Image Index. }
|
|||
|
|
end;
|
|||
|
|
|
|||
|
|
function SHBrowseForFolder(var lpbi: TBrowseInfo): PItemIDList; stdcall; external 'shell32.dll' name
|
|||
|
|
'SHBrowseForFolderA';
|
|||
|
|
|
|||
|
|
function SHGetPathFromIDList(pidl: PItemIDList; pszPath: PChar): BOOL; stdcall external 'shell32.dll' name
|
|||
|
|
'SHGetPathFromIDListA';
|
|||
|
|
{$ENDIF}
|
|||
|
|
var
|
|||
|
|
BrowseInfo: TBrowseInfo;
|
|||
|
|
Id: PItemIDList;
|
|||
|
|
FN: array [0..MAX_PATH] of Char;
|
|||
|
|
begin
|
|||
|
|
with BrowseInfo do
|
|||
|
|
begin
|
|||
|
|
hwndOwner := Handle;
|
|||
|
|
pidlRoot := nil;
|
|||
|
|
pszDisplayName := FN;
|
|||
|
|
lpszTitle := PChar(Title);
|
|||
|
|
ulFlags := 0;
|
|||
|
|
lpfn := nil;
|
|||
|
|
end;
|
|||
|
|
Id := SHBrowseForFolder(BrowseInfo);
|
|||
|
|
Result := Id <> nil;
|
|||
|
|
if Result then
|
|||
|
|
begin
|
|||
|
|
SHGetPathFromIDList(Id, FN);
|
|||
|
|
Folder := FN;
|
|||
|
|
end;
|
|||
|
|
end;
|
|||
|
|
{$ENDIF BCB1}
|
|||
|
|
|
|||
|
|
function LastDate(const Dat: TDateTime): string;
|
|||
|
|
const
|
|||
|
|
D2D: array [0..9] of 1..3 = (3, 1, 2, 2, 2, 3, 3, 3, 3, 3);
|
|||
|
|
Day: array [1..3] of string = ('<27><><EFBFBD><EFBFBD>', '<27><><EFBFBD>', '<27><><EFBFBD><EFBFBD>');
|
|||
|
|
Month: array [1..3] of string = ('<27><><EFBFBD><EFBFBD><EFBFBD>', '<27><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>', '<27><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>');
|
|||
|
|
Year: array [1..3] of string = ('<27><><EFBFBD>', '<27><><EFBFBD><EFBFBD>', '<27><><EFBFBD>');
|
|||
|
|
Week: array [1..4] of string = ('<27><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>', '2 <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>', '3 <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>', '<27><><EFBFBD><EFBFBD><EFBFBD>');
|
|||
|
|
var
|
|||
|
|
Y, M, D: Integer;
|
|||
|
|
begin
|
|||
|
|
if Date = Dat then
|
|||
|
|
Result := '<27><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>'
|
|||
|
|
else
|
|||
|
|
if Dat = Date - 1 then
|
|||
|
|
Result := '<27><><EFBFBD><EFBFBD><EFBFBD>'
|
|||
|
|
else
|
|||
|
|
if Dat = Date - 2 then
|
|||
|
|
Result := '<27><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>'
|
|||
|
|
else
|
|||
|
|
if Dat > Date then
|
|||
|
|
Result := '<27> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>'
|
|||
|
|
else
|
|||
|
|
begin
|
|||
|
|
D := Trunc(Date - Dat);
|
|||
|
|
Y := Round(D / 365);
|
|||
|
|
M := Round(D / 30);
|
|||
|
|
if Y > 0 then
|
|||
|
|
Result := IntToStr(Y) + ' ' + Year[D2D[StrToInt(IntToStr(Y)[Length(IntToStr(Y))])]] + ' <20><><EFBFBD><EFBFBD><EFBFBD>'
|
|||
|
|
else
|
|||
|
|
if M > 0 then
|
|||
|
|
Result := IntToStr(M) + ' ' + Month[D2D[StrToInt(IntToStr(M)[Length(IntToStr(M))])]] + ' <20><><EFBFBD><EFBFBD><EFBFBD>'
|
|||
|
|
else
|
|||
|
|
if D > 6 then
|
|||
|
|
Result := Week[D div 7] + ' <20><><EFBFBD><EFBFBD><EFBFBD>'
|
|||
|
|
else
|
|||
|
|
if D > 0 then
|
|||
|
|
Result := IntToStr(D) + ' ' + Day[D2D[StrToInt(IntToStr(D)[Length(IntToStr(D))])]] + ' <20><><EFBFBD><EFBFBD><EFBFBD>'
|
|||
|
|
end;
|
|||
|
|
end;
|
|||
|
|
|
|||
|
|
procedure AddSlash(var Dir: TFileName);
|
|||
|
|
begin
|
|||
|
|
if (Length(Dir) > 0) and (Dir[Length(Dir)] <> '\') then
|
|||
|
|
Dir := Dir + '\';
|
|||
|
|
end;
|
|||
|
|
|
|||
|
|
function AddSlash2(const Dir: TFileName): string;
|
|||
|
|
begin
|
|||
|
|
Result := Dir;
|
|||
|
|
if (Length(Dir) > 0) and (Dir[Length(Dir)] <> '\') then
|
|||
|
|
Result := Dir + '\';
|
|||
|
|
end;
|
|||
|
|
|
|||
|
|
function AddPath(const FileName, Path: TFileName): TFileName;
|
|||
|
|
begin
|
|||
|
|
if ExtractFileDrive(FileName) = '' then
|
|||
|
|
Result := AddSlash2(Path) + FileName
|
|||
|
|
else
|
|||
|
|
Result := FileName;
|
|||
|
|
end;
|
|||
|
|
|
|||
|
|
function AddPaths(const PathList, Path: string): string;
|
|||
|
|
var
|
|||
|
|
I: Integer;
|
|||
|
|
S: string;
|
|||
|
|
begin
|
|||
|
|
Result := '';
|
|||
|
|
I := 0;
|
|||
|
|
S := SubStr(PathList, I, ';');
|
|||
|
|
while S <> '' do
|
|||
|
|
begin
|
|||
|
|
Result := ConcatSep(Result, AddPath(S, Path), ';');
|
|||
|
|
Inc(I);
|
|||
|
|
S := SubStr(PathList, I, ';');
|
|||
|
|
end;
|
|||
|
|
end;
|
|||
|
|
|
|||
|
|
function ParentPath(const Path: TFileName): TFileName;
|
|||
|
|
begin
|
|||
|
|
Result := Path;
|
|||
|
|
if (Length(Result) > 0) and (Result[Length(Result)] = '\') then
|
|||
|
|
Delete(Result, Length(Result), 1);
|
|||
|
|
Result := ExtractFilePath(Result);
|
|||
|
|
end;
|
|||
|
|
|
|||
|
|
function FindInPath(const FileName, PathList: string): TFileName;
|
|||
|
|
var
|
|||
|
|
I: Integer;
|
|||
|
|
S: string;
|
|||
|
|
begin
|
|||
|
|
I := 0;
|
|||
|
|
S := SubStr(PathList, I, ';');
|
|||
|
|
while S <> '' do
|
|||
|
|
begin
|
|||
|
|
Result := AddSlash2(S) + FileName;
|
|||
|
|
if FileExists(Result) then
|
|||
|
|
Exit;
|
|||
|
|
Inc(I);
|
|||
|
|
S := SubStr(PathList, I, ';');
|
|||
|
|
end;
|
|||
|
|
Result := '';
|
|||
|
|
end;
|
|||
|
|
|
|||
|
|
function GetComputerID: string;
|
|||
|
|
var
|
|||
|
|
SN: DWORD;
|
|||
|
|
Nul: DWORD;
|
|||
|
|
WinDir: array [0..MAX_PATH] of Char;
|
|||
|
|
begin
|
|||
|
|
GetWindowsDirectory(WinDir, MAX_PATH);
|
|||
|
|
WinDir[3] := #0;
|
|||
|
|
if GetVolumeInformation(
|
|||
|
|
WinDir, // address of root directory of the file system
|
|||
|
|
nil, // address of name of the volume
|
|||
|
|
0, // Length of lpVolumeNameBuffer
|
|||
|
|
@SN, // address of volume serial number
|
|||
|
|
Nul, // address of system's maximum filename Length
|
|||
|
|
Nul, // address of file system flags
|
|||
|
|
nil, // address of name of file system
|
|||
|
|
0) // Length of lpFileSystemNameBuffer
|
|||
|
|
then
|
|||
|
|
Result := IntToHex(SN, 8)
|
|||
|
|
else
|
|||
|
|
Result := 'None';
|
|||
|
|
end;
|
|||
|
|
|
|||
|
|
function CurrencyToStr(const Cur: currency): string;
|
|||
|
|
begin
|
|||
|
|
Result := CurrToStrF(Cur, ffCurrency, CurrencyDecimals)
|
|||
|
|
end;
|
|||
|
|
|
|||
|
|
function Cmp(const S1, S2: string): Boolean;
|
|||
|
|
begin
|
|||
|
|
//Result := AnsiCompareText(S1, S2) = 0;
|
|||
|
|
Result := AnsiStrIComp(PChar(S1), PChar(S2)) = 0;
|
|||
|
|
end;
|
|||
|
|
|
|||
|
|
function StringCat(var S1: string; S2: string): string;
|
|||
|
|
begin
|
|||
|
|
S1 := S1 + S2;
|
|||
|
|
Result := S1;
|
|||
|
|
end;
|
|||
|
|
|
|||
|
|
function HasChar(const Ch: Char; const S: string): Boolean;
|
|||
|
|
begin
|
|||
|
|
Result := Pos(Ch, S) > 0;
|
|||
|
|
end;
|
|||
|
|
|
|||
|
|
function HasAnyChar(const Chars: string; const S: string): Boolean;
|
|||
|
|
var
|
|||
|
|
I: Integer;
|
|||
|
|
begin
|
|||
|
|
for I := 1 to Length(Chars) do
|
|||
|
|
if HasChar(Chars[I], S) then
|
|||
|
|
begin
|
|||
|
|
Result := True;
|
|||
|
|
Exit;
|
|||
|
|
end;
|
|||
|
|
Result := False;
|
|||
|
|
end;
|
|||
|
|
|
|||
|
|
function CountOfChar(const Ch: Char; const S: string): Integer;
|
|||
|
|
var
|
|||
|
|
I: Integer;
|
|||
|
|
begin
|
|||
|
|
Result := 0;
|
|||
|
|
for I := 1 to Length(S) do
|
|||
|
|
if S[I] = Ch then
|
|||
|
|
Inc(Result);
|
|||
|
|
end;
|
|||
|
|
|
|||
|
|
procedure SwapInt(var Int1, Int2: Integer);
|
|||
|
|
var
|
|||
|
|
Tmp: Integer;
|
|||
|
|
begin
|
|||
|
|
Tmp := Int1;
|
|||
|
|
Int1 := Int2;
|
|||
|
|
Int2 := Tmp;
|
|||
|
|
end;
|
|||
|
|
|
|||
|
|
function DeleteReadOnlyFile(const FileName: TFileName): Boolean;
|
|||
|
|
begin
|
|||
|
|
FileSetAttr(FileName, 0); {clear Read Only Flag}
|
|||
|
|
Result := DeleteFile(FileName);
|
|||
|
|
end;
|
|||
|
|
|
|||
|
|
function HasParam(const Param: string): Boolean;
|
|||
|
|
var
|
|||
|
|
I: Integer;
|
|||
|
|
begin
|
|||
|
|
Result := False;
|
|||
|
|
for I := 1 to ParamCount do
|
|||
|
|
begin
|
|||
|
|
Result := Cmp(ParamStr(I), Param);
|
|||
|
|
if Result then
|
|||
|
|
Exit;
|
|||
|
|
end;
|
|||
|
|
end;
|
|||
|
|
|
|||
|
|
function HasSwitch(const Param: string): Boolean;
|
|||
|
|
var
|
|||
|
|
I: Integer;
|
|||
|
|
begin
|
|||
|
|
Result := False;
|
|||
|
|
for I := 1 to ParamCount do
|
|||
|
|
if HasChar(ParamStr(I)[1], '-/') then
|
|||
|
|
begin
|
|||
|
|
Result := Cmp(Copy(ParamStr(I), 2, Length(Param)), Param);
|
|||
|
|
if Result then
|
|||
|
|
Exit;
|
|||
|
|
end;
|
|||
|
|
end;
|
|||
|
|
|
|||
|
|
function Switch(const Param: string): string;
|
|||
|
|
var
|
|||
|
|
I: Integer;
|
|||
|
|
begin
|
|||
|
|
Result := '';
|
|||
|
|
for I := 1 to ParamCount do
|
|||
|
|
if HasChar(ParamStr(I)[1], '-/\') and
|
|||
|
|
Cmp(Copy(ParamStr(I), 2, Length(Param)), Param) then
|
|||
|
|
begin
|
|||
|
|
Result := Copy(ParamStr(I), 2 + Length(Param), 260);
|
|||
|
|
Exit;
|
|||
|
|
end;
|
|||
|
|
end;
|
|||
|
|
|
|||
|
|
function ExePath: TFileName;
|
|||
|
|
begin
|
|||
|
|
Result := ExtractFilePath(ParamStr(0));
|
|||
|
|
end;
|
|||
|
|
|
|||
|
|
function FileNewExt(const FileName, NewExt: TFileName): TFileName;
|
|||
|
|
begin
|
|||
|
|
Result := Copy(FileName, 1, Length(FileName) - Length(ExtractFileExt(FileName))) + NewExt;
|
|||
|
|
end;
|
|||
|
|
|
|||
|
|
{$IFNDEF COMPILER3_UP}
|
|||
|
|
|
|||
|
|
function AnsiStrLIComp(S1, S2: PChar; MaxLen: Cardinal): Integer;
|
|||
|
|
begin
|
|||
|
|
Result := CompareString(LOCALE_USER_DEFAULT, NORM_IGNORECASE,
|
|||
|
|
S1, MaxLen, S2, MaxLen) - 2;
|
|||
|
|
end;
|
|||
|
|
|
|||
|
|
function AnsiStrIComp(S1, S2: PChar): Integer;
|
|||
|
|
begin
|
|||
|
|
Result := CompareString(LOCALE_USER_DEFAULT, NORM_IGNORECASE, S1, -1,
|
|||
|
|
S2, -1) - 2;
|
|||
|
|
end;
|
|||
|
|
|
|||
|
|
{$ENDIF}
|
|||
|
|
|
|||
|
|
function CharInSet(const Ch: Char; const SetOfChar: TSetOfChar): Boolean;
|
|||
|
|
begin
|
|||
|
|
{$IFDEF DELPHI}
|
|||
|
|
Result := Ch in SetOfChar;
|
|||
|
|
{$ENDIF DELPHI}
|
|||
|
|
{$IFDEF BCB}
|
|||
|
|
Result := Pos(Ch, SetOfChar) > 0;
|
|||
|
|
{$ENDIF BCB}
|
|||
|
|
end;
|
|||
|
|
|
|||
|
|
function IntPower(Base, Exponent: Integer): Integer;
|
|||
|
|
begin
|
|||
|
|
if Exponent > 0 then
|
|||
|
|
begin
|
|||
|
|
Result := Base;
|
|||
|
|
Dec(Exponent);
|
|||
|
|
while Exponent > 0 do
|
|||
|
|
begin
|
|||
|
|
Result := Result * Base;
|
|||
|
|
Dec(Exponent);
|
|||
|
|
end;
|
|||
|
|
end
|
|||
|
|
else
|
|||
|
|
if Exponent < 0 then
|
|||
|
|
begin
|
|||
|
|
Result := 1;
|
|||
|
|
Inc(Exponent);
|
|||
|
|
while Exponent < 0 do
|
|||
|
|
begin
|
|||
|
|
Result := Result div Base;
|
|||
|
|
Inc(Exponent);
|
|||
|
|
end;
|
|||
|
|
end
|
|||
|
|
else
|
|||
|
|
Result := Base;
|
|||
|
|
end;
|
|||
|
|
|
|||
|
|
function ChangeTopException(E: TObject): TObject;
|
|||
|
|
type
|
|||
|
|
PRaiseFrame = ^TRaiseFrame;
|
|||
|
|
TRaiseFrame = record
|
|||
|
|
NextRaise: PRaiseFrame;
|
|||
|
|
ExceptAddr: Pointer;
|
|||
|
|
ExceptObject: TObject;
|
|||
|
|
ExceptionRecord: PExceptionRecord;
|
|||
|
|
end;
|
|||
|
|
begin
|
|||
|
|
{ CBuilder 3 Warning !}
|
|||
|
|
{ if linker error occured with message "unresolved external 'System::RaiseList'" try
|
|||
|
|
comment this function implementation, compile,
|
|||
|
|
then uncomment and compile again. }
|
|||
|
|
{$IFDEF COMPILER6_UP}
|
|||
|
|
{$WARN SYMBOL_DEPRECATED OFF}
|
|||
|
|
{$ENDIF}
|
|||
|
|
if RaiseList <> nil then
|
|||
|
|
begin
|
|||
|
|
Result := PRaiseFrame(RaiseList)^.ExceptObject;
|
|||
|
|
PRaiseFrame(RaiseList)^.ExceptObject := E
|
|||
|
|
end
|
|||
|
|
else
|
|||
|
|
Result := nil;
|
|||
|
|
// raise Exception.Create('Not in exception');
|
|||
|
|
end;
|
|||
|
|
|
|||
|
|
function MakeValidFileName(const FileName: TFileName;
|
|||
|
|
const ReplaceBadChar: Char): TFileName;
|
|||
|
|
var
|
|||
|
|
I: Integer;
|
|||
|
|
begin
|
|||
|
|
Result := FileName;
|
|||
|
|
for I := 1 to Length(Result) do
|
|||
|
|
if HasChar(Result[I], '''":?*\/') then
|
|||
|
|
Result[I] := ReplaceBadChar;
|
|||
|
|
end;
|
|||
|
|
|
|||
|
|
function Var2Type(V: Variant; const VarType: Integer): Variant;
|
|||
|
|
begin
|
|||
|
|
if TVarData(V).VType in [varEmpty, varNull] then
|
|||
|
|
begin
|
|||
|
|
case VarType of
|
|||
|
|
varString, varOleStr:
|
|||
|
|
Result := '';
|
|||
|
|
varInteger, varSmallint, varByte:
|
|||
|
|
Result := 0;
|
|||
|
|
varBoolean:
|
|||
|
|
Result := False;
|
|||
|
|
varSingle, varDouble, varCurrency, varDate:
|
|||
|
|
Result := 0.0;
|
|||
|
|
varVariant:
|
|||
|
|
Result := Null;
|
|||
|
|
else
|
|||
|
|
Result := VarAsType(V, VarType);
|
|||
|
|
end;
|
|||
|
|
end
|
|||
|
|
else
|
|||
|
|
Result := VarAsType(V, VarType);
|
|||
|
|
if (VarType = varInteger) and (TVarData(V).VType = varBoolean) then
|
|||
|
|
Result := Integer(V = True);
|
|||
|
|
end;
|
|||
|
|
|
|||
|
|
function VarToInt(V: Variant): Integer;
|
|||
|
|
begin
|
|||
|
|
Result := Var2Type(V, varInteger);
|
|||
|
|
end;
|
|||
|
|
|
|||
|
|
function VarToFloat(V: Variant): Double;
|
|||
|
|
begin
|
|||
|
|
Result := Var2Type(V, varDouble);
|
|||
|
|
end;
|
|||
|
|
|
|||
|
|
function CopyDir(const SourceDir, DestDir: TFileName): Boolean;
|
|||
|
|
var
|
|||
|
|
SearchRec: TSearchRec;
|
|||
|
|
DosError: Integer;
|
|||
|
|
Path, DestPath: TFileName;
|
|||
|
|
begin
|
|||
|
|
Result := False;
|
|||
|
|
if not CreateDir(DestDir) then
|
|||
|
|
Exit;
|
|||
|
|
Path := SourceDir;
|
|||
|
|
DestPath := AddSlash2(DestDir);
|
|||
|
|
AddSlash(Path);
|
|||
|
|
DosError := FindFirst(Path + '*.*', faAnyFile, SearchRec);
|
|||
|
|
while DosError = 0 do
|
|||
|
|
begin
|
|||
|
|
if (SearchRec.Name <> '.') and (SearchRec.Name <> '..') then
|
|||
|
|
begin
|
|||
|
|
if (SearchRec.Attr and faDirectory) = faDirectory then
|
|||
|
|
Result := CopyDir(Path + SearchRec.Name, AddSlash2(DestDir) + SearchRec.Name)
|
|||
|
|
else
|
|||
|
|
Result := CopyFile(PChar(Path + SearchRec.Name),
|
|||
|
|
PChar(DestPath + SearchRec.Name), True);
|
|||
|
|
if not Result then
|
|||
|
|
Exit;
|
|||
|
|
end;
|
|||
|
|
DosError := FindNext(SearchRec);
|
|||
|
|
end;
|
|||
|
|
FindClose(SearchRec);
|
|||
|
|
Result := True;
|
|||
|
|
end;
|
|||
|
|
|
|||
|
|
function FileTimeToDateTime(const FT: TFileTime): TDateTime;
|
|||
|
|
var
|
|||
|
|
LocalFileTime: TFileTime;
|
|||
|
|
FileDate: Integer;
|
|||
|
|
begin
|
|||
|
|
FileTimeToLocalFileTime(FT, LocalFileTime);
|
|||
|
|
FileTimeToDosDateTime(LocalFileTime, LongRec(FileDate).Hi, LongRec(FileDate).Lo);
|
|||
|
|
Result := FileDateToDateTime(FileDate);
|
|||
|
|
end;
|
|||
|
|
|
|||
|
|
function DefStr(const S: string; Default: string): string;
|
|||
|
|
begin
|
|||
|
|
if S <> '' then
|
|||
|
|
Result := S
|
|||
|
|
else
|
|||
|
|
Result := Default;
|
|||
|
|
end;
|
|||
|
|
|
|||
|
|
function GetComputerName: string;
|
|||
|
|
var
|
|||
|
|
nSize: DWORD;
|
|||
|
|
begin
|
|||
|
|
nSize := MAX_COMPUTERNAME_LENGTH + 1;
|
|||
|
|
SetLength(Result, nSize);
|
|||
|
|
if Windows.GetComputerName(
|
|||
|
|
PChar(Result), // address of name buffer
|
|||
|
|
nSize) then // address of size of name buffer
|
|||
|
|
SetLength(Result, nSize)
|
|||
|
|
else
|
|||
|
|
Result := '';
|
|||
|
|
end;
|
|||
|
|
|
|||
|
|
function StrToBool(const S: string): Boolean;
|
|||
|
|
begin
|
|||
|
|
Result := (S = '1') or Cmp(S, 'True') or Cmp(S, 'yes');
|
|||
|
|
end;
|
|||
|
|
|
|||
|
|
procedure LoadIcoToImage(ALarge, ASmall: TImageList; const NameRes: string);
|
|||
|
|
var
|
|||
|
|
Ico: TIcon;
|
|||
|
|
begin
|
|||
|
|
Ico := TIcon.Create;
|
|||
|
|
if ALarge <> nil then
|
|||
|
|
begin
|
|||
|
|
Ico.Handle := LoadImage(hInstance, PChar(NameRes), IMAGE_ICON, 32, 32, 0);
|
|||
|
|
ALarge.AddIcon(Ico);
|
|||
|
|
end;
|
|||
|
|
if ASmall <> nil then
|
|||
|
|
begin
|
|||
|
|
Ico.Handle := LoadImage(hInstance, PChar(NameRes), IMAGE_ICON, 16, 16, 0);
|
|||
|
|
ASmall.AddIcon(Ico);
|
|||
|
|
end;
|
|||
|
|
Ico.Free;
|
|||
|
|
end;
|
|||
|
|
|
|||
|
|
procedure WordBreak(Canvas: TCanvas; const S: string; Ss: TStrings);
|
|||
|
|
begin
|
|||
|
|
Ss.Text := S;
|
|||
|
|
end;
|
|||
|
|
|
|||
|
|
procedure RATextOut(Canvas: TCanvas; const R, RClip: TRect; const S: string);
|
|||
|
|
begin
|
|||
|
|
RATextOutEx(Canvas, R, RClip, S, False);
|
|||
|
|
end;
|
|||
|
|
|
|||
|
|
function RATextCalcHeight(Canvas: TCanvas; const R: TRect; const S: string): Integer;
|
|||
|
|
begin
|
|||
|
|
Result := RATextOutEx(Canvas, R, R, S, True);
|
|||
|
|
end;
|
|||
|
|
|
|||
|
|
function RATextOutEx(Canvas: TCanvas; const R, RClip: TRect; const S: string; const CalcHeight: Boolean): Integer;
|
|||
|
|
var
|
|||
|
|
Ss: TStrings;
|
|||
|
|
I: Integer;
|
|||
|
|
H: Integer;
|
|||
|
|
begin
|
|||
|
|
Ss := TStringList.Create;
|
|||
|
|
try
|
|||
|
|
WordBreak(Canvas, S, Ss);
|
|||
|
|
H := Canvas.TextHeight('A');
|
|||
|
|
Result := H * Ss.Count;
|
|||
|
|
if not CalcHeight then
|
|||
|
|
for I := 0 to Ss.Count - 1 do
|
|||
|
|
ExtTextOut(
|
|||
|
|
Canvas.Handle, // handle of device context
|
|||
|
|
R.Left, // X-coordinate of reference point
|
|||
|
|
R.Top + H * I, // Y-coordinate of reference point
|
|||
|
|
ETO_CLIPPED, // text-output options
|
|||
|
|
@RClip, // optional clipping and/or opaquing rectangle
|
|||
|
|
PChar(Ss[I]),
|
|||
|
|
Length(Ss[I]), // number of characters in string
|
|||
|
|
nil); // address of array of intercharacter spacing values
|
|||
|
|
finally
|
|||
|
|
Ss.Free;
|
|||
|
|
end;
|
|||
|
|
end;
|
|||
|
|
|
|||
|
|
procedure Cinema(Canvas: TCanvas; rS, rD: TRect);
|
|||
|
|
const
|
|||
|
|
Pause = 30; {milliseconds}
|
|||
|
|
Steps = 7;
|
|||
|
|
Width = 1;
|
|||
|
|
var
|
|||
|
|
R: TRect;
|
|||
|
|
I: Integer;
|
|||
|
|
PenOld: TPen;
|
|||
|
|
|
|||
|
|
procedure FrameR(R: TRect);
|
|||
|
|
begin
|
|||
|
|
with Canvas do
|
|||
|
|
begin
|
|||
|
|
MoveTo(R.Left, R.Top);
|
|||
|
|
LineTo(R.Left, R.Bottom);
|
|||
|
|
LineTo(R.Right, R.Bottom);
|
|||
|
|
LineTo(R.Right, R.Top);
|
|||
|
|
LineTo(R.Left, R.Top);
|
|||
|
|
end;
|
|||
|
|
end;
|
|||
|
|
|
|||
|
|
procedure Frame;
|
|||
|
|
begin
|
|||
|
|
FrameR(R);
|
|||
|
|
with Canvas do
|
|||
|
|
begin
|
|||
|
|
MoveTo(rS.Left, rS.Top);
|
|||
|
|
LineTo(R.Left, R.Top);
|
|||
|
|
if R.Top <> rS.Top then
|
|||
|
|
begin
|
|||
|
|
MoveTo(rS.Right, rS.Top);
|
|||
|
|
LineTo(R.Right, R.Top);
|
|||
|
|
end;
|
|||
|
|
if R.Left <> rS.Left then
|
|||
|
|
begin
|
|||
|
|
MoveTo(rS.Left, rS.Bottom);
|
|||
|
|
LineTo(R.Left, R.Bottom);
|
|||
|
|
end;
|
|||
|
|
if (R.Bottom <> rS.Bottom) and (R.Right <> rS.Right) then
|
|||
|
|
begin
|
|||
|
|
MoveTo(rS.Right, rS.Bottom);
|
|||
|
|
LineTo(R.Right, R.Bottom);
|
|||
|
|
end;
|
|||
|
|
end;
|
|||
|
|
end;
|
|||
|
|
|
|||
|
|
begin
|
|||
|
|
PenOld := TPen.Create;
|
|||
|
|
PenOld.Assign(Canvas.Pen);
|
|||
|
|
Canvas.Pen.Mode := pmNot;
|
|||
|
|
Canvas.Pen.Width := Width;
|
|||
|
|
Canvas.Pen.Style := psDot;
|
|||
|
|
FrameR(rS);
|
|||
|
|
R := rS;
|
|||
|
|
for I := 1 to Steps do
|
|||
|
|
begin
|
|||
|
|
R.Left := rS.Left + (rD.Left - rS.Left) div Steps * I;
|
|||
|
|
R.Top := rS.Top + (rD.Top - rS.Top) div Steps * I;
|
|||
|
|
R.Bottom := rS.Bottom + (rD.Bottom - rS.Bottom) div Steps * I;
|
|||
|
|
R.Right := rS.Right + (rD.Right - rS.Right) div Steps * I;
|
|||
|
|
Frame;
|
|||
|
|
Sleep(Pause);
|
|||
|
|
Frame;
|
|||
|
|
end;
|
|||
|
|
FrameR(rS);
|
|||
|
|
Canvas.Pen.Assign(PenOld);
|
|||
|
|
end;
|
|||
|
|
|
|||
|
|
function FindFormByClass(FormClass: TFormClass): TForm;
|
|||
|
|
var
|
|||
|
|
I: Integer;
|
|||
|
|
begin
|
|||
|
|
Result := nil;
|
|||
|
|
for I := 0 to Application.ComponentCount - 1 do
|
|||
|
|
if Application.Components[I].ClassName = FormClass.ClassName then
|
|||
|
|
begin
|
|||
|
|
Result := Application.Components[I] as TForm;
|
|||
|
|
Break;
|
|||
|
|
end;
|
|||
|
|
end;
|
|||
|
|
|
|||
|
|
function FindFormByClassName(FormClassName: string): TForm;
|
|||
|
|
var
|
|||
|
|
I: Integer;
|
|||
|
|
begin
|
|||
|
|
Result := nil;
|
|||
|
|
for I := 0 to Application.ComponentCount - 1 do
|
|||
|
|
if Application.Components[I].ClassName = FormClassName then
|
|||
|
|
begin
|
|||
|
|
Result := Application.Components[I] as TForm;
|
|||
|
|
Break;
|
|||
|
|
end;
|
|||
|
|
end;
|
|||
|
|
|
|||
|
|
function FindByTag(WinControl: TWinControl; ComponentClass: TComponentClass; const Tag: Integer): TComponent;
|
|||
|
|
var
|
|||
|
|
I: Integer;
|
|||
|
|
begin
|
|||
|
|
for I := 0 to WinControl.ControlCount - 1 do
|
|||
|
|
begin
|
|||
|
|
Result := WinControl.Controls[I];
|
|||
|
|
if (Result is ComponentClass) and (Result.Tag = Tag) then
|
|||
|
|
Exit;
|
|||
|
|
end;
|
|||
|
|
Result := nil;
|
|||
|
|
end;
|
|||
|
|
|
|||
|
|
function ControlAtPos2(Parent: TWinControl; X, Y: Integer): TControl;
|
|||
|
|
var
|
|||
|
|
I: Integer;
|
|||
|
|
P: TPoint;
|
|||
|
|
begin
|
|||
|
|
P := Point(X, Y);
|
|||
|
|
for I := Parent.ControlCount - 1 downto 0 do
|
|||
|
|
begin
|
|||
|
|
Result := Parent.Controls[I];
|
|||
|
|
with Result do
|
|||
|
|
if PtInRect(BoundsRect, P) then
|
|||
|
|
Exit;
|
|||
|
|
end;
|
|||
|
|
Result := nil;
|
|||
|
|
end;
|
|||
|
|
|
|||
|
|
function RBTag(Parent: TWinControl): Integer;
|
|||
|
|
var
|
|||
|
|
RB: TRadioButton;
|
|||
|
|
I: Integer;
|
|||
|
|
begin
|
|||
|
|
RB := nil;
|
|||
|
|
with Parent do
|
|||
|
|
for I := 0 to ControlCount - 1 do
|
|||
|
|
if (Controls[I] is TRadioButton) and
|
|||
|
|
(Controls[I] as TRadioButton).Checked then
|
|||
|
|
begin
|
|||
|
|
RB := Controls[I] as TRadioButton;
|
|||
|
|
Break;
|
|||
|
|
end;
|
|||
|
|
if RB <> nil then
|
|||
|
|
Result := RB.Tag
|
|||
|
|
else
|
|||
|
|
Result := 0;
|
|||
|
|
end;
|
|||
|
|
|
|||
|
|
function IniReadSection(const IniFileName: TFileName; const Section: string; Ss: TStrings): Boolean;
|
|||
|
|
var
|
|||
|
|
F: Integer;
|
|||
|
|
S: string;
|
|||
|
|
begin
|
|||
|
|
with TStringList.Create do
|
|||
|
|
try
|
|||
|
|
LoadFromFile(IniFileName);
|
|||
|
|
F := IndexOf('[' + Section + ']');
|
|||
|
|
Result := F > -1;
|
|||
|
|
if Result then
|
|||
|
|
begin
|
|||
|
|
Ss.Clear;
|
|||
|
|
Inc(F);
|
|||
|
|
while F < Count do
|
|||
|
|
begin
|
|||
|
|
S := Strings[F];
|
|||
|
|
if (Length(S) > 0) and (Trim(S[1]) = '[') then
|
|||
|
|
Break;
|
|||
|
|
Ss.Add(S);
|
|||
|
|
Inc(F);
|
|||
|
|
end;
|
|||
|
|
end;
|
|||
|
|
finally
|
|||
|
|
Free;
|
|||
|
|
end;
|
|||
|
|
end;
|
|||
|
|
|
|||
|
|
procedure SaveTextFile(const FileName: TFileName; const Source: string);
|
|||
|
|
begin
|
|||
|
|
with TStringList.Create do
|
|||
|
|
try
|
|||
|
|
Text := Source;
|
|||
|
|
SaveToFile(FileName);
|
|||
|
|
finally
|
|||
|
|
Free;
|
|||
|
|
end;
|
|||
|
|
end;
|
|||
|
|
|
|||
|
|
function LoadTextFile(const FileName: TFileName): string;
|
|||
|
|
begin
|
|||
|
|
with TStringList.Create do
|
|||
|
|
try
|
|||
|
|
LoadFromFile(FileName);
|
|||
|
|
Result := Text;
|
|||
|
|
finally
|
|||
|
|
Free;
|
|||
|
|
end;
|
|||
|
|
end;
|
|||
|
|
|
|||
|
|
function ReadFolder(const Folder, Mask: TFileName; FileList: TStrings): Integer;
|
|||
|
|
var
|
|||
|
|
SearchRec: TSearchRec;
|
|||
|
|
DosError: Integer;
|
|||
|
|
begin
|
|||
|
|
FileList.Clear;
|
|||
|
|
Result := FindFirst(AddSlash2(Folder) + Mask, faAnyFile, SearchRec);
|
|||
|
|
DosError := Result;
|
|||
|
|
while DosError = 0 do
|
|||
|
|
begin
|
|||
|
|
if not ((SearchRec.Attr and faDirectory) = faDirectory) then
|
|||
|
|
FileList.Add(SearchRec.Name);
|
|||
|
|
DosError := FindNext(SearchRec);
|
|||
|
|
end;
|
|||
|
|
FindClose(SearchRec);
|
|||
|
|
end;
|
|||
|
|
|
|||
|
|
function ReadFolders(const Folder: TFileName; FolderList: TStrings): Integer;
|
|||
|
|
var
|
|||
|
|
SearchRec: TSearchRec;
|
|||
|
|
DosError: Integer;
|
|||
|
|
begin
|
|||
|
|
FolderList.Clear;
|
|||
|
|
Result := FindFirst(AddSlash2(Folder) + '*.*', faAnyFile, SearchRec);
|
|||
|
|
DosError := Result;
|
|||
|
|
while DosError = 0 do
|
|||
|
|
begin
|
|||
|
|
if ((SearchRec.Attr and faDirectory) = faDirectory) and
|
|||
|
|
(SearchRec.Name <> '.') and (SearchRec.Name <> '..') then
|
|||
|
|
FolderList.Add(SearchRec.Name);
|
|||
|
|
DosError := FindNext(SearchRec);
|
|||
|
|
end;
|
|||
|
|
FindClose(SearchRec);
|
|||
|
|
end;
|
|||
|
|
|
|||
|
|
{$IFDEF COMPILER3_UP}
|
|||
|
|
|
|||
|
|
function TargetFileName(const FileName: TFileName): TFileName;
|
|||
|
|
begin
|
|||
|
|
Result := FileName;
|
|||
|
|
if Cmp(ExtractFileExt(FileName), '.lnk') then
|
|||
|
|
if ResolveLink(Application.Handle, FileName, Result) <> 0 then
|
|||
|
|
raise Exception.CreateFmt(SCantGetShortCut, [FileName]);
|
|||
|
|
end;
|
|||
|
|
|
|||
|
|
function ResolveLink(const hWnd: HWND; const LinkFile: TFileName;
|
|||
|
|
var FileName: TFileName): HRESULT;
|
|||
|
|
var
|
|||
|
|
psl: IShellLink;
|
|||
|
|
WLinkFile: array [0..MAX_PATH] of WideChar;
|
|||
|
|
wfd: TWIN32FINDDATA;
|
|||
|
|
ppf: IPersistFile;
|
|||
|
|
begin
|
|||
|
|
Pointer(psl) := nil;
|
|||
|
|
Pointer(ppf) := nil;
|
|||
|
|
Result := CoInitialize(nil);
|
|||
|
|
if SUCCEEDED(Result) then
|
|||
|
|
begin
|
|||
|
|
// Get a Pointer to the IShellLink interface.
|
|||
|
|
Result := CoCreateInstance(CLSID_ShellLink, nil,
|
|||
|
|
CLSCTX_INPROC_SERVER, IShellLink, psl);
|
|||
|
|
if SUCCEEDED(Result) then
|
|||
|
|
begin
|
|||
|
|
|
|||
|
|
// Get a Pointer to the IPersistFile interface.
|
|||
|
|
Result := psl.QueryInterface(IPersistFile, ppf);
|
|||
|
|
if SUCCEEDED(Result) then
|
|||
|
|
begin
|
|||
|
|
StringToWideChar(LinkFile, WLinkFile, SizeOf(WLinkFile) - 1);
|
|||
|
|
// Load the shortcut.
|
|||
|
|
Result := ppf.Load(WLinkFile, STGM_READ);
|
|||
|
|
if SUCCEEDED(Result) then
|
|||
|
|
begin
|
|||
|
|
// Resolve the link.
|
|||
|
|
Result := psl.Resolve(hWnd, SLR_ANY_MATCH);
|
|||
|
|
if SUCCEEDED(Result) then
|
|||
|
|
begin
|
|||
|
|
// Get the path to the link target.
|
|||
|
|
SetLength(FileName, MAX_PATH);
|
|||
|
|
Result := psl.GetPath(PChar(FileName), MAX_PATH, wfd,
|
|||
|
|
SLGP_UNCPRIORITY);
|
|||
|
|
if not SUCCEEDED(Result) then
|
|||
|
|
Exit;
|
|||
|
|
SetLength(FileName, Length(PChar(FileName)));
|
|||
|
|
end;
|
|||
|
|
end;
|
|||
|
|
// Release the Pointer to the IPersistFile interface.
|
|||
|
|
ppf._Release;
|
|||
|
|
end;
|
|||
|
|
// Release the Pointer to the IShellLink interface.
|
|||
|
|
psl._Release;
|
|||
|
|
end;
|
|||
|
|
CoUnInitialize;
|
|||
|
|
end;
|
|||
|
|
Pointer(psl) := nil;
|
|||
|
|
Pointer(ppf) := nil;
|
|||
|
|
end;
|
|||
|
|
|
|||
|
|
{$ENDIF COMPILER3_UP}
|
|||
|
|
|
|||
|
|
{
|
|||
|
|
with memEdit do begin
|
|||
|
|
Text := ReplaceStrings(Text, SelStart+1, SelLength, memWords.Lines, memFrases.Lines, NewSelStart);
|
|||
|
|
SelStart := NewSelStart-1;
|
|||
|
|
end; }
|
|||
|
|
|
|||
|
|
function ReplaceStrings(S: string; PosBeg, Len: Integer; Words, Frases: TStrings;
|
|||
|
|
var NewSelStart: Integer): string;
|
|||
|
|
var
|
|||
|
|
I, Beg, Ent, LS, F: Integer;
|
|||
|
|
Word: string;
|
|||
|
|
begin
|
|||
|
|
NewSelStart := PosBeg;
|
|||
|
|
Result := S;
|
|||
|
|
LS := Length(S);
|
|||
|
|
if Len = 0 then
|
|||
|
|
begin
|
|||
|
|
if PosBeg < 1 then
|
|||
|
|
Exit;
|
|||
|
|
if PosBeg = 1 then
|
|||
|
|
PosBeg := 2;
|
|||
|
|
for I := PosBeg - 1 downto 1 do
|
|||
|
|
if S[I] in Separators then
|
|||
|
|
Break;
|
|||
|
|
Beg := I + 1;
|
|||
|
|
for Ent := PosBeg to LS do
|
|||
|
|
if S[Ent] in Separators then
|
|||
|
|
Break;
|
|||
|
|
if Ent > Beg then
|
|||
|
|
Word := Copy(S, Beg, Ent - Beg)
|
|||
|
|
else
|
|||
|
|
Word := S[PosBeg];
|
|||
|
|
end
|
|||
|
|
else
|
|||
|
|
begin
|
|||
|
|
Word := Copy(S, PosBeg, Len);
|
|||
|
|
Beg := PosBeg;
|
|||
|
|
Ent := PosBeg + Len;
|
|||
|
|
end;
|
|||
|
|
if Word = '' then
|
|||
|
|
Exit;
|
|||
|
|
F := Words.IndexOf(Word);
|
|||
|
|
if (F > -1) and (F < Frases.Count) then
|
|||
|
|
begin
|
|||
|
|
Result := Copy(S, 1, Beg - 1) + Frases[F] + Copy(S, Ent, LS);
|
|||
|
|
NewSelStart := Beg + Length(Frases[F]);
|
|||
|
|
end;
|
|||
|
|
end;
|
|||
|
|
|
|||
|
|
{
|
|||
|
|
with memEdit do
|
|||
|
|
Text := ReplaceAllStrings(Text, memWords.Lines, memFrases.Lines);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
function ReplaceAllStrings(S: string; Words, Frases: TStrings): string;
|
|||
|
|
var
|
|||
|
|
I, LW: Integer;
|
|||
|
|
P: PChar;
|
|||
|
|
Sm: Integer;
|
|||
|
|
begin
|
|||
|
|
for I := 0 to Words.Count - 1 do
|
|||
|
|
begin
|
|||
|
|
LW := Length(Words[I]);
|
|||
|
|
P := StrPos(PChar(S), PChar(Words[I]));
|
|||
|
|
while P <> nil do
|
|||
|
|
begin
|
|||
|
|
Sm := P - PChar(S);
|
|||
|
|
S := Copy(S, 1, Sm) + Frases[I] + Copy(S, Sm + LW + 1, Length(S));
|
|||
|
|
P := StrPos(PChar(S) + Sm + Length(Frases[I]), PChar(Words[I]));
|
|||
|
|
end;
|
|||
|
|
end;
|
|||
|
|
Result := S;
|
|||
|
|
end;
|
|||
|
|
|
|||
|
|
function CountOfLines(const S: string): Integer;
|
|||
|
|
begin
|
|||
|
|
with TStringList.Create do
|
|||
|
|
try
|
|||
|
|
Text := S;
|
|||
|
|
Result := Count;
|
|||
|
|
finally
|
|||
|
|
Free;
|
|||
|
|
end;
|
|||
|
|
end;
|
|||
|
|
|
|||
|
|
procedure DeleteEmptyLines(Ss: TStrings);
|
|||
|
|
var
|
|||
|
|
I: Integer;
|
|||
|
|
begin
|
|||
|
|
I := 0;
|
|||
|
|
while I < Ss.Count do
|
|||
|
|
if Trim(Ss[I]) = '' then
|
|||
|
|
Ss.Delete(I)
|
|||
|
|
else
|
|||
|
|
Inc(I);
|
|||
|
|
end;
|
|||
|
|
|
|||
|
|
procedure SQLAddWhere(SQL: TStrings; const Where: string);
|
|||
|
|
var
|
|||
|
|
I, J: Integer;
|
|||
|
|
begin
|
|||
|
|
J := SQL.Count - 1;
|
|||
|
|
for I := 0 to SQL.Count - 1 do
|
|||
|
|
// (rom) does this always work? Think of a fieldname "grouporder"
|
|||
|
|
if StrLIComp(PChar(SQL[I]), 'where ', 6) = 0 then
|
|||
|
|
begin
|
|||
|
|
J := I + 1;
|
|||
|
|
while J < SQL.Count do
|
|||
|
|
begin
|
|||
|
|
if (StrLIComp(PChar(SQL[J]), 'order ', 6) = 0) or
|
|||
|
|
(StrLIComp(PChar(SQL[J]), 'group ', 6) = 0) then
|
|||
|
|
Break;
|
|||
|
|
Inc(J);
|
|||
|
|
end;
|
|||
|
|
end;
|
|||
|
|
SQL.Insert(J, 'and ' + Where);
|
|||
|
|
end;
|
|||
|
|
|
|||
|
|
var
|
|||
|
|
ProcList: TList = nil;
|
|||
|
|
type
|
|||
|
|
TJvProcItem = class(TObject)
|
|||
|
|
private
|
|||
|
|
FProcObj: TProcObj;
|
|||
|
|
public
|
|||
|
|
constructor Create(AProcObj: TProcObj);
|
|||
|
|
end;
|
|||
|
|
|
|||
|
|
constructor TJvProcItem.Create(AProcObj: TProcObj);
|
|||
|
|
begin
|
|||
|
|
FProcObj := AProcObj;
|
|||
|
|
end;
|
|||
|
|
|
|||
|
|
procedure TmrProc(hWnd: HWND; uMsg: Integer; idEvent: Integer; dwTime: Integer); stdcall;
|
|||
|
|
var
|
|||
|
|
Pr: TProcObj;
|
|||
|
|
begin
|
|||
|
|
if ProcList[idEvent] <> nil then
|
|||
|
|
begin
|
|||
|
|
Pr := TJvProcItem(ProcList[idEvent]).FProcObj;
|
|||
|
|
TJvProcItem(ProcList[idEvent]).Free;
|
|||
|
|
end
|
|||
|
|
else
|
|||
|
|
Pr := nil;
|
|||
|
|
ProcList.Delete(idEvent);
|
|||
|
|
KillTimer(hWnd, idEvent);
|
|||
|
|
if ProcList.Count <= 0 then
|
|||
|
|
begin
|
|||
|
|
ProcList.Free;
|
|||
|
|
ProcList := nil;
|
|||
|
|
end;
|
|||
|
|
if Assigned(Pr) then
|
|||
|
|
Pr;
|
|||
|
|
end;
|
|||
|
|
|
|||
|
|
procedure ExecAfterPause(Proc: TProcObj; Pause: Integer);
|
|||
|
|
var
|
|||
|
|
Num: Integer;
|
|||
|
|
I: Integer;
|
|||
|
|
begin
|
|||
|
|
if ProcList = nil then
|
|||
|
|
ProcList := TList.Create;
|
|||
|
|
Num := -1;
|
|||
|
|
for I := 0 to ProcList.Count - 1 do
|
|||
|
|
if @TJvProcItem(ProcList[I]).FProcObj = @Proc then
|
|||
|
|
begin
|
|||
|
|
Num := I;
|
|||
|
|
Break;
|
|||
|
|
end;
|
|||
|
|
if Num <> -1 then
|
|||
|
|
KillTimer(Application.Handle, Num)
|
|||
|
|
else
|
|||
|
|
Num := ProcList.Add(TJvProcItem.Create(Proc));
|
|||
|
|
SetTimer(Application.Handle, Num, Pause, @TmrProc);
|
|||
|
|
end;
|
|||
|
|
|
|||
|
|
procedure Roughed(ACanvas: TCanvas; const ARect: TRect; const AVert: Boolean);
|
|||
|
|
var
|
|||
|
|
I: Integer;
|
|||
|
|
J: Integer;
|
|||
|
|
R: TRect;
|
|||
|
|
V: Boolean;
|
|||
|
|
H: Boolean;
|
|||
|
|
begin
|
|||
|
|
H := True;
|
|||
|
|
V := True;
|
|||
|
|
for I := 0 to (ARect.Right - ARect.Left) div 4 do
|
|||
|
|
begin
|
|||
|
|
for J := 0 to (ARect.Bottom - ARect.Top) div 4 do
|
|||
|
|
begin
|
|||
|
|
if AVert then
|
|||
|
|
begin
|
|||
|
|
if V then
|
|||
|
|
R := Bounds(ARect.Left + I * 4 + 2, ARect.Top + J * 4, 2, 2)
|
|||
|
|
else
|
|||
|
|
R := Bounds(ARect.Left + I * 4, ARect.Top + J * 4, 2, 2);
|
|||
|
|
end
|
|||
|
|
else
|
|||
|
|
begin
|
|||
|
|
if H then
|
|||
|
|
R := Bounds(ARect.Left + I * 4, ARect.Top + J * 4 + 2, 2, 2)
|
|||
|
|
else
|
|||
|
|
R := Bounds(ARect.Left + I * 4, ARect.Top + J * 4, 2, 2);
|
|||
|
|
end;
|
|||
|
|
Frame3D(ACanvas, R, clBtnHighlight, clBtnShadow, 1);
|
|||
|
|
V := not V;
|
|||
|
|
end;
|
|||
|
|
H := not H;
|
|||
|
|
end;
|
|||
|
|
end;
|
|||
|
|
|
|||
|
|
function BitmapFromBitmap(SrcBitmap: TBitmap; const AWidth, AHeight, Index: Integer): TBitmap;
|
|||
|
|
begin
|
|||
|
|
Result := TBitmap.Create;
|
|||
|
|
Result.Width := AWidth;
|
|||
|
|
Result.Height := AHeight;
|
|||
|
|
Result.Canvas.CopyRect(Rect(0, 0, AWidth, AHeight), SrcBitmap.Canvas, Bounds(AWidth * Index, 0, AWidth, AHeight));
|
|||
|
|
end;
|
|||
|
|
|
|||
|
|
procedure ShowMenu(Form: TForm; MenuAni: TMenuAnimation);
|
|||
|
|
var
|
|||
|
|
I: Integer;
|
|||
|
|
h: Integer;
|
|||
|
|
w: Integer;
|
|||
|
|
begin
|
|||
|
|
case MenuAni of
|
|||
|
|
maNone:
|
|||
|
|
Form.Show;
|
|||
|
|
maRandom:
|
|||
|
|
;
|
|||
|
|
maUnfold:
|
|||
|
|
begin
|
|||
|
|
h := Form.Height;
|
|||
|
|
Form.Height := 0;
|
|||
|
|
Form.Show;
|
|||
|
|
for I := 0 to h div 10 do
|
|||
|
|
if Form.Height < h then
|
|||
|
|
Form.Height := Form.Height + 10;
|
|||
|
|
end;
|
|||
|
|
maSlide:
|
|||
|
|
begin
|
|||
|
|
h := Form.Height;
|
|||
|
|
w := Form.Width;
|
|||
|
|
Form.Height := 0;
|
|||
|
|
Form.Width := 0;
|
|||
|
|
Form.Show;
|
|||
|
|
for I := 0 to Max(h div 5, w div 5) do
|
|||
|
|
begin
|
|||
|
|
if Form.Height < h then
|
|||
|
|
Form.Height := Form.Height + 5;
|
|||
|
|
if Form.Width < w then
|
|||
|
|
Form.Width := Form.Width + 5;
|
|||
|
|
end;
|
|||
|
|
// CS_SAVEBITS
|
|||
|
|
end;
|
|||
|
|
end;
|
|||
|
|
end;
|
|||
|
|
|
|||
|
|
function ResSaveToFileEx(Instance: HINST; Typ, Name: PChar;
|
|||
|
|
const Compressed: Boolean; const FileName: string): Boolean;
|
|||
|
|
var
|
|||
|
|
RhRsrc: HRSRC;
|
|||
|
|
RhGlobal: HGLOBAL;
|
|||
|
|
RAddr: Pointer;
|
|||
|
|
RLen: DWORD;
|
|||
|
|
Stream: TFileStream;
|
|||
|
|
FileDest: string;
|
|||
|
|
begin
|
|||
|
|
Result := False;
|
|||
|
|
RhRsrc := FindResource(
|
|||
|
|
Instance, // resource-module handle
|
|||
|
|
Name, // address of resource name
|
|||
|
|
Typ); // address of resource type
|
|||
|
|
if RhRsrc = 0 then
|
|||
|
|
Exit;
|
|||
|
|
RhGlobal := LoadResource(
|
|||
|
|
Instance, // resource-module handle
|
|||
|
|
RhRsrc); // resource handle
|
|||
|
|
if RhGlobal = 0 then
|
|||
|
|
Exit;
|
|||
|
|
RAddr := LockResource(
|
|||
|
|
RhGlobal); // handle to resource to lock
|
|||
|
|
FreeResource(RhGlobal);
|
|||
|
|
if RAddr = nil then
|
|||
|
|
Exit;
|
|||
|
|
RLen := SizeofResource(
|
|||
|
|
Instance, // resource-module handle
|
|||
|
|
RhRsrc); // resource handle
|
|||
|
|
if RLen = 0 then
|
|||
|
|
Exit;
|
|||
|
|
{ And now it is possible to duplicate [translated] }
|
|||
|
|
Stream := nil; { for Free [translated] }
|
|||
|
|
if Compressed then
|
|||
|
|
FileDest := GenTempFileName(FileName)
|
|||
|
|
else
|
|||
|
|
FileDest := FileName;
|
|||
|
|
try
|
|||
|
|
try
|
|||
|
|
Stream := TFileStream.Create(FileDest, fmCreate or fmOpenWrite or fmShareExclusive);
|
|||
|
|
Stream.WriteBuffer(RAddr^, RLen);
|
|||
|
|
finally
|
|||
|
|
Stream.Free;
|
|||
|
|
end;
|
|||
|
|
if Compressed then
|
|||
|
|
begin
|
|||
|
|
Result := LZFileExpand(FileDest, FileName);
|
|||
|
|
DeleteFile(FileDest);
|
|||
|
|
end
|
|||
|
|
else
|
|||
|
|
Result := True;
|
|||
|
|
except
|
|||
|
|
end;
|
|||
|
|
end;
|
|||
|
|
|
|||
|
|
function ResSaveToFile(const Typ, Name: string; const Compressed: Boolean;
|
|||
|
|
const FileName: string): Boolean;
|
|||
|
|
begin
|
|||
|
|
Result := ResSaveToFileEx(hInstance, PChar(Typ), PChar(Name), Compressed, FileName);
|
|||
|
|
end;
|
|||
|
|
|
|||
|
|
function ResSaveToString(Instance: HINST; const Typ, Name: string;
|
|||
|
|
var S: string): Boolean;
|
|||
|
|
var
|
|||
|
|
RhRsrc: HRSRC;
|
|||
|
|
RhGlobal: HGLOBAL;
|
|||
|
|
RAddr: Pointer;
|
|||
|
|
RLen: DWORD;
|
|||
|
|
begin
|
|||
|
|
Result := False;
|
|||
|
|
RhRsrc := FindResource(
|
|||
|
|
Instance, // resource-module handle
|
|||
|
|
PChar(Name), // address of resource name
|
|||
|
|
PChar(Typ)); // address of resource type
|
|||
|
|
if RhRsrc = 0 then
|
|||
|
|
Exit;
|
|||
|
|
RhGlobal := LoadResource(
|
|||
|
|
Instance, // resource-module handle
|
|||
|
|
RhRsrc); // resource handle
|
|||
|
|
if RhGlobal = 0 then
|
|||
|
|
Exit;
|
|||
|
|
RAddr := LockResource(
|
|||
|
|
RhGlobal); // handle to resource to lock
|
|||
|
|
FreeResource(RhGlobal);
|
|||
|
|
if RAddr = nil then
|
|||
|
|
Exit;
|
|||
|
|
RLen := SizeofResource(
|
|||
|
|
Instance, // resource-module handle
|
|||
|
|
RhRsrc); // resource handle
|
|||
|
|
if RLen = 0 then
|
|||
|
|
Exit;
|
|||
|
|
{ And now it is possible to duplicate [translated] }
|
|||
|
|
SetString(S, PChar(RAddr), RLen);
|
|||
|
|
end;
|
|||
|
|
|
|||
|
|
// (rom) a thread to wait would be more elegant, also JCL function available
|
|||
|
|
|
|||
|
|
function Execute(const CommandLine, WorkingDirectory: string): Integer;
|
|||
|
|
var
|
|||
|
|
R: Boolean;
|
|||
|
|
ProcessInformation: TProcessInformation;
|
|||
|
|
StartupInfo: TStartupInfo;
|
|||
|
|
{$IFDEF COMPILER4_UP}
|
|||
|
|
ExCode: Cardinal;
|
|||
|
|
{$ELSE}
|
|||
|
|
ExCode: Integer;
|
|||
|
|
{$ENDIF}
|
|||
|
|
begin
|
|||
|
|
Result := 0;
|
|||
|
|
FillChar(StartupInfo, SizeOf(TStartupInfo), 0);
|
|||
|
|
with StartupInfo do
|
|||
|
|
begin
|
|||
|
|
cb := SizeOf(TStartupInfo);
|
|||
|
|
dwFlags := STARTF_USESHOWWINDOW;
|
|||
|
|
wShowWindow := SW_SHOW;
|
|||
|
|
end;
|
|||
|
|
R := CreateProcess(
|
|||
|
|
nil, // Pointer to name of executable module
|
|||
|
|
PChar(CommandLine), // Pointer to command line string
|
|||
|
|
nil, // Pointer to process security attributes
|
|||
|
|
nil, // Pointer to thread security attributes
|
|||
|
|
False, // handle inheritance flag
|
|||
|
|
0, // creation flags
|
|||
|
|
nil, // Pointer to new environment block
|
|||
|
|
PChar(WorkingDirectory), // Pointer to current directory name
|
|||
|
|
StartupInfo, // Pointer to STARTUPINFO
|
|||
|
|
ProcessInformation); // Pointer to PROCESS_INFORMATION
|
|||
|
|
if R then
|
|||
|
|
while (GetExitCodeProcess(ProcessInformation.hProcess, ExCode) and
|
|||
|
|
(ExCode = STILL_ACTIVE)) do
|
|||
|
|
Application.ProcessMessages
|
|||
|
|
else
|
|||
|
|
Result := GetLastError;
|
|||
|
|
end;
|
|||
|
|
|
|||
|
|
function TextWidth(AStr: string): Integer;
|
|||
|
|
var
|
|||
|
|
Canvas: TCanvas;
|
|||
|
|
DC: HDC;
|
|||
|
|
begin
|
|||
|
|
DC := GetDC(HWND_DESKTOP);
|
|||
|
|
Canvas := TCanvas.Create;
|
|||
|
|
// (rom) secured
|
|||
|
|
try
|
|||
|
|
Canvas.Handle := DC;
|
|||
|
|
Result := Canvas.TextWidth(AStr);
|
|||
|
|
Canvas.Handle := 0;
|
|||
|
|
Canvas.Free;
|
|||
|
|
finally
|
|||
|
|
ReleaseDC(HWND_DESKTOP, DC);
|
|||
|
|
end;
|
|||
|
|
end;
|
|||
|
|
|
|||
|
|
function AppMinimized: Boolean;
|
|||
|
|
begin
|
|||
|
|
Result := IsIconic(Application.Handle);
|
|||
|
|
end;
|
|||
|
|
|
|||
|
|
function MessageBox(const Msg: string; Caption: string; const Flags: Integer): Integer;
|
|||
|
|
begin
|
|||
|
|
if Caption = '' then
|
|||
|
|
Caption := Application.Title;
|
|||
|
|
Result := Application.MessageBox(PChar(Msg), PChar(Caption), Flags);
|
|||
|
|
end;
|
|||
|
|
|
|||
|
|
function MsgDlgDef1(const Msg, ACaption: string; DlgType: TMsgDlgType;
|
|||
|
|
Buttons: TMsgDlgButtons; DefButton: TMsgDlgBtn; UseDefButton: Boolean;
|
|||
|
|
AHelpContext: Integer; Control: TWinControl): Integer;
|
|||
|
|
const
|
|||
|
|
{$IFNDEF COMPILER2}
|
|||
|
|
ButtonNames: array [TMsgDlgBtn] of PChar =
|
|||
|
|
('Yes', 'No', 'OK', 'Cancel', 'Abort', 'Retry', 'Ignore', 'All', 'NoToAll',
|
|||
|
|
'YesToAll', 'Help');
|
|||
|
|
{$ELSE}
|
|||
|
|
ButtonNames: array [TMsgDlgBtn] of string =
|
|||
|
|
('Yes', 'No', 'OK', 'Cancel', 'Abort', 'Retry', 'Ignore', 'All', 'Help');
|
|||
|
|
{$ENDIF COMPILER2}
|
|||
|
|
var
|
|||
|
|
P: TPoint;
|
|||
|
|
I: Integer;
|
|||
|
|
Btn: TButton;
|
|||
|
|
StayOnTop: Boolean;
|
|||
|
|
begin
|
|||
|
|
if AHelpContext <> 0 then
|
|||
|
|
Buttons := Buttons + [mbHelp];
|
|||
|
|
StayOnTop := False;
|
|||
|
|
with CreateMessageDialog(Msg, DlgType, Buttons) do
|
|||
|
|
try
|
|||
|
|
{$IFDEF COMPILER3_UP}
|
|||
|
|
Font.CharSet := MsgDlgCharSet;
|
|||
|
|
{$ENDIF COMPILER3_UP}
|
|||
|
|
if (Screen.ActiveForm <> nil) and
|
|||
|
|
(Screen.ActiveForm.FormStyle = fsStayOnTop) then
|
|||
|
|
begin
|
|||
|
|
StayOnTop := True;
|
|||
|
|
SetWindowTop(Screen.ActiveForm.Handle, False);
|
|||
|
|
end;
|
|||
|
|
if ACaption <> '' then
|
|||
|
|
Caption := ACaption;
|
|||
|
|
if Control = nil then
|
|||
|
|
begin
|
|||
|
|
Left := (Screen.Width - Width) div 2;
|
|||
|
|
Top := (Screen.Height - Height) div 2;
|
|||
|
|
end
|
|||
|
|
else
|
|||
|
|
begin
|
|||
|
|
P := Point((Control.Width - Width) div 2,
|
|||
|
|
(Control.Height - Height) div 2);
|
|||
|
|
P := Control.ClientToScreen(P);
|
|||
|
|
Left := P.X;
|
|||
|
|
Top := P.Y
|
|||
|
|
end;
|
|||
|
|
if Left < 0 then
|
|||
|
|
Left := 0
|
|||
|
|
else
|
|||
|
|
if Left > Screen.Width then
|
|||
|
|
Left := Screen.Width - Width;
|
|||
|
|
if Top < 0 then
|
|||
|
|
Top := 0
|
|||
|
|
else
|
|||
|
|
if Top > Screen.Height then
|
|||
|
|
Top := Screen.Height - Height;
|
|||
|
|
HelpContext := AHelpContext;
|
|||
|
|
|
|||
|
|
Btn := FindComponent(ButtonNames[DefButton]) as TButton;
|
|||
|
|
if UseDefButton and (Btn <> nil) then
|
|||
|
|
begin
|
|||
|
|
for I := 0 to ComponentCount - 1 do
|
|||
|
|
if Components[I] is TButton then
|
|||
|
|
(Components[I] as TButton).Default := False;
|
|||
|
|
Btn.Default := True;
|
|||
|
|
ActiveControl := Btn;
|
|||
|
|
end;
|
|||
|
|
Btn := FindComponent(ButtonNames[mbIgnore]) as TButton;
|
|||
|
|
if Btn <> nil then
|
|||
|
|
begin
|
|||
|
|
// Btn.Width := Btn.Width * 5 div 4; {To shift the Help button Help [translated] }
|
|||
|
|
end;
|
|||
|
|
Result := ShowModal;
|
|||
|
|
finally
|
|||
|
|
Free;
|
|||
|
|
if (Screen.ActiveForm <> nil) and StayOnTop then
|
|||
|
|
SetWindowTop(Screen.ActiveForm.Handle, True);
|
|||
|
|
end;
|
|||
|
|
end;
|
|||
|
|
|
|||
|
|
function MsgDlgDef(const Msg, ACaption: string; DlgType: TMsgDlgType;
|
|||
|
|
Buttons: TMsgDlgButtons; DefButton: TMsgDlgBtn; HelpContext: Integer;
|
|||
|
|
Control: TWinControl): Integer;
|
|||
|
|
begin
|
|||
|
|
Result := MsgDlgDef1(Msg, ACaption, DlgType, Buttons, DefButton, True, HelpContext, Control);
|
|||
|
|
end;
|
|||
|
|
|
|||
|
|
function MsgDlg2(const Msg, ACaption: string; DlgType: TMsgDlgType;
|
|||
|
|
Buttons: TMsgDlgButtons; HelpContext: Integer;
|
|||
|
|
Control: TWinControl): Integer;
|
|||
|
|
begin
|
|||
|
|
Result := MsgDlgDef1(Msg, ACaption, DlgType, Buttons, mbHelp, False, HelpContext, Control);
|
|||
|
|
end;
|
|||
|
|
|
|||
|
|
procedure CenterHor(Parent: TControl; MinLeft: Integer; Controls: array of TControl);
|
|||
|
|
var
|
|||
|
|
I: Integer;
|
|||
|
|
begin
|
|||
|
|
for I := Low(Controls) to High(Controls) do
|
|||
|
|
Controls[I].Left := Max(MinLeft, (Parent.Width - Controls[I].Width) div 2)
|
|||
|
|
end;
|
|||
|
|
|
|||
|
|
procedure EnableControls(Control: TWinControl; const Enable: Boolean);
|
|||
|
|
var
|
|||
|
|
I: Integer;
|
|||
|
|
begin
|
|||
|
|
for I := 0 to Control.ControlCount - 1 do
|
|||
|
|
Control.Controls[I].Enabled := Enable;
|
|||
|
|
end;
|
|||
|
|
|
|||
|
|
procedure EnableMenuItems(MenuItem: TMenuItem; const Tag: Integer; const Enable: Boolean);
|
|||
|
|
var
|
|||
|
|
I: Integer;
|
|||
|
|
begin
|
|||
|
|
for I := 0 to MenuItem.Count - 1 do
|
|||
|
|
if MenuItem[I].Tag <> Tag then
|
|||
|
|
MenuItem[I].Enabled := Enable;
|
|||
|
|
end;
|
|||
|
|
|
|||
|
|
procedure ExpandWidth(Parent: TControl; MinWidth: Integer; Controls: array of TControl);
|
|||
|
|
var
|
|||
|
|
I: Integer;
|
|||
|
|
begin
|
|||
|
|
for I := Low(Controls) to High(Controls) do
|
|||
|
|
Controls[I].Width := Max(MinWidth, Parent.ClientWidth - 2 * Controls[I].Left);
|
|||
|
|
end;
|
|||
|
|
|
|||
|
|
function PanelBorder(Panel: TCustomPanel): Integer;
|
|||
|
|
begin
|
|||
|
|
Result := TPanel(Panel).BorderWidth;
|
|||
|
|
if TPanel(Panel).BevelOuter <> bvNone then
|
|||
|
|
Inc(Result, TPanel(Panel).BevelWidth);
|
|||
|
|
if TPanel(Panel).BevelInner <> bvNone then
|
|||
|
|
Inc(Result, TPanel(Panel).BevelWidth);
|
|||
|
|
end;
|
|||
|
|
|
|||
|
|
{$IFDEF COMPILER2}
|
|||
|
|
function CompareMem(P1, P2: Pointer; Length: Integer): Boolean; assembler;
|
|||
|
|
asm
|
|||
|
|
PUSH ESI
|
|||
|
|
PUSH EDI
|
|||
|
|
MOV ESI,P1
|
|||
|
|
MOV EDI,P2
|
|||
|
|
MOV EDX,ECX
|
|||
|
|
XOR EAX,EAX
|
|||
|
|
AND EDX,3
|
|||
|
|
SHR ECX,1
|
|||
|
|
SHR ECX,1
|
|||
|
|
REPE CMPSD
|
|||
|
|
JNE @@2
|
|||
|
|
MOV ECX,EDX
|
|||
|
|
REPE CMPSB
|
|||
|
|
JNE @@2
|
|||
|
|
@@1: Inc EAX
|
|||
|
|
@@2: POP EDI
|
|||
|
|
POP ESI
|
|||
|
|
end;
|
|||
|
|
{$ENDIF COMPILER2}
|
|||
|
|
|
|||
|
|
{ function DefineCursor was typed from
|
|||
|
|
book "Secrets of Delphi 2" by Ray Lischner }
|
|||
|
|
|
|||
|
|
function DefineCursor(Identifier: PChar): TCursor;
|
|||
|
|
var
|
|||
|
|
Handle: HCursor;
|
|||
|
|
begin
|
|||
|
|
Handle := LoadCursor(hInstance, Identifier);
|
|||
|
|
if Handle = 0 then
|
|||
|
|
raise EOutOfResources.Create('Cannot load cursor resource');
|
|||
|
|
for Result := 1 to High(TCursor) do
|
|||
|
|
if Screen.Cursors[Result] = Screen.Cursors[crDefault] then
|
|||
|
|
begin
|
|||
|
|
Screen.Cursors[Result] := Handle;
|
|||
|
|
Exit;
|
|||
|
|
end;
|
|||
|
|
raise EOutOfResources.Create('Too many user-defined cursors');
|
|||
|
|
end;
|
|||
|
|
|
|||
|
|
procedure Delay(MSec: Longword);
|
|||
|
|
var
|
|||
|
|
T: Longword;
|
|||
|
|
begin
|
|||
|
|
T := GetTickCount;
|
|||
|
|
while GetTickCount - T < MSec do
|
|||
|
|
Application.ProcessMessages;
|
|||
|
|
end;
|
|||
|
|
|
|||
|
|
function Pixels(Control: TControl; APixels: Integer): Integer;
|
|||
|
|
var
|
|||
|
|
Form: TForm;
|
|||
|
|
begin
|
|||
|
|
Result := APixels;
|
|||
|
|
if Control is TForm then
|
|||
|
|
Form := TForm(Control)
|
|||
|
|
else
|
|||
|
|
Form := TForm(GetParentForm(Control));
|
|||
|
|
if Form.Scaled then
|
|||
|
|
Result := Result * Form.PixelsPerInch div 96;
|
|||
|
|
end;
|
|||
|
|
|
|||
|
|
procedure SetChildPropOrd(Owner: TComponent; PropName: string; Value: Longint);
|
|||
|
|
var
|
|||
|
|
I: Integer;
|
|||
|
|
PropInfo: PPropInfo;
|
|||
|
|
begin
|
|||
|
|
for I := 0 to Owner.ComponentCount - 1 do
|
|||
|
|
begin
|
|||
|
|
PropInfo := GetPropInfo(Owner.Components[I].ClassInfo, PropName);
|
|||
|
|
if PropInfo <> nil then
|
|||
|
|
SetOrdProp(Owner.Components[I], PropInfo, Value);
|
|||
|
|
end;
|
|||
|
|
end;
|
|||
|
|
|
|||
|
|
procedure Error(const Msg: string);
|
|||
|
|
begin
|
|||
|
|
raise Exception.Create(Msg);
|
|||
|
|
end;
|
|||
|
|
|
|||
|
|
procedure ItemHtDrawEx(Canvas: TCanvas; Rect: TRect;
|
|||
|
|
const State: TOwnerDrawState; const Text: string;
|
|||
|
|
const HideSelColor: Boolean; var PlainItem: string;
|
|||
|
|
var Width: Integer; CalcWidth: Boolean);
|
|||
|
|
var
|
|||
|
|
CL: string;
|
|||
|
|
I: Integer;
|
|||
|
|
M1: string;
|
|||
|
|
OriRect: TRect; // it's added
|
|||
|
|
oldFontStyles: TFontStyles;
|
|||
|
|
oldFontColor: TColor;
|
|||
|
|
|
|||
|
|
function Cmp(M1: string): Boolean;
|
|||
|
|
begin
|
|||
|
|
Result := AnsiStrLIComp(PChar(Text) + I, PChar(M1), Length(M1)) = 0;
|
|||
|
|
end;
|
|||
|
|
|
|||
|
|
function Cmp1(M1: string): Boolean;
|
|||
|
|
begin
|
|||
|
|
Result := AnsiStrLIComp(PChar(Text) + I, PChar(M1), Length(M1)) = 0;
|
|||
|
|
if Result then
|
|||
|
|
Inc(I, Length(M1));
|
|||
|
|
end;
|
|||
|
|
|
|||
|
|
function CmpL(M1: string): Boolean;
|
|||
|
|
begin
|
|||
|
|
Result := Cmp(M1 + '>');
|
|||
|
|
end;
|
|||
|
|
|
|||
|
|
function CmpL1(M1: string): Boolean;
|
|||
|
|
begin
|
|||
|
|
Result := Cmp1(M1 + '>');
|
|||
|
|
end;
|
|||
|
|
|
|||
|
|
procedure Draw(const M: string);
|
|||
|
|
begin
|
|||
|
|
if not Assigned(Canvas) then
|
|||
|
|
Exit;
|
|||
|
|
if not CalcWidth then
|
|||
|
|
Canvas.TextOut(Rect.Left, Rect.Top, M);
|
|||
|
|
Rect.Left := Rect.Left + Canvas.TextWidth(M);
|
|||
|
|
end;
|
|||
|
|
|
|||
|
|
procedure Style(const Style: TFontStyle; const Include: Boolean);
|
|||
|
|
begin
|
|||
|
|
if not Assigned(Canvas) then
|
|||
|
|
Exit;
|
|||
|
|
if Include then
|
|||
|
|
Canvas.Font.Style := Canvas.Font.Style + [Style]
|
|||
|
|
else
|
|||
|
|
Canvas.Font.Style := Canvas.Font.Style - [Style];
|
|||
|
|
end;
|
|||
|
|
|
|||
|
|
begin
|
|||
|
|
PlainItem := '';
|
|||
|
|
oldFontColor := 0; { satisfy compiler }
|
|||
|
|
if Canvas <> nil then
|
|||
|
|
begin
|
|||
|
|
oldFontStyles := Canvas.Font.Style;
|
|||
|
|
oldFontColor := Canvas.Font.Color;
|
|||
|
|
end;
|
|||
|
|
try
|
|||
|
|
if HideSelColor and Assigned(Canvas) then
|
|||
|
|
begin
|
|||
|
|
Canvas.Brush.Color := clWindow;
|
|||
|
|
Canvas.Font.Color := clWindowText;
|
|||
|
|
end;
|
|||
|
|
if Assigned(Canvas) then
|
|||
|
|
Canvas.FillRect(Rect);
|
|||
|
|
|
|||
|
|
Width := Rect.Left;
|
|||
|
|
Rect.Left := Rect.Left + 2;
|
|||
|
|
|
|||
|
|
OriRect := Rect; //save origin rectangle
|
|||
|
|
|
|||
|
|
M1 := '';
|
|||
|
|
I := 1;
|
|||
|
|
while I <= Length(Text) do
|
|||
|
|
begin
|
|||
|
|
if (Text[I] = '<') and
|
|||
|
|
(CmpL('b') or CmpL('/b') or
|
|||
|
|
CmpL('i') or CmpL('/i') or
|
|||
|
|
CmpL('u') or CmpL('/u') or
|
|||
|
|
Cmp('c:')) then
|
|||
|
|
begin
|
|||
|
|
Draw(M1);
|
|||
|
|
PlainItem := PlainItem + M1;
|
|||
|
|
|
|||
|
|
if CmpL1('b') then
|
|||
|
|
Style(fsBold, True)
|
|||
|
|
else
|
|||
|
|
if CmpL1('/b') then
|
|||
|
|
Style(fsBold, False)
|
|||
|
|
else
|
|||
|
|
if CmpL1('i') then
|
|||
|
|
Style(fsItalic, True)
|
|||
|
|
else
|
|||
|
|
if CmpL1('/i') then
|
|||
|
|
Style(fsItalic, False)
|
|||
|
|
else
|
|||
|
|
if CmpL1('u') then
|
|||
|
|
Style(fsUnderline, True)
|
|||
|
|
else
|
|||
|
|
if CmpL1('/u') then
|
|||
|
|
Style(fsUnderline, False)
|
|||
|
|
else
|
|||
|
|
if Cmp1('c:') then
|
|||
|
|
begin
|
|||
|
|
CL := SubStr(PChar(Text) + I, 0, '>');
|
|||
|
|
if (HideSelColor or not (odSelected in State)) and Assigned(Canvas) then
|
|||
|
|
try
|
|||
|
|
if (Length(CL) > 0) and (CL[1] <> '$') then
|
|||
|
|
Canvas.Font.Color := StringToColor('cl' + CL)
|
|||
|
|
else
|
|||
|
|
Canvas.Font.Color := StringToColor(CL);
|
|||
|
|
except
|
|||
|
|
end;
|
|||
|
|
Inc(I, Length(CL) + 1 {'>'});
|
|||
|
|
end;
|
|||
|
|
|
|||
|
|
M1 := '';
|
|||
|
|
end
|
|||
|
|
else
|
|||
|
|
// next lines were added
|
|||
|
|
if (Text[I] = Chr(13)) and Cmp1(string(Chr(10))) then
|
|||
|
|
begin
|
|||
|
|
// new line
|
|||
|
|
Draw(M1);
|
|||
|
|
PlainItem := PlainItem + M1;
|
|||
|
|
Rect.Left := OriRect.Left;
|
|||
|
|
Rect.Top := Rect.Top + Canvas.TextHeight(M1);
|
|||
|
|
M1 := '';
|
|||
|
|
end
|
|||
|
|
else
|
|||
|
|
// add text
|
|||
|
|
M1 := M1 + Text[I];
|
|||
|
|
Inc(I);
|
|||
|
|
end; { for }
|
|||
|
|
Draw(M1);
|
|||
|
|
PlainItem := PlainItem + M1;
|
|||
|
|
finally
|
|||
|
|
if Canvas <> nil then
|
|||
|
|
begin
|
|||
|
|
Canvas.Font.Style := oldFontStyles;
|
|||
|
|
Canvas.Font.Color := oldFontColor;
|
|||
|
|
end;
|
|||
|
|
end;
|
|||
|
|
Width := Rect.Left - Width + 2;
|
|||
|
|
end;
|
|||
|
|
|
|||
|
|
function ItemHtDraw(Canvas: TCanvas; Rect: TRect;
|
|||
|
|
const State: TOwnerDrawState; const Text: string;
|
|||
|
|
const HideSelColor: Boolean): string;
|
|||
|
|
var
|
|||
|
|
S: string;
|
|||
|
|
W: Integer;
|
|||
|
|
begin
|
|||
|
|
ItemHtDrawEx(Canvas, Rect, State, Text, HideSelColor, S, W, False);
|
|||
|
|
end;
|
|||
|
|
|
|||
|
|
function ItemHtPlain(const Text: string): string;
|
|||
|
|
var
|
|||
|
|
S: string;
|
|||
|
|
W: Integer;
|
|||
|
|
begin
|
|||
|
|
ItemHtDrawEx(nil, Rect(0, 0, -1, -1), [], Text, False, S, W, False);
|
|||
|
|
Result := S;
|
|||
|
|
end;
|
|||
|
|
|
|||
|
|
function ItemHtWidth(Canvas: TCanvas; Rect: TRect;
|
|||
|
|
const State: TOwnerDrawState; const Text: string;
|
|||
|
|
const HideSelColor: Boolean): Integer;
|
|||
|
|
var
|
|||
|
|
S: string;
|
|||
|
|
W: Integer;
|
|||
|
|
begin
|
|||
|
|
ItemHtDrawEx(Canvas, Rect, State, Text, HideSelColor, S, W, True);
|
|||
|
|
Result := W;
|
|||
|
|
end;
|
|||
|
|
|
|||
|
|
procedure ClearList(List: TList);
|
|||
|
|
var
|
|||
|
|
I: Integer;
|
|||
|
|
begin
|
|||
|
|
if not Assigned(List) then
|
|||
|
|
Exit;
|
|||
|
|
for I := 0 to List.Count - 1 do
|
|||
|
|
TObject(List[I]).Free;
|
|||
|
|
List.Clear;
|
|||
|
|
end;
|
|||
|
|
|
|||
|
|
procedure MemStreamToClipBoard(MemStream: TMemoryStream; const Format: Word);
|
|||
|
|
var
|
|||
|
|
Data: THandle;
|
|||
|
|
DataPtr: Pointer;
|
|||
|
|
begin
|
|||
|
|
Clipboard.Open;
|
|||
|
|
try
|
|||
|
|
Data := GlobalAlloc(GMEM_MOVEABLE, MemStream.Size);
|
|||
|
|
try
|
|||
|
|
DataPtr := GlobalLock(Data);
|
|||
|
|
try
|
|||
|
|
Move(MemStream.Memory^, DataPtr^, MemStream.Size);
|
|||
|
|
Clipboard.Clear;
|
|||
|
|
SetClipboardData(Format, Data);
|
|||
|
|
finally
|
|||
|
|
GlobalUnlock(Data);
|
|||
|
|
end;
|
|||
|
|
except
|
|||
|
|
GlobalFree(Data);
|
|||
|
|
raise;
|
|||
|
|
end;
|
|||
|
|
finally
|
|||
|
|
Clipboard.Close;
|
|||
|
|
end;
|
|||
|
|
end;
|
|||
|
|
|
|||
|
|
procedure ClipBoardToMemStream(MemStream: TMemoryStream; const Format: Word);
|
|||
|
|
var
|
|||
|
|
Data: THandle;
|
|||
|
|
DataPtr: Pointer;
|
|||
|
|
begin
|
|||
|
|
Clipboard.Open;
|
|||
|
|
try
|
|||
|
|
Data := GetClipboardData(Format);
|
|||
|
|
if Data = 0 then
|
|||
|
|
Exit;
|
|||
|
|
DataPtr := GlobalLock(Data);
|
|||
|
|
if DataPtr = nil then
|
|||
|
|
Exit;
|
|||
|
|
try
|
|||
|
|
MemStream.WriteBuffer(DataPtr^, GlobalSize(Data));
|
|||
|
|
MemStream.Position := 0;
|
|||
|
|
finally
|
|||
|
|
GlobalUnlock(Data);
|
|||
|
|
end;
|
|||
|
|
finally
|
|||
|
|
Clipboard.Close;
|
|||
|
|
end;
|
|||
|
|
end;
|
|||
|
|
|
|||
|
|
function GetPropType(Obj: TObject; const PropName: string): TTypeKind;
|
|||
|
|
var
|
|||
|
|
PropInf: PPropInfo;
|
|||
|
|
begin
|
|||
|
|
PropInf := GetPropInfo(Obj.ClassInfo, PropName);
|
|||
|
|
if PropInf = nil then
|
|||
|
|
Result := tkUnknown
|
|||
|
|
else
|
|||
|
|
Result := PropInf^.PropType^.Kind;
|
|||
|
|
end;
|
|||
|
|
|
|||
|
|
function GetPropStr(Obj: TObject; const PropName: string): string;
|
|||
|
|
var
|
|||
|
|
PropInf: PPropInfo;
|
|||
|
|
begin
|
|||
|
|
PropInf := GetPropInfo(Obj.ClassInfo, PropName);
|
|||
|
|
if PropInf = nil then
|
|||
|
|
raise Exception.CreateFmt(SPropertyNotExists, [PropName]);
|
|||
|
|
if not (PropInf^.PropType^.Kind in
|
|||
|
|
[tkString, tkLString {$IFDEF COMPILER3_UP}, tkWString {$ENDIF COMPILER3_UP}]) then
|
|||
|
|
raise Exception.CreateFmt(SInvalidPropertyType, [PropName]);
|
|||
|
|
Result := GetStrProp(Obj, PropInf);
|
|||
|
|
end;
|
|||
|
|
|
|||
|
|
function GetPropOrd(Obj: TObject; const PropName: string): Integer;
|
|||
|
|
var
|
|||
|
|
PropInf: PPropInfo;
|
|||
|
|
begin
|
|||
|
|
PropInf := GetPropInfo(Obj.ClassInfo, PropName);
|
|||
|
|
if PropInf = nil then
|
|||
|
|
raise Exception.CreateFmt(SPropertyNotExists, [PropName]);
|
|||
|
|
if not (PropInf^.PropType^.Kind in
|
|||
|
|
[tkInteger, tkChar, tkWChar, tkEnumeration, tkClass]) then
|
|||
|
|
raise Exception.CreateFmt(SInvalidPropertyType, [PropName]);
|
|||
|
|
Result := GetOrdProp(Obj, PropInf);
|
|||
|
|
end;
|
|||
|
|
|
|||
|
|
function GetPropMethod(Obj: TObject; const PropName: string): TMethod;
|
|||
|
|
var
|
|||
|
|
PropInf: PPropInfo;
|
|||
|
|
begin
|
|||
|
|
PropInf := GetPropInfo(Obj.ClassInfo, PropName);
|
|||
|
|
if PropInf = nil then
|
|||
|
|
raise Exception.CreateFmt(SPropertyNotExists, [PropName]);
|
|||
|
|
if not (PropInf^.PropType^.Kind = tkMethod) then
|
|||
|
|
raise Exception.CreateFmt(SInvalidPropertyType, [PropName]);
|
|||
|
|
Result := GetMethodProp(Obj, PropInf);
|
|||
|
|
end;
|
|||
|
|
|
|||
|
|
procedure PrepareIniSection(SS: TStrings);
|
|||
|
|
var
|
|||
|
|
I: Integer;
|
|||
|
|
S: string;
|
|||
|
|
begin
|
|||
|
|
I := 0;
|
|||
|
|
while I < Ss.Count do
|
|||
|
|
begin
|
|||
|
|
S := Trim(Ss[I]);
|
|||
|
|
if (Length(S) = 0) or (S[1] in [';', '#']) then
|
|||
|
|
Ss.Delete(I)
|
|||
|
|
else
|
|||
|
|
Inc(I);
|
|||
|
|
end;
|
|||
|
|
end;
|
|||
|
|
|
|||
|
|
{:Creates a TPointL structure from a pair of coordinates.
|
|||
|
|
Call PointL to create a TPointL structure that represents the specified
|
|||
|
|
coordinates. Use PointL to construct parameters for functions
|
|||
|
|
that require a TPointL, rather than setting up local variables
|
|||
|
|
for each parameter.
|
|||
|
|
@param X The X coordinate.
|
|||
|
|
@param Y The Y coordinate.
|
|||
|
|
@return A TPointL structure for coordinates X and Y.
|
|||
|
|
@example <Code>
|
|||
|
|
var
|
|||
|
|
p: TPointL;
|
|||
|
|
begin
|
|||
|
|
p := PointL(100, 100);
|
|||
|
|
end;
|
|||
|
|
</Code>
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
function PointL(const X, Y: Longint): TPointL;
|
|||
|
|
begin
|
|||
|
|
Result.X := X;
|
|||
|
|
Result.Y := Y;
|
|||
|
|
end;
|
|||
|
|
|
|||
|
|
{:Conditional assignment.
|
|||
|
|
Returns the value in True or False depending on the condition Test.
|
|||
|
|
@param Test The test condition.
|
|||
|
|
@param True Returns this value if Test is True.
|
|||
|
|
@param False Returns this value if Test is False.
|
|||
|
|
@return Value in True or False depending on Test.
|
|||
|
|
@example <Code>
|
|||
|
|
bar := iif(foo, 1, 0);
|
|||
|
|
</Code>
|
|||
|
|
<br>has the same effects as:<br>
|
|||
|
|
<Code>
|
|||
|
|
if foo then
|
|||
|
|
bar := 1
|
|||
|
|
else
|
|||
|
|
bar := 0;
|
|||
|
|
</Code>
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
function iif(const Test: Boolean; const ATrue, AFalse: Variant): Variant;
|
|||
|
|
begin
|
|||
|
|
if Test then
|
|||
|
|
Result := ATrue
|
|||
|
|
else
|
|||
|
|
Result := AFalse;
|
|||
|
|
end;
|
|||
|
|
|
|||
|
|
end.
|
|||
|
|
|