From 868daf94f29ce1ffdd799a68c07bb668cd373bcd Mon Sep 17 00:00:00 2001
From: HP\李良庭 <liliangting@lanpucloud.cn:1111>
Date: 星期二, 08 七月 2025 11:49:03 +0800
Subject: [PATCH] 提交分辨率自适应版本V3.1.0.1500

---
 src/pub/PubUtils.pas | 3854 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 3,854 insertions(+), 0 deletions(-)

diff --git a/src/pub/PubUtils.pas b/src/pub/PubUtils.pas
new file mode 100644
index 0000000..bb3d949
--- /dev/null
+++ b/src/pub/PubUtils.pas
@@ -0,0 +1,3854 @@
+{------------------------------------------------------------------------------}
+{项目名称:公共项目                                                            }
+{单元名称:PubUtils.pas                                                        }
+{版本版次:3.3                                                                 }
+{模块名称:全局公共函数库                                                      }
+{功能描述:维护通用公共函数调用                                                }   
+{建立日期:2011-01-01                                                          }
+{修改修改:2025-02-12                                                          }
+{版权所有:李良庭                                                              }
+{------------------------------------------------------------------------------}
+
+//2011-10-26 新增ComboBox_XPMan_KeyPress函数,解决ComboBox控件输入乱码问题,
+//           在KeyPress事件中执行ComboBox_XPMan_KeyPress即可解决。
+//2015-12-01 新增Base16Encode、Base16Decode、Delay、GetVersionInfo等功能函数。
+//2015-12-24 新增Excel操作函数,使用ADO方式连接Excel文件读写。
+//2017-10-15 新增屏幕截图保存为png文件,传入文件路径,静默保存至本地,使用Tpngimage组件.
+//2018-04-01 新增根据程序名称获取句柄的方法,支持跨进程发送消息。
+//2018-10-20 为数采开发平台新增Dll调用函数。
+//2018-10-30 优化公共函数库,去掉部分重复函数。
+//2019-01-17 基于DateUtils库,扩充 DateTimeToUnix()函数,减8小时变成格林威治时间
+//2022-09-20 增加科学计数法和浮点型数字互转,输入输出均使用string类型。
+//2023-11-01 增加检查串口是否存在的函数。
+//2025-02-12 增加整形转为布尔值的函数。
+
+unit PubUtils;
+
+interface
+
+uses
+  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, StdCtrls, Masks,
+  Math, ShellApi, ShlObj, ComObj, ActiveX, Registry, Dialogs, StrUtils, Printers,
+  Winsock, TLHelp32, PsAPI, DateUtils, Global;
+
+// 字符串相关
+function IsInt(const S: string): Boolean;
+function IsFloat(const S: string): Boolean;
+function IsEmail(const S: string): Boolean;
+function PathWithSlash(const Path: string): string;
+function PathWithoutSlash(const Path: string): string;
+function CombineFileName(const Path, FileName: string): string;
+function FileExtWithDot(const FileExt: string): string;
+function FileExtWithoutDot(const FileExt: string): string;
+function AddNumberComma(Number: Int64): string;
+function ExtractFileMainName(const FileName: string): string;
+function ExtractUrlFilePath(const Url: string): string;
+function ExtractUrlFileName(const Url: string): string;
+function ValidateFileName(const FileName: string): string;
+function GetSizeString(Bytes: Int64; const Postfix: string = ' KB'): string;
+function GetPercentString(Position, Max: Int64; const Postfix: string = ' %'): string;
+function RestrictStrWidth(const S: WideString; Canvas: TCanvas; Width: Integer; const Suffix: string = '...'): WideString;
+function RestrictFileNameWidth(const FileName: string; MaxBytes: Integer): string;
+function LikeString(Value, Pattern: WideString; CaseInsensitive: Boolean): Boolean;
+procedure SplitString(S: string; Delimiter: Char; List: TStrings);
+function StartWith(const Source: string; const Left: string): Boolean;
+function EndWith(const Source: string; const Right: string): Boolean;
+function MyPos(c: Char; const str: string): Integer;
+
+// 系统相关
+function GetComputerName: string;
+function GetWinUserName: string;
+function GetWindowsDir: string;
+function GetWinTempDir: string;
+function GetWinTempFile(const PrefixStr: string = ''): string;
+function GetFullFileName(const FileName: string): string;
+function GetShortFileName(const FileName: string): string;
+function GetLongFileName(const FileName: string): string;
+function GetSpecialFolder(FolderID: Integer): string;
+function GetQuickLaunchPath: string;
+function GetSystemDrivePath: string;
+function GetEnvVar(const EnvVar: string): string;
+function GetWorkAreaRect: TRect;
+function SelectDir(ParentHWnd: HWND; const Caption: string; const Root: WideString; var Path: string): Boolean;
+function ExecuteFile(const FileName, Params, DefaultDir: string; ShowCmd: Integer): HWND;
+function OpenURL(const URL: string): Boolean;
+function OpenEmail(const Email: string): Boolean;
+procedure SetStayOnTop(Form : TCustomForm; StayOnTop: Boolean);
+procedure HideAppFromTaskBar;
+function CheckLangChinesePR: Boolean;
+function ShutdownWindows: Boolean;
+function RebootWindows: Boolean;
+function GetMouseCursorPos: TPoint;
+function CreateShortCut(const OriginalFileName, ShortcutFileName, Arguments,
+  WorkingDir, Description: string; ShowCmd: Integer; IsFolderShortcut: Boolean): Boolean;
+
+// 文件相关
+function GetFileSize(const FileName: string): Int64;
+function GetFolderSize(FolderName: string): Int64;
+function GetFileDate(const FileName: string): TDateTime;
+function SetFileDate(const FileName: string; CreationTime, LastWriteTime, LastAccessTime: TFileTime): Boolean;
+function CopyFileToFolder(FileName, BackupFolder: string): Boolean;
+function AutoRenameFileName(const FullName: string): string;
+function GetTempFileAtPath(const Path: string; const PrefixStr: string = ''): string;
+function IsFileReadOnly(const FileName: string): Boolean;
+function DeleteFileToRecycle(const FileName: string): Boolean;
+procedure DeleteFileEx(FileName:string); 
+function DeleteDirectory(const Dir: string): Boolean;
+function IsEmptyDir(sDir: String): Boolean;
+function ReadFile(const sFile:String):String;     //读文本文件,liliangting 2016-01-18
+function ReadLogFile(const sFile:String):String;  //读文本文件,liliangting 2016-01-18
+procedure WriteLogFile(const sFile,sMsg: string); //写文本文件,liliangting 2016-01-18
+
+// 注册表相关, 增加注册表读写函数
+function SetAutoRunOnStartup(AutoRun, CurrentUser: Boolean; AppTitle: string = ''; AppName: string = ''; AppPara: string = ''): Boolean;
+procedure AutoRun(Flag: Boolean; title:String);
+function ReadReg(const Name: String; CurrentUser: Boolean=true):String;
+function WriteReg(const Name,Value: String; CurrentUser: Boolean=true):Boolean;
+function AssociateFile(const FileExt, FileKey, SoftName, FileDesc: string; IconIndex: Integer = 0; Flush: Boolean = False): Boolean;
+function SaveAppPath(const CompanyName, SoftName, Version: string): Boolean;
+function ReadAppPath(const CompanyName, SoftName, Version: string; var Path: string): Boolean;
+
+// 日期时间相关
+function FileTimeToLocalSystemTime(FTime: TFileTime): TSystemTime;
+function LocalSystemTimeToFileTime(STime: TSystemTime): TFileTime;
+function GetDatePart(DateTime: TDateTime): TDate;
+function GetTimePart(DateTime: TDateTime): TTime;
+
+//获取硬件信息模块
+function GetCPUIDStr:String;                              //获取CPUID并输出字符串
+function GetMacAddress: string;                           //获取网卡MAC地址
+function GetMemUse: Cardinal;                             //获取内存使用量
+
+// 其它函数
+procedure BeginWait;
+procedure EndWait;
+function Iif(Value: Boolean; Value1, Value2: Variant): Variant;
+function Min(V1, V2: Integer): Integer;
+function Max(V1, V2: Integer): Integer;
+function TrimValue(Value, Min, Max: Integer): Integer;
+procedure Swap(var V1, V2: Integer);
+function GetTickDiff(const OldTickCount, NewTickCount: Cardinal): Cardinal;
+function RestrictRectInScr(Rect: TRect; AllVisible: Boolean): TRect;
+function GetModulePath: string;
+function GetModuleSubPath(const SubFolder: string = ''): string;
+function GetAppPath: string;
+function GetAppSubPath(const SubFolder: string = ''): string;
+function GetRectWidth(const R: TRect): Integer;
+function GetRectHeight(const R: TRect): Integer;
+procedure DrawStrokedText(Canvas: TCanvas; X, Y: Integer; const Text: string;
+  FontColor, StrokedColor, SmoothColor: TColor);
+
+//系统Bug修正
+function GetScreenWidth:Integer;                //获取屏幕宽度和高度,即分辨率
+function GetScreenHeight:Integer;
+function GetDesktopWidth:Integer;               //获取桌面宽度和高度
+function GetDesktopHeight:Integer;
+function IsBigInt(const S:String): Boolean;			//2012-04-12增加
+function  IsNTSystem:Boolean;                                   //判断是否NT系统
+procedure ComboBox_XPMan_KeyPress(Sender:TObject;var Key: Char);//修正下拉选择框输入乱码
+Function  formatNum(Number, Length: Integer): string;           //扩展并转换字符长度
+Function  Q(s1:string):string;                                  //加单引号
+procedure Delay(MSecs: Longint);                                //无刷新延时函数
+procedure PreparePrinter(Width,Height:Integer);                 //自定义纸张打印程序
+procedure DeleteMe;
+procedure SetSystemDateFormat(sFormat:string='yyyy-MM-dd');     //设置系统日期格式
+
+//其他函数,liliangting 2015-12-01
+function  Base16Encode(const Src: AnsiString): AnsiString;                    //Base编码字符串
+function  Base16Decode(const Src: AnsiString): AnsiString;                    //Base解码字符串
+function  GetGUID:string;                                                     //自动生成一条GUID
+procedure Delay1(MSecs: Longint);                                             //定时器1
+procedure Delay2(MSecs: Longint);                                             //定时器2
+procedure GetVersionInfo(AppExeName:string);
+procedure EnumComPorts(Ports: TStrings);                                      //枚举系统COM口
+function  CheckComPort(ComPortName: string; var ComPortList: Tstrings): boolean;
+function  StrToHexStr(const S:string):string;                                 //字符串转16进制字符串
+function  StrToHexStr1(const S:string):string;
+function  HexStrToStr(const S:string; bFlag:boolean=false):string;            //16进制字符串转ASCII(支持中英文)
+function  GetMemBytes(var X; size: Integer): string;                           //以十六进制方式查看内存的函数
+procedure GetFileList(FilePath, ExtMask: string; FileList: TStrings; SubDir: Boolean = True);
+procedure GetFileListEx(FilePath, ExtMask: string; FileList: TStrings; SubDir: Boolean = True);
+function  DeleteDir(Path: string;IsDelDir: Boolean = False): Boolean;
+
+//Excel函数,liliangting 2015-12-24
+function GetInstalledWordVersion: Integer;                                    //获取Office版本
+function RandomNum:String;                                                    //生成18位随机数
+
+//TStringList自定义排序参数,liliangting 2017-9-1
+function SortParam(List: TStringList; Index1, Index2: Integer): Integer;
+function RoundEx(const Value: Extended; const Digit: Byte = 0): Extended;
+
+//带中文的String转byte
+function UniCode2GB(S: string): string;
+function GB2UniCode(GB: string): string;
+
+//重写BoolToStr函数,True-1,liliangting 2022-11-14
+function BoolToHexStr(B: Boolean; UseBoolStrs: Boolean = False): string;
+function BoolToString(B: Boolean; UseBoolStrs: Boolean = False): string;
+function BoolToString1(B: Boolean; UseBoolStrs: Boolean = False): string;
+function BoolToString2(B: Boolean; UseBoolStrs: Boolean = False): string;
+function BoolToString3(B: Boolean; UseBoolStrs: Boolean = False): string;
+function BoolToString4(B: Boolean; UseBoolStrs: Boolean = False): string;
+//Int-->boolean,0-False,其他-True,liliangting 2025-02-12
+function IntToBool(AValue: Integer): Boolean;
+
+//将日期格式转换成Unix时间戳 , 长度8字节,liliangting 2017-10-19
+function DateTimeToUnixDate(const ADate: TDateTime): Longint;
+//将数值转成KB、MB、GB
+function FormatFileSize(size:Int64):String;
+//将数值转成#.##万、#.##亿
+function FormatNumberSize(num:Int64):String;
+function SplitStr(str:string;chr:char;i:Integer):string;
+function SplitStrCount(str:string; chr:char):Integer;
+
+//windows杀进程的两种方法
+procedure KillProgram(WindowTitle: string);
+function KillTask(ExeFileName: string): integer;
+//刷新任务栏图标的两种方法
+procedure RefreshTaskbarIcon;
+procedure RefreshTaskbarIcon2;
+
+//强行关闭计算机系统的方法,liliangting 2018-1-4
+function GetOperatingSystem(): string;
+
+//跨进程传递消息的过程方法,liliangting 2018-04-01
+function GetHWndByPID(const hPID: THandle): THandle;
+function GetHwndByAppName(const AppName: String): THandle;
+
+//-----------------------------------------------------------------------------
+//数采开发平台专用方法
+//liliangting 2018-10-20
+//-----------------------------------------------------------------------------
+//封装的动态Dll函数调用方法
+function CallFunc(dllname,funcname:string; const param:array of const):DWORD;   //通用Dll调用方法
+function PingHost(HostIP: String): Boolean;                                     //ping测试网络
+function SecondToTime(sec:Integer):String;                                      //秒转时间字符串
+function SecondToTime1(second: Word): TDateTime;                                //秒转时间
+
+//扩充DateUtils库,增加北京时间转Int64时间格式,注意减去时区
+function DateTimeToUnixPro(const AValue: TDateTime): Int64;
+function UnixToDateTimePro(const AValue: Int64): TDateTime;
+
+//科学计数与浮点型数互转,'-1.4857E-02' <--> '-0.014857'
+function ExpToFloat(s:String):String;
+function FloatToExp(s:String):String;
+
+//------ 几种插值算法 ---------------------------------------------------------
+function LinearInterpolation(x0, y0, x1, y1, x: Double): Double;                         //线性插值算法
+function LagrangeInterpolation(x, y: array of Double; n: Integer; xi: Double): Double;   //拉格朗日插值算法
+function NewtonInterpolation(x, fx: array of Double; n: Integer; t: Double): Double;     //牛顿插值算法
+function LeastSquaresInterpolation(x, y: array of Double; n: Integer; t: Double): Double;//最小二乘法插值算法
+function BayesianInterpolation(x,y: array of Double; xi: Double; sigma: Double): Double; //贝叶斯插值算法
+//-----------------------------------------------------------------------------
+
+function GetMillisecondTimeStamp: Int64;
+
+function SwapHighLowWord(Value: Word): Word;
+
+implementation
+
+{$WARN SYMBOL_PLATFORM OFF}
+{$WARN SYMBOL_DEPRECATED OFF}
+
+type
+  TCPUID = array[1..4] of Longint;//使用CPU内置指令获取CPU编号的二进制
+
+//-----------------------------------------------------------------------------
+// 描述: 判断字符串 S 是不是一个整型数字
+//-----------------------------------------------------------------------------
+function IsInt(const S: string): Boolean;
+var
+  E, R: Integer;
+begin
+  Val(S, R, E);
+  Result := E = 0;
+  E := R; // avoid hints
+end;
+
+//-----------------------------------------------------------------------------
+// 描述: 判断字符串 S 是不是一个浮点型数字
+//-----------------------------------------------------------------------------
+function IsFloat(const S: string): boolean;
+var
+  V: Extended;
+begin
+  Result := TextToFloat(PChar(S), V, fvExtended);
+end;
+
+//-----------------------------------------------------------------------------
+// 描述: 判断字符串 S 是不是一个 Email 地址
+//-----------------------------------------------------------------------------
+function IsEmail(const S: string): Boolean;
+begin
+  Result := True;
+  if Pos('@', S) = 0 then Result := False;
+  if Pos('.', S) = 0 then Result := False;
+end;
+
+//-----------------------------------------------------------------------------
+// 描述: 补全路径字符串后面的 "\"
+//-----------------------------------------------------------------------------
+function PathWithSlash(const Path: string): string;
+begin
+  Result := Trim(Path);
+  if Length(Result) > 0 then
+    Result := IncludeTrailingPathDelimiter(Result);
+end;
+
+//-----------------------------------------------------------------------------
+// 描述: 去掉路径字符串后面的 "\"
+//-----------------------------------------------------------------------------
+function PathWithoutSlash(const Path: string): string;
+begin
+  Result := Trim(Path);
+  if Length(Result) > 0 then
+    Result := ExcludeTrailingPathDelimiter(Result);
+end;
+
+//-----------------------------------------------------------------------------
+// 描述: 将路径和文件名组合在一起
+//-----------------------------------------------------------------------------
+function CombineFileName(const Path, FileName: string): string;
+begin
+  Result := PathWithSlash(Path) + FileName;
+end;
+
+//-----------------------------------------------------------------------------
+// 描述: 补全文件扩展名前面的 "."
+//-----------------------------------------------------------------------------
+function FileExtWithDot(const FileExt: string): string;
+begin
+  Result := FileExt;
+  if Length(Result) > 0 then
+    if Copy(Result, 1, 1) <> '.' then
+      Result := '.' + Result;
+end;
+
+//-----------------------------------------------------------------------------
+// 描述: 去掉文件扩展名前面的 "."
+//-----------------------------------------------------------------------------
+function FileExtWithoutDot(const FileExt: string): string;
+begin
+  Result := FileExt;
+  if Length(Result) > 0 then
+    if Copy(Result, 1, 1) = '.' then
+      Delete(Result, 1, 1);
+end;
+
+//-----------------------------------------------------------------------------
+// 描述: 给数字加上分隔逗号
+// 示例: 1234567 -> 1,234,567
+//-----------------------------------------------------------------------------
+function AddNumberComma(Number: Int64): string;
+var
+  Temp: Double;
+begin
+  Temp := Number;
+  Result := Format('%.0n', [Temp]);
+end;
+
+//-----------------------------------------------------------------------------
+// 描述: 取得文件名的主文件名
+// 示例: "C:\test.dat" -> "test"
+//-----------------------------------------------------------------------------
+function ExtractFileMainName(const FileName: string): string;
+var
+  Ext: string;
+begin
+  Ext := ExtractFileExt(FileName);
+  Result := ExtractFileName(FileName);
+  Result := Copy(Result, 1, Length(Result) - Length(Ext));
+end;
+
+//-----------------------------------------------------------------------------
+// 描述: 返回URL中的文件路径
+// 示例:
+//   ExtractUrlFileName('http://www.download.com/file.zip');
+//   此调用将返回 'http://www.download.com/'.
+//-----------------------------------------------------------------------------
+function ExtractUrlFilePath(const Url: string): string;
+var
+  I: Integer;
+begin
+  I := LastDelimiter('/\:', Url);
+  Result := Copy(Url, 1, I);
+end;
+
+//-----------------------------------------------------------------------------
+// 描述: 返回URL中的文件名
+// 示例:
+//   ExtractUrlFileName('http://www.download.com/file.zip');
+//   此调用将返回 'file.zip'.
+//-----------------------------------------------------------------------------
+function ExtractUrlFileName(const Url: string): string;
+var
+  I: Integer;
+begin
+  I := LastDelimiter('/\:', Url);
+  Result := Copy(Url, I + 1, MaxInt);
+end;
+
+//-----------------------------------------------------------------------------
+// 描述: 去掉文件名中不合法的字符
+// 示例: "tes*t.dat?" -> "test.dat"
+//-----------------------------------------------------------------------------
+function ValidateFileName(const FileName: string): string;
+var
+  I: Integer;
+begin
+  Result := '';
+  for I := 1 to Length(FileName) do
+  begin
+    if not (AnsiChar(FileName[I]) in ['\', '/', ':', '*', '?', '"', '<', '>', '|']) and
+      not (Ord(FileName[I]) < 32) then
+      Result := Result + FileName[I];
+  end;
+end;
+
+//-----------------------------------------------------------------------------
+// 描述: 取得一个用来描述字节数的字符串
+// 参数:
+//   Bytes   - 字节数
+//   Postfix - 单位后缀,缺省为 " KB"
+//-----------------------------------------------------------------------------
+function GetSizeString(Bytes: Int64; const Postfix: string): string;
+var
+  Temp: Double;
+begin
+  if Bytes > 0 then
+  begin
+    Temp := Bytes div 1024;
+    if Bytes mod 1024 <> 0 then Temp := Temp + 1;
+  end else
+    Temp := 0;
+  Result := Format('%s%s', [Format('%.0n', [Temp]), Postfix]);
+end;
+
+//-----------------------------------------------------------------------------
+// 描述: 取得一个用来描述百分比的字符串
+// 参数:
+//   Position, Max   - 当前值 和 最大值
+//   Postfix         - 后缀字符串,缺省为 " %"
+//-----------------------------------------------------------------------------
+function GetPercentString(Position, Max: Int64; const Postfix: string): string;
+begin
+  if Max > 0 then
+    Result := IntToStr(Trunc((Position / Max) * 100)) + Postfix
+  else
+    Result := '100' + Postfix;
+end;
+
+//-----------------------------------------------------------------------------
+// 描述: 缩短字符串的长度以适应显示宽度
+// 参数:
+//   S       - 待缩短的字符串.
+//   Canvas  - 字符串所在的Canvas.
+//   Width   - 最大象素宽度
+//   Suffix  - 如果字符串被截断,则添加什么后缀
+// 返回:
+//   缩短之后的字符串
+//-----------------------------------------------------------------------------
+function RestrictStrWidth(const S: WideString; Canvas: TCanvas;
+  Width: Integer; const Suffix: string): WideString;
+var
+  Src: WideString;
+begin
+  Src := S;
+  Result := S;
+  while (Canvas.TextWidth(Result) > Width) and (Length(Result) > 0) do
+  begin
+    if Length(Src) > 1 then
+    begin
+      Delete(Src, Length(Src), 1);
+      Result := Src + Suffix;
+    end else
+      Delete(Result, Length(Result), 1);
+  end;
+end;
+
+//-----------------------------------------------------------------------------
+// 描述: 缩短文件名的长度以适应最大字节数限制
+// 参数:
+//   FileName - 待缩短的文件名(可以包含路径)
+//   MaxBytes - 最大字节数
+// 返回:
+//   缩短之后的文件名字符串
+//-----------------------------------------------------------------------------
+function RestrictFileNameWidth(const FileName: string;
+  MaxBytes: Integer): string;
+
+  function GetBytes(const S: WideString): Integer;
+  var
+    AnsiStr: string;
+  begin
+    AnsiStr := S;
+    Result := Length(AnsiStr);
+  end;
+
+var
+  MainName, NewMainName: WideString;
+  Ext: string;
+  ExtLen: Integer;
+begin
+  if Length(FileName) <= MaxBytes then
+  begin
+    Result := FileName;
+  end else
+  begin
+    Ext := ExtractFileExt(FileName);
+    MainName := Copy(FileName, 1, Length(FileName) - Length(Ext));
+    ExtLen := Length(Ext);
+
+    NewMainName := MainName;
+    while (GetBytes(NewMainName) + ExtLen > MaxBytes) and (Length(NewMainName) > 0) do
+    begin
+      if Length(MainName) > 1 then
+      begin
+        Delete(MainName, Length(MainName), 1);
+        NewMainName := MainName + '...';
+      end else
+        Delete(NewMainName, Length(NewMainName), 1);
+    end;
+
+    Result := NewMainName + Ext;
+    if Length(Result) > MaxBytes then
+      Result := Copy(Result, 1, MaxBytes);
+  end;
+end;
+
+//-----------------------------------------------------------------------------
+// 描述:计算通配符表达式,支持通配符'*' 和 '?'
+// 参数:
+//   Value            - 母串
+//   Pattern          - 子串
+//   CaseInsensitive  - 是否忽略大小写
+// 返回:
+//   True  -  匹配
+//   False -  不匹配
+// 示例:
+//   LikeString('abcdefg', 'abc*', True);
+//-----------------------------------------------------------------------------
+function LikeString(Value, Pattern: WideString; CaseInsensitive: Boolean): Boolean;
+const
+  MultiWildChar = '*';
+  SingleWildChar = '?';
+var
+  ValuePtr, PatternPtr: PWideChar;
+  I: Integer;
+  B: Boolean;
+begin
+  ValuePtr := PWideChar(Value);
+  PatternPtr := PWideChar(Pattern);
+
+  while True do
+  begin
+    if (CompareStringW(LOCALE_USER_DEFAULT, NORM_IGNORECASE + SORT_STRINGSORT,
+      PatternPtr, Length(PatternPtr), WideChar(MultiWildChar), 1) - 2 = 0) then
+    begin
+      Result := True;
+      Exit;
+    end
+    else if (ValuePtr^ = #0) and (PatternPtr^ <> #0) then
+    begin
+      Result := False;
+      Exit;
+    end
+    else if (ValuePtr^ = #0) then
+    begin
+      Result := True;
+      Exit;
+    end else
+    begin
+      case PatternPtr^ of
+        MultiWildChar:
+          begin
+            for I := 0 to Length(ValuePtr) - 1 do
+            begin
+              if LikeString(ValuePtr + I, PatternPtr + 1, CaseInsensitive) then
+              begin
+                Result := True;
+                Exit;
+              end;
+            end;
+            Result := False;
+            Exit;
+          end;
+        SingleWildChar:
+          begin
+            Inc(ValuePtr);
+            Inc(PatternPtr);
+          end;
+      else
+        begin
+          B := False;
+          if CaseInsensitive then
+          begin
+            if (CompareStringW(LOCALE_USER_DEFAULT, NORM_IGNORECASE + SORT_STRINGSORT,
+              PatternPtr, 1, ValuePtr, 1) - 2 = 0) then
+              B := True;
+          end else
+          begin
+            if (CompareStringW(LOCALE_USER_DEFAULT, SORT_STRINGSORT,
+              PatternPtr, 1, ValuePtr, 1) - 2 = 0) then
+              B := True;
+          end;
+
+          if B then
+          begin
+            Inc(ValuePtr);
+            Inc(PatternPtr);
+          end else
+          begin
+            Result := False;
+            Exit;
+          end;
+        end;
+      end; // case
+    end;
+  end;
+end;
+
+//-----------------------------------------------------------------------------
+// 描述: 分割字符串
+//-----------------------------------------------------------------------------
+procedure SplitString(S: string; Delimiter: Char; List: TStrings);
+var
+  I: Integer;
+begin
+  List.Clear;
+  while Length(S) > 0 do
+  begin
+    I := Pos(Delimiter, S);
+    if I > 0 then
+    begin
+      List.Add(Copy(S, 1, I - 1));
+      Delete(S, 1, I);
+    end else
+    begin
+      List.Add(S);
+      Break;
+    end;
+  end;
+end;
+
+//-----------------------------------------------------------------------------
+// 描述: 判断字符串 Source 是不是以 Left 开始
+//-----------------------------------------------------------------------------
+function StartWith(const Source: string; const Left: string): Boolean;
+var
+  Start: string;
+  Len: Integer;
+begin
+  Len := Length(Left);
+  if (Source = '') or (Left = '') or (Length(Source) < Len) then
+  begin
+    Result := False;
+  end else
+  begin
+    Start := Copy(Source, 1, Len);
+    Result := Start = Left;
+  end;
+end;
+
+//-----------------------------------------------------------------------------
+// 描述: 判断字符串 Source 是不是以 Right 结束
+//-----------------------------------------------------------------------------
+function EndWith(const Source: string; const Right: string): Boolean;
+var
+  EndStr: string;
+  RightLen: Integer;
+  SourceLen: Integer;
+begin
+  RightLen := Length(Right);
+  SourceLen := Length(Source);
+
+  if (Source = '') or (Right = '') or (SourceLen < RightLen) then
+  begin
+    Result := False;
+  end else
+  begin
+    EndStr := Copy(Source, SourceLen - RightLen + 1, RightLen);
+    Result := EndStr = Right;
+  end;
+end;
+
+//------------------------------------------------------------------------------
+// 描述:Pos 函数,返回查找字符出现次数
+//------------------------------------------------------------------------------
+function MyPos(c: Char; const str: string): Integer;
+var
+  i,j: Integer;
+begin
+  j := 0;
+  for i := 1 to Length(str) do
+    if c = str[i] then inc(j);
+  Result:=j;
+end;
+
+//-----------------------------------------------------------------------------
+// 描述: 取得计算机名
+//-----------------------------------------------------------------------------
+function GetComputerName: string;
+const
+  MaxSize = 256;
+var
+  Buffer: array[0..MaxSize-1] of Char;
+  Size: Cardinal;
+begin
+  Size := MaxSize;
+  Windows.GetComputerName(PChar(@Buffer[0]), Size);
+  Result := Buffer;
+end;
+
+//-----------------------------------------------------------------------------
+// 描述: 取得当前系统用户名
+//-----------------------------------------------------------------------------
+function GetWinUserName: string;
+const
+  Size = 255;
+var
+  Buffer: array[0..Size] of Char;
+  Len: DWord;
+begin
+  Len := Size;
+  GetUserName(Buffer, Len);
+  Result := Buffer;
+end;
+
+//-----------------------------------------------------------------------------
+// 描述: 取得 Windows 目录
+//-----------------------------------------------------------------------------
+function GetWindowsDir: string;
+var
+  Buffer: array[0..MAX_PATH] of Char;
+begin
+  GetWindowsDirectory(Buffer, MAX_PATH);
+  Result := PathWithSlash(Buffer);
+end;
+
+//-----------------------------------------------------------------------------
+// 描述: 取得系统临时文件目录
+//-----------------------------------------------------------------------------
+function GetWinTempDir: string;
+const
+  Size = 1024;
+var
+  Buffer: array[0..Size] of Char;
+  LongName: string;
+begin
+  GetTempPath(Size, Buffer);
+  Result := PathWithSlash(Buffer);
+  LongName := GetLongFileName(Result);
+  if Length(LongName) >= Length(Result) then
+    Result := LongName;
+end;
+
+//-----------------------------------------------------------------------------
+// 描述: 取得一个临时文件名(路径为系统临时目录)
+// 参数:
+//   PrefixStr - 文件名前缀,前三个字符有效
+//-----------------------------------------------------------------------------
+function GetWinTempFile(const PrefixStr: string): string;
+var
+  FileName: array[0..MAX_PATH] of Char;
+  LongName: string;
+begin
+  Windows.GetTempFileName(PChar(GetWinTempDir), PChar(PrefixStr), 0, FileName);
+  Result := FileName;
+  LongName := GetLongFileName(Result);
+  if Length(LongName) >= Length(Result) then
+    Result := LongName;
+end;
+
+//-----------------------------------------------------------------------------
+// 描述: 文件的全名(包含路径)
+// 示例:
+//   "test.dat" -> "C:\test.dat"
+//   "C:\a\..\test.dat" -> "C:\test.dat"
+//-----------------------------------------------------------------------------
+function GetFullFileName(const FileName: string): string;
+const
+  Size = 1024;
+var
+  Buffer: array[0..Size] of Char;
+  FileNamePtr: PChar;
+  Len: DWord;
+begin
+  Len := Size;
+  GetFullPathName(PChar(FileName), Len, Buffer, FileNamePtr);
+  Result := Buffer;
+end;
+
+//-----------------------------------------------------------------------------
+// 描述: 长文件名 -> 短文件名(8.3)
+// 备注: FileName 可以是路径,也可以是文件名。
+// 示例:
+//   "C:\Program Files" -> "C:\PROGRA~1"
+//-----------------------------------------------------------------------------
+function GetShortFileName(const FileName: string): string;
+const
+  Size = 1024;
+var
+  Buffer: array[0..Size] of Char;
+begin
+  GetShortPathName(PChar(FileName), Buffer, Size);
+  Result := Buffer;
+end;
+
+//-----------------------------------------------------------------------------
+// 描述: 短文件名(8.3) -> 长文件名
+// 备注: FileName 可以是路径,也可以是文件名。
+// 示例:
+//   "C:\PROGRA~1\COMMON~1\" -> "C:\Program Files\Common Files\"
+//-----------------------------------------------------------------------------
+function GetLongFileName(const FileName: string): string;
+var
+  Name, S: string;
+  SearchRec : TSearchRec;
+begin
+  S := ExcludeTrailingPathDelimiter(FileName);
+  if (Length(S) < 3) or (ExtractFilePath(S) = S) then
+  begin
+    Result := FileName;
+    Exit;
+  end;
+
+  if FindFirst(S, faAnyFile, SearchRec) = 0 then
+    Name := SearchRec.Name
+  else
+    Name := ExtractFileName(S);
+  FindClose(SearchRec);
+
+  Result := GetLongFileName(ExtractFilePath(S)) + Name;
+  if Length(S) <> Length(FileName) then Result := Result + '\';
+end;
+
+//-----------------------------------------------------------------------------
+// 描述: 取得特殊文件夹路径
+// 参数:
+//   FolderID -
+//      CSIDL_DESKTOP
+//      CSIDL_PROGRAMS
+//      CSIDL_RECENT
+//      CSIDL_SENDTO
+//      CSIDL_STARTMENU
+//      CSIDL_STARTUP
+//      CSIDL_TEMPLATES
+//      CSIDL_APPDATA
+// 返回:
+//   若成功,返回带最后斜线(\)的路径;
+//   若失败,返回空字符串。
+// 备注:
+//   若要取"快速启动"的路径,可:
+//   GetSpecialFolder(CSIDL_APPDATA) + 'Microsoft\Internet Explorer\Quick Launch\'.
+//-----------------------------------------------------------------------------
+function GetSpecialFolder(FolderID: Integer): string;
+var
+  PidL: PItemIDList;
+  Buffer: array[0..MAX_PATH] of Char;
+  Malloc: IMalloc;
+begin
+  Result := '';
+  if Failed(SHGetMalloc(Malloc)) then
+    Malloc := nil;
+  if Succeeded(SHGetSpecialFolderLocation(0, FolderID, PidL)) then
+  begin
+    if SHGetPathFromIDList(PidL, Buffer) then
+      Result := Buffer;
+    if Assigned(Malloc) then
+      Malloc.Free(PidL);
+    Result := PathWithSlash(Result);
+  end;
+end;
+
+//-----------------------------------------------------------------------------
+// 描述: 取得 "快速启动" 的路径
+//-----------------------------------------------------------------------------
+function GetQuickLaunchPath: string;
+begin
+  Result := GetSpecialFolder(CSIDL_APPDATA) +
+    'Microsoft\Internet Explorer\Quick Launch\';
+end;
+
+//-----------------------------------------------------------------------------
+// 描述: 取得 SystemDrive 的路径
+//-----------------------------------------------------------------------------
+function GetSystemDrivePath: string;
+begin
+  if Win32Platform = VER_PLATFORM_WIN32_NT then
+    Result := GetEnvVar('SystemDrive')  {don't localize}
+  else
+    Result := '';
+
+  if Result = '' then
+  begin
+    Result := ExtractFileDrive(GetWindowsDir);
+    if Result = '' then
+      Result := 'C:';
+  end;
+
+  Result := PathWithSlash(Result);
+end;
+
+//-----------------------------------------------------------------------------
+// 描述: 取得环境变量的值
+//-----------------------------------------------------------------------------
+function GetEnvVar(const EnvVar: string): string;
+
+  function AdjustLength(var S: string; const R: Cardinal): Boolean;
+  begin
+    Result := Integer(R) < Length(S);
+    SetLength(S, R);
+  end;
+
+const
+  MaxSize = 255;
+var
+  R: DWORD;
+begin
+  SetLength(Result, MaxSize);
+  repeat
+    R := GetEnvironmentVariable(PChar(EnvVar), PChar(Result), Length(Result));
+    if R = 0 then
+    begin
+      Result := '';
+      Break;
+    end;
+  until AdjustLength(Result, R);
+end;
+
+//-----------------------------------------------------------------------------
+// 描述: 取得桌面上除任务栏以外的区域
+//-----------------------------------------------------------------------------
+function GetWorkAreaRect: TRect;
+begin
+  SystemParametersInfo(SPI_GETWORKAREA, 0, @Result, 0);
+end;
+
+//-----------------------------------------------------------------------------
+// 描述: 浏览文件夹,可定位文件夹
+// 参数:
+//   ParentHWnd - 父窗口的句柄
+//   Caption    - 浏览对话框的提示标题
+//   Root       - 根目录
+//   Path       - 存放用户最终选择的目录
+// 返回:
+//   True  - 用户点了确定
+//   False - 用户点了取消
+//-----------------------------------------------------------------------------
+function SelectDir(ParentHWnd: HWND; const Caption: string;
+  const Root: WideString; var Path: string): Boolean;
+const
+{$WRITEABLECONST ON}
+  InitPath: string = '';
+{$WRITEABLECONST OFF}
+var
+  WindowList: Pointer;
+  BrowseInfo: TBrowseInfo;
+  Buffer: PChar;
+  RootItemIDList, ItemIDList: PItemIDList;
+  ShellMalloc: IMalloc;
+  IDesktopFolder: IShellFolder;
+  Eaten, Flags: LongWord;
+
+  function BrowseCallbackProc(hwnd: HWND; uMsg: UINT; lParam: Cardinal; lpData: Cardinal):Integer; stdcall;
+  var
+    R: TRect;
+  begin
+    if uMsg = BFFM_INITIALIZED then
+    begin
+      GetWindowRect(hwnd, R);
+      MoveWindow(hwnd,
+        (Screen.Width - (R.Right - R.Left)) div 2,
+        (Screen.Height - (R.Bottom - R.Top)) div 2,
+        R.Right - R.Left,
+        R.Bottom - R.Top,
+        True);
+      Result := SendMessage(hwnd, BFFM_SETSELECTION, Ord(TRUE), Longint(PChar(InitPath)))
+    end else
+      Result := 1;
+  end;
+
+begin
+  Result := False;
+  InitPath := Path;
+  FillChar(BrowseInfo, SizeOf(BrowseInfo), 0);
+  if (ShGetMalloc(ShellMalloc) = S_OK) and (ShellMalloc <> nil) then
+  begin
+    Buffer := ShellMalloc.Alloc(MAX_PATH);
+    try
+      RootItemIDList := nil;
+      if Root <> '' then
+      begin
+        SHGetDesktopFolder(IDesktopFolder);
+        IDesktopFolder.ParseDisplayName(Application.Handle, nil,
+          POleStr(Root), Eaten, RootItemIDList, Flags);
+      end;
+      with BrowseInfo do
+      begin
+        hwndOwner := ParentHWnd;
+        pidlRoot := RootItemIDList;
+        pszDisplayName := Buffer;
+        lpszTitle := PChar(Caption);
+        ulFlags := BIF_RETURNONLYFSDIRS;
+        lpfn :=@BrowseCallbackProc;
+        lParam :=BFFM_INITIALIZED;
+      end;
+      WindowList := DisableTaskWindows(0);
+      try
+        ItemIDList := ShBrowseForFolder(BrowseInfo);
+      finally
+        EnableTaskWindows(WindowList);
+      end;
+      Result :=  ItemIDList <> nil;
+      if Result then
+      begin
+        ShGetPathFromIDList(ItemIDList, Buffer);
+        ShellMalloc.Free(ItemIDList);
+        Path := Buffer;
+      end;
+    finally
+      ShellMalloc.Free(Buffer);
+    end;
+  end;
+end;
+
+//-----------------------------------------------------------------------------
+// 描述: 用系统 Shell 调用来打开一个文件
+//-----------------------------------------------------------------------------
+function ExecuteFile(const FileName, Params, DefaultDir: string; ShowCmd: Integer): HWND;
+begin
+  Result := ShellExecute(Application.Handle, nil,
+    PChar(FileName), PChar(Params), PChar(DefaultDir), ShowCmd);
+end;
+
+//-----------------------------------------------------------------------------
+// 描述: 打开一个 URL
+// 示例:
+//   OpenURL('http://www.abc.com');
+//   OpenURL('www.abc.com');
+//   OpenURL('file:///c:\');
+//-----------------------------------------------------------------------------
+function OpenURL(const URL: string): Boolean;
+begin
+  Result := ShellExecute(Application.Handle, 'Open', PChar(Trim(URL)), '', '', SW_SHOW) > 32;
+end;
+
+//-----------------------------------------------------------------------------
+// 描述: 打开一个 Email 发送客户端
+//-----------------------------------------------------------------------------
+function OpenEmail(const Email: string): Boolean;
+const
+  SPrefix = 'mailto:';
+var
+  S: string;
+begin
+  S := Trim(Email);
+  if Pos(SPrefix, S) <> 1 then S := SPrefix + S;
+  
+  Result := OpenURL(S);
+end;
+
+//-----------------------------------------------------------------------------
+// 描述: 让窗口保持在最上层
+//-----------------------------------------------------------------------------
+procedure SetStayOnTop(Form : TCustomForm; StayOnTop: Boolean);
+begin
+  if StayOnTop Then
+    SetWindowPos(Form.Handle, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE Or SWP_NOSIZE)
+  else
+    SetWindowPos(Form.Handle, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOMOVE Or SWP_NOSIZE);
+end;
+
+//-----------------------------------------------------------------------------
+// 描述: 隐藏应用程序在任务栏上的选择按钮
+//-----------------------------------------------------------------------------
+procedure HideAppFromTaskBar;
+var
+  ExtendedStyle : Integer;
+begin
+  ExtendedStyle := GetWindowLong(Application.Handle, GWL_EXSTYLE);
+  SetWindowLong(Application.Handle, GWL_EXSTYLE,
+    (ExtendedStyle or WS_EX_TOOLWINDOW) and not WS_EX_APPWINDOW);
+end;
+
+//-----------------------------------------------------------------------------
+// 描述: 检查当前系统语言是否简体中文
+//-----------------------------------------------------------------------------
+function CheckLangChinesePR: Boolean;
+const
+  // LCID Consts
+  LangChinesePR = (SUBLANG_CHINESE_SIMPLIFIED shl 10) or LANG_CHINESE;
+begin
+  Result := SysLocale.DefaultLCID = LangChinesePR;
+end;
+
+//-----------------------------------------------------------------------------
+// 描述: 关机
+//-----------------------------------------------------------------------------
+function ShutdownWindows: Boolean;
+const
+  SE_SHUTDOWN_NAME = 'SeShutdownPrivilege';
+var
+  hToken: THandle;
+  tkp: TTokenPrivileges;
+  tkpo: TTokenPrivileges;
+  Zero: DWORD;
+begin
+  Result := True;
+  if Win32Platform = VER_PLATFORM_WIN32_NT then
+  begin
+    Zero := 0;
+    if not OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES or TOKEN_QUERY, hToken) then
+    begin
+      Result := False;
+      Exit;
+    end;
+    if not LookupPrivilegeValue(nil, SE_SHUTDOWN_NAME, tkp.Privileges[0].Luid) then
+    begin
+      Result := False;
+      Exit;
+    end;
+    tkp.PrivilegeCount := 1;
+    tkp.Privileges[0].Attributes := SE_PRIVILEGE_ENABLED;
+
+    AdjustTokenPrivileges(hToken, False, tkp, SizeOf(TTokenPrivileges), tkpo, Zero);
+    if Boolean(GetLastError()) then
+    begin
+      Result := False;
+      Exit;
+    end else
+      ExitWindowsEx(EWX_SHUTDOWN or EWX_POWEROFF, 0);
+  end else
+    ExitWindowsEx(EWX_SHUTDOWN or EWX_POWEROFF, 0);
+end;
+
+//------------------------------------------------------------------------------
+// 描述:重启
+//------------------------------------------------------------------------------
+function RebootWindows: Boolean;
+const
+  SE_SHUTDOWN_NAME = 'SeShutdownPrivilege';
+var
+  hToken: THandle;
+  tkp: TTokenPrivileges;
+  tkpo: TTokenPrivileges;
+  Zero: DWORD;
+begin
+  Result := True;
+  if Win32Platform = VER_PLATFORM_WIN32_NT then
+  begin
+    Zero := 0;
+    if not OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES or TOKEN_QUERY, hToken) then
+    begin
+      Result := False;
+      Exit;
+    end;
+    if not LookupPrivilegeValue(nil, SE_SHUTDOWN_NAME, tkp.Privileges[0].Luid) then
+    begin
+      Result := False;
+      Exit;
+    end;
+    tkp.PrivilegeCount := 1;
+    tkp.Privileges[0].Attributes := SE_PRIVILEGE_ENABLED;
+
+    AdjustTokenPrivileges(hToken, False, tkp, SizeOf(TTokenPrivileges), tkpo, Zero);
+    if Boolean(GetLastError()) then
+    begin
+      Result := False;
+      Exit;
+    end else
+      ExitWindowsEx(EWX_SHUTDOWN or EWX_REBOOT, 0);
+  end else
+    ExitWindowsEx(EWX_SHUTDOWN or EWX_REBOOT, 0);
+end;
+
+//-----------------------------------------------------------------------------
+// 描述: 取鼠标的当前位置
+// 注意: Mouse.CursorPos 会在带密码保护的屏保启动时抛出异常。
+//-----------------------------------------------------------------------------
+function GetMouseCursorPos: TPoint;
+begin
+  if not Windows.GetCursorPos(Result) then
+    Result := Point(0, 0);
+end;
+
+//-----------------------------------------------------------------------------
+// 描述: 创建快捷方式
+// 参数:
+//   OriginalFileName - 原始文件名,含路径 (即快捷方式指向的文件)
+//   ShortcutFileName - 快捷方式文件名,含路径,含扩展名(.lnk)
+//   Arguments        - 运行参数
+//   WorkingDir       - 工作目录
+//   Description      - 快捷方式描述
+//   ShowCmd          - 运行方式 (SW_SHOW, SW_MINIMIZE, SW_MAXIMIZE)
+//   IsFolderShortcut - 是否文件夹快捷方式
+// 返回:
+//   True  - 成功
+//   False - 失败
+//-----------------------------------------------------------------------------
+function CreateShortCut(const OriginalFileName, ShortcutFileName, Arguments,
+  WorkingDir, Description: string; ShowCmd: Integer;
+  IsFolderShortcut: Boolean): Boolean;
+
+  function IsWindowsXP: Boolean;
+  begin
+    Result := (Win32Platform >= VER_PLATFORM_WIN32_NT) and
+      (Win32MajorVersion >= 5) and (Win32MinorVersion >= 1);
+  end;
+
+const
+  CLSID_FolderShortcut: TGUID = (
+    D1:$0AFACED1; D2:$E828; D3:$11D1; D4:($91,$87,$B5,$32,$F1,$E9,$57,$5D));
+var
+  OleResult: HRESULT;
+  Obj: IUnknown;
+  SL: IShellLink;
+  PF: IPersistFile;
+  WideFileName: WideString;
+begin
+  if IsFolderShortcut then
+  begin
+    try
+      Obj := CreateComObject(CLSID_FolderShortcut);
+    except
+      { Folder shortcuts aren't supported prior to Windows 2000/Me.
+        Fall back to creating a normal shell link. }
+      Obj := nil;
+    end;
+  end;
+  if Obj = nil then
+  begin
+    IsFolderShortcut := False;
+    Obj := CreateComObject(CLSID_ShellLink);
+  end;
+  SL := Obj as IShellLink;
+  SL.SetPath(PChar(OriginalFileName));
+  SL.SetArguments(PChar(Arguments));
+  if WorkingDir <> '' then
+    SL.SetWorkingDirectory(PChar(WorkingDir));
+  SL.SetShowCmd(ShowCmd);
+  if Description <> '' then
+    SL.SetDescription(PChar(Description));
+
+  PF := SL as IPersistFile;
+  { When creating a folder shortcut on 2000/Me, IPersistFile::Save will strip
+    off everything past the last '.' in the ShortcutFileName, so we keep the .lnk
+    extension on to give it something harmless to strip off. XP doesn't do
+    that, so we must remove the .lnk extension ourself. }
+  if IsFolderShortcut and IsWindowsXP then
+    WideFileName := ChangeFileExt(ShortcutFileName, '')
+  else
+    WideFileName := ShortcutFileName;
+  OleResult := PF.Save(PWideChar(WideFileName), True);
+  Result := OleResult = S_OK;
+end;
+
+//-----------------------------------------------------------------------------
+// 描述: 取得文件大小
+//-----------------------------------------------------------------------------
+function GetFileSize(const FileName: string): Int64;
+var
+  Handle: THandle;
+  FindData: TWin32FindData;
+begin
+  Result := -1;
+  Handle := FindFirstFile(PChar(FileName), FindData);
+  if Handle <> INVALID_HANDLE_VALUE then
+  begin
+    Windows.FindClose(Handle);
+    if (FindData.dwFileAttributes and FILE_ATTRIBUTE_DIRECTORY) = 0 then
+    begin
+      Int64Rec(Result).Lo := FindData.nFileSizeLow;
+      Int64Rec(Result).Hi := FindData.nFileSizeHigh;
+    end;
+  end;
+end;
+
+//-----------------------------------------------------------------------------
+// 描述: 取得文件夹大小
+//-----------------------------------------------------------------------------
+function GetFolderSize(FolderName: string): Int64;
+var
+  sr: TSearchRec;
+begin
+  Result := 0;
+  if RightStr(FolderName, 1) <> '\' then FolderName := FolderName + '\';
+  if FindFirst(FolderName + '*.* ', faAnyFile, sr) = 0 then
+    repeat
+      if (sr.Name <> '.') and (sr.Name <> '..') then begin
+        Result := Result + GetFileSize(FolderName + sr.Name);
+        if (sr.Attr and faDirectory) <> 0 then
+          Result := Result + GetFolderSize(FolderName + sr.Name + '\');
+      end;
+    until FindNext(sr) <> 0;
+  FindClose(sr);
+end;
+
+//-----------------------------------------------------------------------------
+// 描述: 取得文件的修改时间
+//-----------------------------------------------------------------------------
+function GetFileDate(const FileName: string): TDateTime;
+var
+  FileDate: Integer;
+begin
+  FileDate := FileAge(FileName);
+  if FileDate = -1 then
+    Result := 0
+  else
+    Result := FileDateToDateTime(FileDate);
+end;
+
+//-----------------------------------------------------------------------------
+// 描述: 设置文件的时间
+//-----------------------------------------------------------------------------
+function SetFileDate(const FileName: string;
+  CreationTime, LastWriteTime, LastAccessTime: TFileTime): Boolean;
+var
+  FileHandle : Integer;
+begin
+  FileHandle := FileOpen(FileName, fmOpenWrite or fmShareDenyNone);
+  try
+    if FileHandle <> Integer(INVALID_HANDLE_VALUE) then
+    begin
+      SetFileTime(FileHandle, @CreationTime, @LastAccessTime, @LastWriteTime);
+      Result := True;
+    end else
+      Result := False;
+  finally
+    FileClose(FileHandle);
+  end;
+end;
+
+//-----------------------------------------------------------------------------
+// 描述: 复制文件到一个文件夹
+//-----------------------------------------------------------------------------
+function CopyFileToFolder(FileName, BackupFolder: string): Boolean;
+var
+  MainFileName: string;
+begin
+  BackupFolder := PathWithSlash(BackupFolder);
+  MainFileName := ExtractFileName(FileName);
+  ForceDirectories(BackupFolder);
+  Result := CopyFile(PChar(FileName), PChar(BackupFolder + MainFileName), False);
+end;
+
+//-----------------------------------------------------------------------------
+// 描述: 自动调整文件名,防止文件名重复
+// 参数:
+//   FullName - 文件的全路径名
+// 示例:
+//   NewName := AutoRenameFileName('C:\Downloads\test.dat');
+//   如果 "C:\Downloads\" 下已经存在test.dat,则函数返回 "C:\Downloads\test(1).dat".
+//-----------------------------------------------------------------------------
+function AutoRenameFileName(const FullName: string): string;
+const
+  SLeftSym = '(';
+  SRightSym = ')';
+
+  // 若S='test(1)',则返回'(1)'; 若S='test(a)',则返回''。
+  function GetNumberSection(const S: string): string;
+  var
+    I: Integer;
+  begin
+    Result := '';
+    if Length(S) < 3 then Exit;
+    if S[Length(S)] = SRightSym then
+    begin
+      for I := Length(S) - 2 downto 1 do
+        if S[I] = SLeftSym then
+        begin
+          Result := Copy(S, I, MaxInt);
+          Break;
+        end;
+    end;
+    if Length(Result) > 0 then
+    begin
+      if not IsInt(Copy(Result, 2, Length(Result)-2)) then
+        Result := '';
+    end;
+  end;
+
+var
+  Number: Integer;
+  Name, Ext, NumSec: string;
+begin
+  Ext := ExtractFileExt(FullName);
+  Result := FullName;
+  while FileExists(Result) do
+  begin
+    Name := Copy(Result, 1, Length(Result) - Length(Ext));
+    NumSec := GetNumberSection(Name);
+    if Length(NumSec) = 0 then
+    begin
+      Result := Name + SLeftSym + '1' + SRightSym + Ext;
+    end else
+    begin
+      Number := StrToInt(Copy(NumSec, 2, Length(NumSec)-2));
+      Inc(Number);
+      Result := Copy(Name, 1, Length(Name) - Length(NumSec)) +
+        SLeftSym + IntToStr(Number) + SRightSym + Ext;
+    end;
+  end;
+end;
+
+//-----------------------------------------------------------------------------
+// 描述: 取得一个临时文件名
+// 参数:
+//   Path      - 临时文件所在路径
+//   PrefixStr - 文件名前缀,前三个字符有效
+//-----------------------------------------------------------------------------
+function GetTempFileAtPath(const Path: string; const PrefixStr: string): string;
+var
+  I: Integer;
+begin
+  I := 1;
+  while True do
+  begin
+    Result := PathWithSlash(Path) + Copy(PrefixStr, 1, 3) + IntToStr(I) + '.tmp';
+    if FileExists(Result) then
+      Inc(I)
+    else
+      Break;
+  end;
+end;
+
+//-----------------------------------------------------------------------------
+// 描述: 判断文件是否具有只读属性
+//-----------------------------------------------------------------------------
+function IsFileReadOnly(const FileName: string): Boolean;
+begin
+  Result := (GetFileAttributes(PChar(FileName)) and FILE_ATTRIBUTE_READONLY) <> 0;
+end;
+
+//-----------------------------------------------------------------------------
+// 描述: 删除文件到回收站
+//-----------------------------------------------------------------------------
+function DeleteFileToRecycle(const FileName: string): Boolean;
+var
+  OpStruct: TSHFileOpStruct;
+begin
+  FillChar(OpStruct, SizeOf(OpStruct), 0);
+  with OpStruct do
+  begin
+    Wnd := 0;
+    wFunc := FO_DELETE;
+    pFrom := PChar(FileName);
+    fFlags := FOF_ALLOWUNDO or FOF_NOCONFIRMATION or FOF_SILENT;
+  end;
+  Result := SHFileOperation(OpStruct) = 0;
+end;
+
+//------------------------------------------------------------------------------
+// 描述:模糊匹配删除文件
+//------------------------------------------------------------------------------
+procedure DeleteFileEx(FileName:string);
+var  
+    FileDir:string;  
+    FileStruct:TSHFileOpStruct;  
+begin  
+    FileDir := FileName;// 'C:\temp\*.txt';
+    FileStruct.Wnd :=0;
+    FileStruct.wFunc := FO_delete;
+    FileStruct.pFrom := Pchar(FileDir+#0);
+    FileStruct.fFlags:= FOF_NOCONFIRMATION;
+    FileStruct.pTo := ' ';
+    if SHFileOperation(FileStruct)=0 then
+      MessageBox(0,'注意: 综合测试台仪器测量数据已经清空!','提示',MB_OK+MB_ICONINFORMATION);
+end;
+
+//-----------------------------------------------------------------------------
+// 描述: 删除空或非空目录
+//-----------------------------------------------------------------------------
+function DeleteDirectory(const Dir: string): Boolean;
+var
+  FileOp: TSHFileOpStruct;
+begin
+  FillChar(FileOp, SizeOf(FileOp), 0);
+  with FileOp do
+  begin
+    Wnd := 0;
+    wFunc := FO_DELETE;
+    pFrom := PChar(Dir + #0);
+    pTo := #0#0;
+    fFlags := FOF_NOCONFIRMATION + FOF_SILENT;
+  end;
+  Result := (SHFileOperation(FileOp) = 0);
+end;
+
+//-----------------------------------------------------------------------------
+// 描述: 判断目录是否为空
+//-----------------------------------------------------------------------------
+function IsEmptyDir(sDir: String): Boolean;
+var
+  sr: TsearchRec;
+begin
+  Result := True;
+  if Copy(sDir, Length(sDir) - 1, 1) <> '\' then sDir := sDir + '\';
+  if FindFirst(sDir + '*.*', faAnyFile, sr) = 0 then
+    repeat
+      if (sr.Name <> '.') and (sr.Name <> '..') then
+      begin
+        Result := False;
+        break;
+      end;
+    until FindNext(sr) <> 0;
+  FindClose(sr);
+end;
+
+//------------------------------------------------------------------------------
+// 读取文本文件的一种方法
+//------------------------------------------------------------------------------
+function ReadFile(const sFile:String):String;
+var
+  sList: TStringlist;
+begin
+  sList := TStringList.Create;
+  try
+    if FileExists(sFile) then begin
+      sList.LoadFromFile(sFile);
+      Result := sList.GetText;
+    end;
+  finally
+    sList.Free;
+  end;
+end;
+
+//------------------------------------------------------------------------------
+// 读取文件:
+//1,关联文件:AssignFile(pMyFile,'c:\ttt.csv');
+//2,打开文件:Reset(pMyFile);
+//3,读取一行:Readln(pMyFile,pStr);
+//4,关闭文件:CloseFile(pMyFile);
+//------------------------------------------------------------------------------
+function ReadLogFile(const sFile:String):String;
+var
+  pMyFile:textfile;
+  pStr : string;
+begin
+  try
+    Assignfile(pMyFile,sFile);
+    if FileExists(sFile) then begin
+      Reset(pMyFile);
+      while not Eof(pMyFile) do begin
+        Readln(pMyFile,pStr);
+        //next;
+      end;
+    end;
+  finally
+    CloseFile(pMyFile);
+  end;
+  Result := pStr;
+end; 
+
+//------------------------------------------------------------------------------
+// 写入文件:
+//1,关联文件:AssignFile(pMyFile,'c:\ttt.csv');
+//2,打开文件:ReWrite(pMyFile);   //如果文件不存在,用ReWrite打开
+//             Append(pMyFile);   //如果文件已经存在,追加内容,用Append打开
+//3,写入一行:WriteLn(pMyFile,pStr);
+//4,关闭文件:CloseFile(pMyFile);
+//------------------------------------------------------------------------------
+procedure WriteLogFile(const sFile,sMsg: string);
+var
+  pMyFile: textFile;
+begin
+  try
+    AssignFile(pMyFile,sFile);
+    if FileExists(sFile) then
+      Append(pMyFile)
+    else
+      ReWrite(pMyFile);
+    WriteLn(pMyFile,sMsg);
+  finally
+    CloseFile(pMyFile);
+  end;
+end;
+
+//-----------------------------------------------------------------------------
+// 描述: 设置自启动
+// 参数:
+//   AutoRun     - 是否自启动
+//   CurrentUser - 是否只对当前用户有效
+//   AppTitle    - 应用程序的标题,如 "MSN"
+//   AppPara     - 自启动的命令行参数,如 "/min"
+//-----------------------------------------------------------------------------
+function SetAutoRunOnStartup(AutoRun, CurrentUser: Boolean;
+  AppTitle, AppName, AppPara: string): Boolean;
+var
+  R: TRegistry;
+  Key : string;
+begin
+  Result := True;
+  try
+    R := TRegistry.Create;
+    try
+      if CurrentUser then
+        R.RootKey := HKEY_CURRENT_USER
+      else
+        R.RootKey := HKEY_LOCAL_MACHINE;
+      Key := '\Software\Microsoft\Windows\CurrentVersion\Run\';
+
+      if AppTitle = '' then AppTitle := Application.Title;
+      if AppName = ''  then AppName := Application.ExeName;
+      if AppPara <> '' then AppName := AppName + ' ' + AppPara;
+
+      if R.OpenKey(Key, True) then
+      begin
+        if AutoRun then
+          R.WriteString(AppTitle, AppName)
+        else
+          R.DeleteValue(AppTitle);
+      end;
+    finally
+      R.Free;
+    end;
+  except
+    Result := False;
+  end;
+end;
+
+{开机运行。}
+procedure AutoRun(Flag: Boolean; title:String);
+var
+  tempreg: TRegistry;
+begin
+  tempreg := TRegistry.Create;
+  try
+    tempreg.RootKey := HKEY_CURRENT_USER;
+    tempreg.OpenKey('SOFTWARE\Microsoft\Windows\CurrentVersion\Run', True);
+    if Flag then
+      tempreg.WriteString(title, '"' + ParamStr(0) + '"')
+    else begin
+      tempreg.DeleteValue(title);
+    end;
+  finally
+    tempreg.Closekey;
+    tempreg.Free;
+  end;
+end;
+
+//-----------------------------------------------------------------------------
+// 描述: 读注册表指定键
+// 参数:
+//   CurrentUser - 是否只对当前用户有效
+//   Name        - 应用程序的标题,如 "MSN"
+// 返回:Value   - 返回Name对应值
+//-----------------------------------------------------------------------------
+function ReadReg(const Name: String; CurrentUser: Boolean=true):String;
+var
+  R: TRegistry;
+  Key : String;
+begin
+  Result := '';
+  R := TRegistry.Create;
+  try
+    if CurrentUser then
+      R.RootKey := HKEY_CURRENT_USER
+    else
+      R.RootKey := HKEY_LOCAL_MACHINE;
+    Key := '\Software\liliangting\';
+
+    if R.OpenKey(Key,True) then
+      Result := R.ReadString(Name);
+  finally
+    R.Free;
+  end;
+end;
+
+//写注册表指定值
+function WriteReg(const Name,Value: String; CurrentUser: Boolean=true):Boolean;
+var
+  R: TRegistry;
+  Key : String;
+begin
+  Result := false;
+  R := TRegistry.Create;
+  try
+    if CurrentUser then
+      R.RootKey := HKEY_CURRENT_USER
+    else
+      R.RootKey := HKEY_LOCAL_MACHINE;
+    Key := '\Software\liliangting\';
+
+    if R.OpenKey(Key,True) then begin
+      R.WriteString(Name, Value);
+      Result := true;
+    end;
+  finally
+    R.Free;
+  end;
+end;
+
+//-----------------------------------------------------------------------------
+// 描述: 文件关联
+// 参数:
+//   FileExt      - 文件扩展名
+//   FileKey      - 该文件类型的英文符号
+//   SoftName     - 软件的名字 (用于显示在资源管理器的右键菜单上)
+//   FileDesc     - 文件类型的描述
+//   IconIndex    - 图标序号(0-based)
+//   Flush        - 是否刷新Windows缓冲
+// 示例:
+//   AssociateFile('.edf', 'EDiaryFile', 'EDiary', '电子日记本文件');
+//-----------------------------------------------------------------------------
+function AssociateFile(const FileExt, FileKey, SoftName, FileDesc: string;
+  IconIndex: Integer; Flush: Boolean): Boolean;
+var
+  R: TRegistry;
+begin
+  Result := True;
+  try  // Win2000下受限用户执行此操作将会报错
+    R := TRegistry.Create;
+    try
+      R.RootKey := HKEY_CLASSES_ROOT;
+      R.OpenKey('\' + FileExt, True);
+      R.WriteString('', FileKey);
+      R.OpenKey('\' + FileKey, True);
+      R.WriteString('', FileDesc);
+      R.OpenKey('\' + FileKey + '\Shell\Open\Command', True);
+      R.WriteString('', Application.ExeName + ' "%1"');
+      R.OpenKey('\' + FileKey + '\Shell\Open with ' + SoftName + '\Command', True);
+      R.WriteString('', Application.ExeName + ' "%1"');
+      R.OpenKey('\' + FileKey + '\DefaultIcon', True);
+      R.WriteString('', Application.ExeName + ',' + IntToStr(IconIndex));
+    finally
+      R.Free;
+    end;
+    if Flush then SHChangeNotify(SHCNE_ASSOCCHANGED, SHCNF_IDLIST, nil, nil);
+  except
+    Result := False;
+  end;
+end;
+
+//-----------------------------------------------------------------------------
+// 描述: 在注册表中记下程序路径
+//-----------------------------------------------------------------------------
+function SaveAppPath(const CompanyName, SoftName, Version: string): Boolean;
+const
+  SPathKey = 'Path'; 
+var
+  R: TRegistry;
+  Key: string;
+begin
+  Result := True;
+  try
+    R := TRegistry.Create;
+    try
+      R.RootKey := HKEY_CURRENT_USER;
+      Key := '\Software\' + CompanyName + '\' + SoftName + '\' + Version + '\';
+      if R.OpenKey(Key, True) then
+        R.WriteString(SPathKey, GetModulePath);
+    finally
+      R.Free;
+    end;
+  except
+    Result := False;
+  end;
+end;
+
+//-----------------------------------------------------------------------------
+// 描述: 从注册表中读取程序路径
+//-----------------------------------------------------------------------------
+function ReadAppPath(const CompanyName, SoftName, Version: string; var Path: string): Boolean;
+const
+  SPathKey = 'Path'; 
+var
+  R: TRegistry;
+  Key: string;
+begin
+  try
+    R := TRegistry.Create;
+    try
+      R.RootKey := HKEY_CURRENT_USER;
+      Key := '\Software\' + CompanyName + '\' + SoftName + '\' + Version + '\';
+      Result := R.OpenKey(Key, False);
+      if Result then
+        Path := R.ReadString(SPathKey);
+    finally
+      R.Free;
+    end;
+  except
+    Result := False;
+  end;
+end;
+
+//-----------------------------------------------------------------------------
+// 描述: FileTime -> LocalSystemTime
+//-----------------------------------------------------------------------------
+function FileTimeToLocalSystemTime(FTime: TFileTime): TSystemTime;
+var
+  STime: TSystemTime;
+begin
+  FileTimeToLocalFileTime(FTime, FTime);
+  FileTimeToSystemTime(FTime, STime);
+  Result := STime;
+end;
+
+//-----------------------------------------------------------------------------
+// 描述: LocalSystemTime -> FileTime
+//-----------------------------------------------------------------------------
+function LocalSystemTimeToFileTime(STime: TSystemTime): TFileTime;
+var
+  FTime: TFileTime;
+begin
+  SystemTimeToFileTime(STime, FTime);
+  LocalFileTimeToFileTime(FTime, FTime);
+  Result := FTime;
+end;
+
+//-----------------------------------------------------------------------------
+// 描述: 返回 TDateTime 中的日期部分
+//-----------------------------------------------------------------------------
+function GetDatePart(DateTime: TDateTime): TDate;
+begin
+  Result := Trunc(DateTime);
+end;
+
+//-----------------------------------------------------------------------------
+// 描述: 返回 TDateTime 中的时间部分
+//-----------------------------------------------------------------------------
+function GetTimePart(DateTime: TDateTime): TTime;
+begin
+  Result := DateTime - Trunc(DateTime);
+end;
+
+//-----------------------------------------------------------------------------
+//获取CPUID并输出字符串
+//-----------------------------------------------------------------------------
+function GetCPUID: TCPUID; assembler; register;
+asm
+  PUSH EBX {Save affected register}
+  PUSH EDI
+  MOV EDI,EAX {@Resukt}
+  MOV EAX,1
+  DW $A20F {CPUID Command}
+  STOSD {CPUID[1]}
+  MOV EAX,EBX
+  STOSD {CPUID[2]}
+  MOV EAX,ECX
+  STOSD {CPUID[3]}
+  MOV EAX,EDX
+  STOSD {CPUID[4]}
+  POP EDI {Restore registers}
+  POP EBX
+end;
+
+//输出函数: 获取CPUID并输出字符串
+function GetCPUIDStr:String;
+var
+  CPUID:TCPUID;
+begin
+  CPUID:=GetCPUID;
+  Result:=IntToStr(CPUID[1])+IntToStr(CPUID[2])+IntToStr(CPUID[3])+IntToStr(CPUID[4]);
+end;
+
+//获取网卡MAC地址部分
+//调用系统函数获取当前可用的mac
+function GetMacAddress: string;
+var
+  Lib: Cardinal;
+  Func: function(GUID: PGUID): Longint; stdcall;
+  GUID1, GUID2: TGUID;
+begin
+  Result := '000000000000';
+  Lib := LoadLibrary('rpcrt4.dll');
+  if Lib <> 0 then
+  begin
+    if Win32Platform <>VER_PLATFORM_WIN32_NT then
+      @Func := GetProcAddress(Lib, 'UuidCreate')
+      else @Func := GetProcAddress(Lib, 'UuidCreateSequential');
+    if Assigned(Func) then
+    begin
+      if (Func(@GUID1) = 0) and
+        (Func(@GUID2) = 0) and
+        (GUID1.D4[2] = GUID2.D4[2]) and
+        (GUID1.D4[3] = GUID2.D4[3]) and
+        (GUID1.D4[4] = GUID2.D4[4]) and
+        (GUID1.D4[5] = GUID2.D4[5]) and
+        (GUID1.D4[6] = GUID2.D4[6]) and
+        (GUID1.D4[7] = GUID2.D4[7]) then
+      begin
+        Result :=IntToHex(GUID1.D4[2], 2) + IntToHex(GUID1.D4[3], 2) +
+                 IntToHex(GUID1.D4[4], 2) + IntToHex(GUID1.D4[5], 2) +
+                 IntToHex(GUID1.D4[6], 2) + IntToHex(GUID1.D4[7], 2);
+      end;
+    end;
+    FreeLibrary(Lib);
+  end;
+end;
+
+//获取实时内存使用量
+function GetMemUse: Cardinal;
+  function GetProcessMemUse(PID: Cardinal): Cardinal;
+  var
+    pmc: pprocess_memory_counters;//uses psApi
+    ProcHandle: HWND;
+    iSize: DWORD;
+  begin
+    Result := 0;
+    iSize := SizeOf(_PROCESS_MEMORY_COUNTERS);
+    GetMem(pmc, iSize);
+    try
+      pmc^.cb := iSize;
+      ProcHandle := OpenProcess(PROCESS_QUERY_INFORMATION or PROCESS_VM_READ, False, PID);
+      if GetProcessMemoryInfo(ProcHandle, pmc, iSize) then
+        Result := pmc^.WorkingSetSize;
+    finally
+      FreeMem(pmc);
+    end;
+  end;
+begin
+  Result := GetProcessMemUse(GetCurrentProcessId);
+end;
+//-----------------------------------------------------------------------------
+// 描述: 开始等待
+//-----------------------------------------------------------------------------
+procedure BeginWait;
+begin
+  Screen.Cursor := crHourGlass;
+end;
+
+//-----------------------------------------------------------------------------
+// 描述: 停止等待
+//-----------------------------------------------------------------------------
+procedure EndWait;
+begin
+  Screen.Cursor := crDefault;
+end;
+
+//-----------------------------------------------------------------------------
+// 描述: 相当于C语言中的 exp ? v1 : v2
+//-----------------------------------------------------------------------------
+function Iif(Value: Boolean; Value1, Value2: Variant): Variant;
+begin
+  if Value then Result := Value1
+  else Result := Value2;
+end;
+
+//-----------------------------------------------------------------------------
+// 描述: 取 V1, V2 中的最小值
+//-----------------------------------------------------------------------------
+function Min(V1, V2: Integer): Integer;
+begin
+  if V1 > V2 then Result := V2
+  else Result := V1;
+end;
+
+//-----------------------------------------------------------------------------
+// 描述: 取 V1, V2 中的最大值
+//-----------------------------------------------------------------------------
+function Max(V1, V2: Integer): Integer;
+begin
+  if V1 > V2 then Result := V1
+  else Result := V2;
+end;
+
+//-----------------------------------------------------------------------------
+// 描述: 调整 Value,使 (Value >= Min) and (Value <= Max)
+//-----------------------------------------------------------------------------
+function TrimValue(Value, Min, Max: Integer): Integer;
+begin
+  if Value < Min then Value := Min;
+  if Value > Max then Value := Max;
+  Result := Value;
+end;
+
+//-----------------------------------------------------------------------------
+// 描述: 交换 V1, V2
+//-----------------------------------------------------------------------------
+procedure Swap(var V1, V2: Integer);
+var
+  Temp: Integer;
+begin
+  Temp := V1;
+  V1 := V2;
+  V2 := Temp;
+end;
+
+//-----------------------------------------------------------------------------
+// 描述: 取得两个 Ticks 之差
+//-----------------------------------------------------------------------------
+function GetTickDiff(const OldTickCount, NewTickCount: Cardinal): Cardinal;
+begin
+  if NewTickCount >= OldTickCount then
+  begin
+    Result := NewTickCount - OldTickCount;
+  end else
+  begin
+    Result := High(Cardinal) - OldTickCount + NewTickCount;
+  end;
+end;
+
+//-----------------------------------------------------------------------------
+// 描述: 限制矩形区域不要超出屏幕范围
+// 参数:
+//   Rect       - 待调整的矩形区域
+//   AllVisible - 矩形区域是不是要全部可见
+// 返回:
+//   调整后的矩形区域 (宽、高不变)
+//-----------------------------------------------------------------------------
+function RestrictRectInScr(Rect: TRect; AllVisible: Boolean): TRect;
+const
+  Space = 100;
+var
+  ScrRect: TRect;
+  W, H: Integer;
+begin
+  ScrRect := Screen.WorkAreaRect;
+  W := Rect.Right - Rect.Left;
+  H := Rect.Bottom - Rect.Top;
+
+  if AllVisible then
+  begin
+    if W > (ScrRect.Right - ScrRect.Left) then W := (ScrRect.Right - ScrRect.Left);
+    if H > (ScrRect.Bottom - ScrRect.Top) then H := (ScrRect.Bottom - ScrRect.Top);
+    if Rect.Right > ScrRect.Right then
+      Rect.Left := ScrRect.Right - W;
+    if Rect.Bottom > ScrRect.Bottom then Rect.Top := ScrRect.Bottom - H;
+    if Rect.Left < ScrRect.Left then Rect.Left := ScrRect.Left;
+    if Rect.Top < ScrRect.Top then Rect.Top := ScrRect.Top;
+    Rect.Right := Rect.Left + W;
+    Rect.Bottom := Rect.Top + H;
+  end else
+  begin
+    if Rect.Left >= ScrRect.Right - Space then
+      Rect.Left := ScrRect.Right - Space;
+    if Rect.Top >= ScrRect.Bottom - Space then
+      Rect.Top := ScrRect.Bottom - Space;
+    if Rect.Right <= ScrRect.Left + Space then
+      Rect.Left := ScrRect.Left - (Rect.Right - Rect.Left) + Space;
+    if Rect.Top < ScrRect.Top then
+      Rect.Top := ScrRect.Top;
+    Rect.Right := Rect.Left + W;
+    Rect.Bottom := Rect.Top + H;
+  end;
+  Result := Rect;
+end;
+
+//-----------------------------------------------------------------------------
+// 描述: 取得自身 DLL或OCX或EXE 所在的路径
+// 注意: 用 Application.ExeName 无法取得 ActiveX 的路径。
+//-----------------------------------------------------------------------------
+function GetModulePath: string;
+var
+  S: array[0..MAX_PATH] of Char;
+begin
+  GetModuleFileName(HInstance, S, MAX_PATH);
+  Result := PathWithSlash(ExtractFilePath(S));
+end;
+
+//-----------------------------------------------------------------------------
+// 描述: 取得自身 DLL或OCX或EXE 所在路径的子目录路径
+//-----------------------------------------------------------------------------
+function GetModuleSubPath(const SubFolder: string = ''): string;
+begin
+  Result := GetModulePath + SubFolder;
+  Result := PathWithSlash(Result);
+end;
+
+//-----------------------------------------------------------------------------
+// 描述: 取得自身 EXE 所在路径
+//-----------------------------------------------------------------------------
+function GetAppPath: string;
+begin
+  Result := ExtractFilePath(Application.ExeName);
+end;
+
+//-----------------------------------------------------------------------------
+// 描述: 取得自身 EXE 所在路径的子目录路径
+//-----------------------------------------------------------------------------
+function GetAppSubPath(const SubFolder: string): string;
+begin
+  Result := GetAppPath + SubFolder;
+  Result := PathWithSlash(Result);
+end;
+
+//-----------------------------------------------------------------------------
+// 描述: 返回矩形 R 的宽度
+//-----------------------------------------------------------------------------
+function GetRectWidth(const R: TRect): Integer;
+begin
+  Result := R.Right - R.Left;
+end;
+
+//-----------------------------------------------------------------------------
+// 描述: 返回矩形 R 的高度
+//-----------------------------------------------------------------------------
+function GetRectHeight(const R: TRect): Integer;
+begin
+  Result := R.Bottom - R.Top;
+end;
+
+//-----------------------------------------------------------------------------
+// 描述: 绘制有边框的文字
+//-----------------------------------------------------------------------------
+procedure DrawStrokedText(Canvas: TCanvas; X, Y: Integer; const Text: string;
+  FontColor, StrokedColor, SmoothColor: TColor);
+var
+  SaveStyle: TBrushStyle;
+  SaveFontColor: TColor;
+begin
+  SaveStyle := Canvas.Brush.Style;
+  SaveFontColor := Canvas.Font.Color;
+  try
+    Canvas.Brush.Style := bsClear;
+
+    Canvas.Font.Color := SmoothColor;
+    Canvas.TextOut(X - 1, Y - 1, Text);
+    Canvas.TextOut(X - 1, Y + 1, Text);
+    Canvas.TextOut(X + 1, Y - 1, Text);
+    Canvas.TextOut(X + 1, Y + 1, Text);
+
+    Canvas.Font.Color := StrokedColor;
+    Canvas.TextOut(X, Y - 1, Text);
+    Canvas.TextOut(X, Y + 1, Text);
+    Canvas.TextOut(X + 1, Y, Text);
+    Canvas.TextOut(X - 1, Y, Text);
+
+    Canvas.Font.Color := FontColor;
+    Canvas.TextOut(X, Y, Text);
+  finally
+    Canvas.Font.Color := SaveFontColor;
+    Canvas.Brush.Style := SaveStyle;
+  end;
+end;
+
+//------------------------------------------------------------------------------
+//返回屏幕分辨率宽度
+//------------------------------------------------------------------------------
+function GetScreenWidth:Integer;
+var
+  sysinfo: TSystemInfo;
+begin
+  GetSystemInfo(sysinfo);
+  Result:= GetSystemMetrics(SM_CXSCREEN);   //分辨率宽
+  //y:= GetSystemMetrics(SM_CYSCREEN);   //分辨率高
+end;
+//返回屏幕分辨率高度
+function GetScreenHeight:Integer;
+var
+  sysinfo: TSystemInfo;
+begin
+  GetSystemInfo(sysinfo);
+  //x:= GetSystemMetrics(SM_CXSCREEN);   //分辨率宽
+  Result:= GetSystemMetrics(SM_CYSCREEN);   //分辨率高
+end;
+
+//------------------------------------------------------------------------------
+//返回桌面高度和宽度
+//------------------------------------------------------------------------------
+function GetDesktopWidth:Integer;
+var
+  hRect : TRect;
+begin
+  SystemParametersInfo(SPI_GETWORKAREA,0,@hRect, 0);
+  Result:= hRect.Right; //返回宽度
+end;
+function GetDesktopHeight:Integer;
+var
+  hRect : TRect;
+begin
+  SystemParametersInfo(SPI_GETWORKAREA,0,@hRect, 0);
+  Result:= hRect.Bottom; //返回宽度
+end;
+
+//-----------------------------------------------------------------------------
+// 描述: 判断字符串是否为任意长度带整数
+//-----------------------------------------------------------------------------
+function IsBigInt(const S:String): Boolean; //变量S为要判断的字符串,返回true则正确
+var
+  i : integer;
+begin
+  Result:=True;
+  for i :=1 to length(s) do
+     if not (s[i] in ['0'..'9']) then   //判断字符串每个字符即s[i],是否为"0"到'9"数字
+       Result:=False;
+end;
+
+//------------------------------------------------------------------------------
+//2011-10-26 新增ComboBox_XPMan_KeyPress函数,解决ComboBox控件输入乱码问题,
+//           在KeyPress事件中执行ComboBox_XPMan_KeyPress即可解决。
+//------------------------------------------------------------------------------
+Function IsNTSystem:Boolean;
+var
+  info:OSVERSIONINFO;
+begin
+  info.dwOSVersionInfoSize:=sizeof(info);
+  GetVersionEx(info);
+  Result:=info.dwPlatformId=VER_PLATFORM_WIN32_NT;
+end;
+
+procedure ComboBox_XPMan_KeyPress(Sender:TObject;var Key: Char);
+  {子函数,处理消息}
+  function HasSelectedText(CB_HWND:HWND; var StartPos, EndPos: DWORD): Boolean;
+  begin
+    SendMessage(CB_HWND, CB_GETEDITSEL, Integer(@StartPos),
+    Integer(@EndPos));
+    Result := EndPos > StartPos;
+  end;
+var
+  StartPos, EndPos: DWORD;
+  OldText, SaveText: WideString; //关键在此,中间字符串要设为宽字符串型
+  LastByte: Integer;
+  TheCB:TComboBox;
+  CBHandle:HWND;
+begin
+  if not IsNTSystem then Exit; //非NT系统则退出
+
+  TheCB:=TComboBox(Sender);
+  CBHandle:=TheCB.Handle;
+
+  if not TheCB.AutoComplete then exit;
+
+  if ord(Key) = VK_BACK then
+  begin
+    SaveText := TheCB.Text;
+    if HasSelectedText(CBHandle, StartPos, EndPos) then
+    begin
+      SendMessage(CBHandle,CB_GETEDITSEL,Integer(@StartPos),Integer(@EndPos));
+      Delete(SaveText, StartPos + 1, EndPos - StartPos);
+      SendMessage(CBHandle, CB_SETCURSEL, -1, 0);
+      TheCB.Text := SaveText;
+      SendMessage(CBHandle,CB_SETEDITSEL,0,MakeLParam(StartPos,StartPos));
+      Key := #0;
+    end
+    else if(TheCB.Style in [csDropDown,csSimple]) and (Length(SaveText)>0) then
+    begin
+      LastByte := StartPos;
+      OldText := Copy(SaveText, 1, LastByte - 1);
+      SendMessage(CBHandle, CB_SETCURSEL, -1, 0);
+      TheCB.Text := OldText + Copy(SaveText, EndPos + 1, MaxInt);
+      SendMessage(CBHandle, CB_SETEDITSEL, 0, MakeLParam(LastByte - 1,LastByte - 1));
+      Key := #0;
+    end;
+  end;
+end;
+
+//--------------------------------------------------
+// 函数: 格式化数字, 按指定位数扩展数字,转换字符串
+// 入参: 待格式化的数字,扩展位数
+// 返回: 转换的字符串
+// 例如: formatNum(12,4) = '0012'
+//--------------------------------------------------
+Function formatNum(Number, Length: Integer): string;
+var
+  i : Integer;
+  s1: string;
+begin
+  s1:='';
+  for i:=0 to Length-1 do
+    s1:=s1+'0';
+  Result:=RightStr(s1+IntToStr(Number), Length);
+end;
+
+//------------------------------------------------------------------------------
+// 函数:格式化字符串,加单引号
+// 入参:待格式化的字符串
+// 返回:转换的字符串
+// 例如:Q('abc') = ''abc''
+//------------------------------------------------------------------------------
+Function Q(s1:string):string;
+begin
+  Result:=Quotedstr(s1);
+end;
+
+//无刷新延时函数
+procedure Delay(MSecs: Longint);
+var
+  FirstTickCount, Now: Longint;
+begin
+  FirstTickCount := GetTickCount();
+  repeat
+    Application.ProcessMessages;
+    Now := GetTickCount();
+  until (Now - FirstTickCount >= MSecs) or (Now < FirstTickCount);
+end;
+
+//------------------------------------------------------------------------------
+// 函数: 自定义纸张打印函数
+// 以下程序将打印机纸张设为:114mm*190mm:
+// Uses Printers;
+//------------------------------------------------------------------------------
+procedure PreparePrinter(Width,Height:Integer);
+var 
+  aDevice: array[0..CCHDEVICENAME-1] of Char; 
+  aDriver: array[0..MAX_PATH-1] of Char; 
+  aPort:   array[0..31] of Char; 
+  hDevMode: THandle; 
+  pDevMode: PDeviceMode; 
+begin 
+  //获取打印机DeviceMode的句柄 
+  Printer.GetPrinter(aDevice, aDriver, aPort, hDevMode); 
+  if hDevMode <> 0 then 
+  begin 
+    //获取指向DeviceMode的指针 
+    pDevMode:=GlobalLock(hDevMode); 
+    if pDevMode <> nil then 
+    begin 
+      pDevMode^.dmPaperSize:= DMPAPER_USER; //自定义纸张:256
+      pDevMode^.dmPaperLength:=Width*10;
+      pDevMode^.dmPaperWidth:= Height*10;
+      pDevMode^.dmFields:=pDevMode^.dmFields or DM_PAPERSIZE;//以下三句是对应dmFields成员置位 
+      pDevMode^.dmFields:=pDevMode^.dmFields or DM_PAPERLENGTH; 
+      pDevMode^.dmFields:=pDevMode^.dmFields or DM_PAPERWIDTH; 
+      ResetDC(Printer.Handle, pDevMode^);  //设置打印机设备句柄
+      GlobalUnlock(hDevMode); 
+    end; 
+  end; 
+end;
+
+//------------------------------------------------------------------------------
+// 描述:程序符合要求时自动销毁主程序
+//------------------------------------------------------------------------------
+procedure DeleteMe;
+var
+  BatchFile: TextFile;
+  BatchFileName: string;
+  ProcessInfo: TProcessInformation;
+  StartUpInfo: TStartupInfo;
+begin
+  BatchFileName := ExtractFilePath(ParamStr(0)) + '_deleteme.bat';
+  AssignFile(BatchFile, BatchFileName);
+  Rewrite(BatchFile);
+
+  Writeln(BatchFile, ':try');
+  Writeln(BatchFile, 'del "' + ParamStr(0) + '"');
+  Writeln(BatchFile,
+    'if exist "' + ParamStr(0) + '"' + ' goto try');
+  Writeln(BatchFile, 'del %0');
+  CloseFile(BatchFile);
+
+  FillChar(StartUpInfo, SizeOf(StartUpInfo), $00);
+  StartUpInfo.dwFlags := STARTF_USESHOWWINDOW;
+  StartUpInfo.wShowWindow := SW_HIDE;
+  if CreateProcess(nil, PChar(BatchFileName), nil, nil,
+    False, IDLE_PRIORITY_CLASS, nil, nil, StartUpInfo,
+    ProcessInfo) then
+  begin
+    CloseHandle(ProcessInfo.hThread);
+    CloseHandle(ProcessInfo.hProcess);
+  end;
+end;
+
+//------------------------------------------------------------------------------
+// 在系统运行时自动改变系统的日期格式
+// 入参: 日期格式,如 yyyy-MM-dd
+//------------------------------------------------------------------------------
+procedure SetSystemDateFormat(sFormat:string='yyyy-MM-dd');
+begin
+  SetLocaleInfo(LOCALE_SLONGDATE,LOCALE_SDATE,'- ');
+  SetLocaleInfo(LOCALE_SLONGDATE,LOCALE_SSHORTDATE, PChar(sFormat));
+  SendMessage(HWND_BROADCAST,WM_SETTINGCHANGE,0,0);
+end;
+
+//-----------------------------------------------------------------------------
+// 描述: 对字符串进行 base16 编码
+// 参数:
+//   Value - 待编码的字符串
+// 返回:
+//   编码后的字符串
+//-----------------------------------------------------------------------------
+function Base16Encode(const Src: AnsiString): AnsiString;
+const
+  H: array[0..15] of AnsiChar = '0123456789ABCDEF';
+var
+  S: PByte;
+  D: PAnsiChar;
+  SrcBytes: Integer;
+begin
+  Result := '';
+  SrcBytes := Length(Src);
+  SetLength(Result, SrcBytes * 2);
+  if SrcBytes = 0 then Exit;
+  D := PAnsiChar(Result);
+  S := PByte(Src);
+  while SrcBytes > 0 do
+  begin
+    D^ := H[S^ shr  4]; Inc(D);
+    D^ := H[S^ and $F]; Inc(D);
+    Inc(S);
+    Dec(SrcBytes);
+  end;
+end;
+
+//-----------------------------------------------------------------------------
+// 描述: 将 base16 编码的内容还原成字符串
+// 参数:
+//   Value - 待解码的字符串
+// 返回:
+//   解码后的字符串
+//-----------------------------------------------------------------------------
+function Base16Decode(const Src: AnsiString): AnsiString;
+var
+  D: PByte;
+  V: Byte;
+  S: PAnsiChar;
+  SrcBytes: Integer;
+begin
+  Result := '';
+  SrcBytes := Length(Src);
+  SetLength(Result, (SrcBytes +1) div 2);
+  D := PByte(Result);
+  S := PAnsiChar(Src);
+  while SrcBytes > 0 do
+  begin
+    V := Byte(UpCase(S^));
+    Inc(S);
+    if V > Byte('9') then D^ := V - Byte('A') + 10
+      else D^ := V - Byte('0');
+    V := Byte(UpCase(S^));
+    Inc(S);
+    D^ := D^ shl 4;
+    if V > Byte('9') then D^ := D^ or (V - Byte('A') + 10)
+      else D^ := D^ or (V - Byte('0'));
+    Dec(SrcBytes, 2);
+    Inc(D);
+  end;
+  SetLength(Result, PAnsiChar(D) - PAnsiChar(Result));
+end;
+
+//------------------------------------------------------------------------------
+//一个通过ActiveX获取GUID的函数
+//返回值:GUID字符串
+//------------------------------------------------------------------------------
+Function GetGUID:string;
+var
+  sGUID  : string;
+  TmpGUID: TGUID;
+begin
+  if CoCreateGUID(TmpGUID) = S_OK then
+    sGUID := GUIDToString(TmpGUID)
+  else
+    sGUID := '0';
+  Result:=sGUID;
+end;
+
+//------------------------------------------------------------------------------
+//延时函数,MSecs单位为毫秒(千分之1秒)
+//输入值:毫秒,延时时间
+//------------------------------------------------------------------------------
+procedure Delay1(MSecs: Longint);
+var
+  First: Longint;
+begin
+  for First:=1 to 10 do
+  begin
+    Sleep(Trunc(Msecs/10));
+    //Application.ProcessMessages;
+  end;
+end;
+
+procedure Delay2(MSecs: Longint);
+var
+  FirstTickCount, Now: Longint;
+begin
+  FirstTickCount := GetTickCount();
+  repeat
+    Application.ProcessMessages;
+    Now := GetTickCount();
+  until (Now - FirstTickCount >= MSecs) or (Now < FirstTickCount);
+end;
+
+//------------------------------------------------------------------------------
+//获取软件版权信息
+//输入值:应用程序名
+//返回值:初始化全局变量glxxx , 包括产品名称,产品版本,文件描述,版权,文件版本,
+//        公司名称,注册商标,外部名称,原始名称等
+//------------------------------------------------------------------------------
+procedure GetVersionInfo(AppExeName:string);
+var
+   BufSize, Len:DWORD;
+   Buf, Value:PChar;
+begin
+   BufSize:=GetFileVersionInfoSize(PChar(AppExeName), BufSize);
+   if BufSize>0 then
+   begin
+   	Buf:=AllocMem(BufSize); 
+   	GetFileVersionInfo(PChar(Application.ExeName), 0, BufSize, Buf);
+   	if VerQueryValue(Buf,PChar('StringFileInfo\080403A8\'+glVerInfo[1]),Pointer(Value),Len) then
+   		glProductName:=Value;
+   	if VerQueryValue(Buf,PChar('StringFileInfo\080403A8\'+glVerInfo[2]),Pointer(Value),Len) then
+   		glProductVersion:=Value;
+   	if VerQueryValue(Buf,PChar('StringFileInfo\080403A8\'+glVerInfo[3]),Pointer(Value),Len) then
+   		glFileDescription:=Value;
+   	if VerQueryValue(Buf,PChar('StringFileInfo\080403A8\'+glVerInfo[4]),Pointer(Value),Len) then
+   		glLegalCopyright:=Value;
+   	if VerQueryValue(Buf,PChar('StringFileInfo\080403A8\'+glVerInfo[5]),Pointer(Value),Len) then
+   		glFileVersion:=Value;
+   	if VerQueryValue(Buf,PChar('StringFileInfo\080403A8\'+glVerInfo[6]),Pointer(Value),Len) then
+   		glCompanyName:=Value;
+   	if VerQueryValue(Buf,PChar('StringFileInfo\080403A8\'+glVerInfo[7]),Pointer(Value),Len) then
+   		glLegalTrademarks:=Value;
+   	if VerQueryValue(Buf,PChar('StringFileInfo\080403A8\'+glVerInfo[8]),Pointer(Value),Len) then
+   		glInternalName:=Value;
+   	if VerQueryValue(Buf,PChar('StringFileInfo\080403A8\'+glVerInfo[9]),Pointer(Value),Len) then
+   		glOriginalFilename:=Value;
+   	FreeMem(Buf,BufSize);
+   end;
+end;
+
+//------------------------------------------------------------------------------
+// 枚举系统COM口,加到COM列表
+// 输入值:端口列表
+// 返回值:nil
+//------------------------------------------------------------------------------
+procedure EnumComPorts(Ports: TStrings);
+var
+  KeyHandle: HKEY;
+  ErrCode, Index: Integer;
+  ValueName, Data: string;
+  ValueLen, DataLen, ValueType: DWORD;
+  TmpPorts: TStringList;
+begin
+  ErrCode := RegOpenKeyEx(HKEY_LOCAL_MACHINE, 'HARDWARE\DEVICEMAP\SERIALCOMM', 0,
+                          KEY_READ, KeyHandle);
+  if ErrCode <> ERROR_SUCCESS then
+    Exit;  // raise EComPort.Create(CError_RegError, ErrCode);
+  TmpPorts := TStringList.Create;
+  try
+    Index := 0;
+    repeat
+      ValueLen := 256;
+      DataLen := 256;
+      SetLength(ValueName, ValueLen);
+      SetLength(Data, DataLen);
+      ErrCode := RegEnumValue(KeyHandle, Index, PChar(ValueName), Cardinal(ValueLen),
+                              nil, @ValueType, PByte(PChar(Data)), @DataLen);
+      if ErrCode = ERROR_SUCCESS then
+      begin
+        SetLength(Data, DataLen);
+        TmpPorts.Add(Data);
+        Inc(Index);
+      end
+      else
+        if ErrCode <> ERROR_NO_MORE_ITEMS then
+          exit; //raise EComPort.Create(CError_RegError, ErrCode);
+    until (ErrCode <> ERROR_SUCCESS) ;
+    TmpPorts.Sort;
+    Ports.Assign(TmpPorts);
+  finally
+    RegCloseKey(KeyHandle);
+    TmpPorts.Free;
+  end;
+end;
+
+function CheckComPort(ComPortName: string; var ComPortList: Tstrings): boolean;
+var
+  reg: TRegistry; //uses 单元文件Registry
+  ts: TStrings;   //键名
+  i: Integer;
+  tl: TStringList; //串口名称
+  nIndex: Integer;
+begin
+  reg := TRegistry.Create;
+  ts := TStringList.Create;
+  try
+    reg.RootKey := HKEY_LOCAL_MACHINE;
+    reg.OpenKey('hardware\devicemap\serialcomm', False);
+    reg.GetValueNames(ts); //获取注册表中串口的 键名
+ 
+    tl := TStringList.Create;
+    for i := 0 to ts.Count - 1 do
+    begin
+      tl.Add(reg.ReadString(ts.Strings[i])); //根据键名,读取注册表中对应的串口名称(例如COM1)
+    end;
+    tl.Sort;
+    ComPortList := tl;
+    Result := tl.Find(ComPortName, nIndex);//查询是否存在
+    //ShowMessage(IntToStr((nIndex)));
+  finally
+   // tl.Free;
+    ts.Free;
+    reg.CloseKey;
+    reg.Free;
+  end;
+end;
+
+//------------------------------------------------------------------------------
+// 字符串转换成16进制字符串
+// 输入值:ASCII字符串
+// 返回值:ASCII转成16进制数,并用string显示
+//------------------------------------------------------------------------------
+function StrToHexStr(const S:string):string;
+var
+  I:Integer;
+begin
+  for I:=1 to Length(S) do
+  begin
+    if I=1 then
+      Result:=IntToHex(Ord(S[1]),2)
+    else
+      Result:=Result+' '+IntToHex(Ord(S[I]),2);
+  end;
+end;
+
+//字符串转换成十六进制字符串,中间无空格!!!
+function StrToHexStr1(const S:string):string;
+var
+  I:Integer;
+  ss:String;
+begin
+  for I:=1 to Length(S) do
+    ss:=ss+IntToHex(Integer(S[I]),2);
+  Result:=ss;
+end;
+
+//------------------------------------------------------------------------------
+// 16进制字符串转换成字符串
+// 输入值:待转换的16进制字符串
+// 返回值:ASCII字符串
+//------------------------------------------------------------------------------
+function HexStrToStr(const S:string; bFlag:boolean=false):string;
+var
+  t:Integer;
+  ts, SS:string;
+  M,Code:Integer;
+begin
+  t:=1;
+  Result:='';
+  //处理字符串 '00'-->'20' (即将null转为空格,防止行解析终止)
+  if bFlag then
+    SS := StringReplace(S, '00', '20', [rfReplaceAll, rfIgnoreCase])
+  else
+    SS := S ;
+  while t<=Length(SS) do
+  begin
+    while (t<=Length(SS)) and (not (SS[t] in ['0'..'9','A'..'F','a'..'f'])) do
+      inc(t);
+    if (t+1>Length(SS))or(not (SS[t+1] in ['0'..'9','A'..'F','a'..'f'])) then
+      ts:='$'+SS[t]
+    else
+      ts:='$'+SS[t]+SS[t+1];
+    Val(ts,M,Code);
+    if Code=0 then
+      Result:=Result+Chr(M);
+    inc(t,2);
+  end;
+end;
+
+//------------------------------------------------------------------------------
+// 以十六进制方式查看内存的函数
+// 输入值:任意类型值、值的长度
+// 返回值:16进制ASCII,并用string显示
+//------------------------------------------------------------------------------
+function GetMemBytes(var X; size: Integer): string;
+var
+  pb: PByte;
+  i: Integer;
+begin
+  pb := PByte(X);
+  for i := 0 to size - 1 do
+  begin
+    Result := Result + IntToHex(pb^, 2) + #32;
+    Inc(pb);
+  end;
+end;
+
+//------------------------------------------------------------------------------
+// 遍历目录和子目录下的文件名(可按后缀名遍历)
+// 输入值:FilePath-路径如'C:\DIR',ExtMask-文件后缀如'*.*',FileList-字符串列表
+//         SubDir-是否遍历子目录
+// 返回值:无,直接访问fileList字符串列表
+// 包含文件:Contnrs (TQueue类使用)
+// eg:GetFileListEx(dir, '*.tst', clbSodimFile.Items, False);
+//------------------------------------------------------------------------------
+procedure GetFileListEx(FilePath, ExtMask: string; FileList: TStrings; SubDir: Boolean = True);
+  function Match(FileName: string; MaskList: TStrings): Boolean;
+  var
+    i: integer;
+  begin
+    Result := False;
+    for i := 0 to MaskList.Count - 1 do
+    begin
+      if MatchesMask(FileName, MaskList[i]) then
+      begin
+        Result := True;
+        break;
+      end;
+    end;
+  end;
+
+var
+  FileRec: TSearchRec;
+  MaskList: TStringList;
+begin
+  if DirectoryExists(FilePath) then
+  begin
+    if FilePath[Length(FilePath)] <> '\' then
+      FilePath := FilePath + '\';
+    if FindFirst(FilePath + '*.*', faAnyFile, FileRec) = 0 then
+    begin
+      MaskList := TStringList.Create;
+      try
+        ExtractStrings([';'], [], PChar(ExtMask), MaskList);
+        FileList.BeginUpdate;
+        repeat
+          if ((FileRec.Attr and faDirectory) <> 0) and SubDir then
+          begin
+            if (FileRec.Name <> '.') and (FileRec.Name <> '..') then
+              GetFileListEx(FilePath + FileRec.Name + '\', ExtMask, FileList);
+          end
+          else
+          begin
+            if Match(FilePath + FileRec.Name, MaskList) then
+             //这里如果只返回文件名,则注释掉路径即可
+             // FileList.Add( { FilePath + } FileRec.Name);
+             FileList.Add( FilePath + FileRec.Name);
+          end;
+        until FindNext(FileRec) <> 0;
+        FileList.EndUpdate;
+      finally
+        MaskList.Free;
+      end;
+    end;
+    FindClose(FileRec);
+  end;
+end;
+
+//返回不带路径的文件集合
+procedure GetFileList(FilePath, ExtMask: string; FileList: TStrings; SubDir: Boolean = True);
+  function Match(FileName: string; MaskList: TStrings): Boolean;
+  var
+    i: integer;
+  begin
+    Result := False;
+    for i := 0 to MaskList.Count - 1 do
+    begin
+      if MatchesMask(FileName, MaskList[i]) then
+      begin
+        Result := True;
+        break;
+      end;
+    end;
+  end;
+
+var
+  FileRec: TSearchRec;
+  MaskList: TStringList;
+begin
+  if DirectoryExists(FilePath) then
+  begin
+    if FilePath[Length(FilePath)] <> '\' then
+      FilePath := FilePath + '\';
+    if FindFirst(FilePath + '*.*', faAnyFile, FileRec) = 0 then
+    begin
+      MaskList := TStringList.Create;
+      try
+        ExtractStrings([';'], [], PChar(ExtMask), MaskList);
+        FileList.BeginUpdate;
+        repeat
+          if ((FileRec.Attr and faDirectory) <> 0) and SubDir then
+          begin
+            if (FileRec.Name <> '.') and (FileRec.Name <> '..') then
+              GetFileListEx(FilePath + FileRec.Name + '\', ExtMask, FileList);
+          end
+          else
+          begin
+            if Match(FilePath + FileRec.Name, MaskList) then
+             //这里如果只返回文件名,则注释掉路径即可
+              FileList.Add( { FilePath + } FileRec.Name);
+             //FileList.Add( FilePath + FileRec.Name);
+          end;
+        until FindNext(FileRec) <> 0;
+        FileList.EndUpdate;
+      finally
+        MaskList.Free;
+      end;
+    end;
+    FindClose(FileRec);
+  end;
+end;
+
+//------------------------------------------------------------------------------
+// 删除整个目录下的文件,包括目录
+// 输入值:Path-路径如'C:\DIR',IsDelDir-是否删除目录
+// 返回值:True-操作成功
+// eg:DeleteDirectory(dir, True);
+//------------------------------------------------------------------------------
+function DeleteDir(Path: string;IsDelDir: Boolean = False): Boolean;
+var
+  search: TSearchRec;
+  ret: integer;
+  key: string;
+begin
+  if Path[Length(Path)] <> '\' then
+    Path := Path + '\';
+  key := Path + '*.*';
+  ret := findFirst(key, faanyfile, search);
+  while ret = 0 do
+  begin
+    if ((search.Attr and fadirectory) = fadirectory) then
+    begin
+      if (search.Name <> '.') and (search.name <> '..') then
+        DeleteDirectory(Path + search.name);
+    end
+    else
+    begin
+      if ((search.Attr and fadirectory) <> fadirectory) then
+      begin
+        deletefile(Path + search.name);
+      end;
+    end;
+    ret := FindNext(search);
+  end;
+  findClose(search);
+  if IsDelDir then  //如果需要删除文件夹则添加
+    removedir(Path);
+  result := True;
+end;
+
+//------------------------------------------------------------------------------
+// 操作Excel的相关函数
+// 获取Excel版本,返回值:版本号11-2003,12-2007
+{const
+  Wordversion97 = 8;
+  Wordversion2000 = 9;
+  WordversionXP = 10;
+  Wordversion2003 = 11;
+  Wordversion2007 = 12;}
+//------------------------------------------------------------------------------
+function GetInstalledWordVersion: Integer;
+var
+  Excel: OLEVariant;
+begin  
+  try  
+    Excel:=CreateOLEObject('Excel.Application');  
+  except
+    on E: Exception do
+      showmessage('获取Excle版本时发生错误!' + #13#10
+                + '异常类名称:' + E.ClassName + #13#10
+                + '异常信息:' + E.Message);
+  end;
+  result := Excel.version;
+  Excel.Quit;
+  FreeAndNil(Excel);
+end;
+
+//------------------------------------------------------------------------------
+// 生成随机数
+//------------------------------------------------------------------------------
+function RandomNum:String;
+begin   //生成随机数
+  Result := FormatDateTime('yyyymmddhhnnss',Now) + IntToStr(Random(10))+IntToStr(Random(10))+IntToStr(Random(10))+IntToStr(Random(10));
+end;
+
+//------------------------------------------------------------------------------
+// TStringlist自定义排序参数
+// 应用范例:
+{ sl := TStringList.Create;
+  try
+    sl.DelimitedText:='12,9.123,0.5,30'; //初始化排序sl
+    sl.Sorted:=false;                    //自定义排序
+    sl.CustomSort(SortParam);            //按自定义排序参数重新排序
+    showmessage(sl.Text);                //打印排序后的结果
+    showmessage(sl.Strings[0]);          //打印最小值
+    showmessage(sl.Strings[sl.Count-1]); //打印最大值
+  finally
+    FreeAndNil(sl);
+  end;
+}
+//------------------------------------------------------------------------------
+function SortParam(List: TStringList; Index1, Index2: Integer): Integer;
+begin
+  if StrToFloat(List[index1])<StrToFloat(List[Index2]) then
+    result:=-1
+  else if StrToFloat(List[index1])=StrToFloat(List[Index2]) then
+    Result:=0
+  else
+    Result:=1;
+end;
+
+//------------------------------------------------------------------------------
+//传统的"四舍五入"方法
+//------------------------------------------------------------------------------
+function RoundEx(const Value: Extended; const Digit: Byte = 0): Extended;
+var
+  tmp: Extended;
+begin
+  tmp := Power(10, Digit);
+  if Value > 0 then
+    Result := Value * tmp + 0.5
+  else
+    Result := Value * tmp - 0.5;
+  Result := Trunc(Result) / tmp;
+end;
+
+{//Math
+//RoundMode参数:向下舍入-rmTruncate;向上舍入-rmUp
+function RoundEx(const Value: Extended; const Digit: int = 0; RoundMode: TFPURoundingMode = rmUp): Extended;
+var
+  RM: TFPURoundingMode;
+begin
+  RM := GetRoundMode;
+  try
+    SetRoundMode(RoundMode);
+    Result := Round(Value);
+  finally
+    SetRoundMode(RM);
+  end;
+end;     }
+
+//------------------------------------------------------------------------------
+//中文转成 array of byte 应该就是你想要的结果
+//用字节发送到网络上和接收的
+//带中文的String  转byte
+//------------------------------------------------------------------------------
+function UniCode2GB(S: string): string;
+var I: Integer;
+begin
+  I := Length(S);
+  while I >= 4 do begin
+    try
+      Result := WideChar(StrToInt('$' + S[I - 3] + S[I - 2] + S[I - 1] + S[I])) + Result;
+    except
+    end;
+    I := I - 4;
+  end;
+end;
+function GB2UniCode(GB: string): string;
+var
+  s: string;
+  i, j, k: integer;
+  a: array[1..160] of char;
+begin
+  s := '';
+  StringToWideChar(GB, @(a[1]), 500);
+  i := 1;
+  while ((a[i] <> #0) or (a[i + 1] <> #0)) do begin
+    j := Integer(a[i]);
+    k := Integer(a[i + 1]);
+    s := s + Copy(Format('%X ', [k * $100 + j + $10000]), 2, 4);
+    //S := S + Char(k)+Char(j);
+    i := i + 2;
+  end;
+  Result := s;
+end;
+
+//------------------------------------------------------------------------------
+//重写SysUtils单元的BoolToStr-->BoolToHexStr
+//入参:bool值
+//返回:字符串,False-0,True-1
+//------------------------------------------------------------------------------
+function BoolToHexStr(B: Boolean; UseBoolStrs: Boolean = False): string;
+const
+  cSimpleBoolStrs: array [boolean] of String = ('00', '01');
+begin
+  if UseBoolStrs then
+  begin
+    if Length(TrueBoolStrs) = 0 then
+    begin
+      SetLength(TrueBoolStrs, 1);
+      TrueBoolStrs[0] := DefaultTrueBoolStr;
+    end;
+    if Length(FalseBoolStrs) = 0 then
+    begin
+      SetLength(FalseBoolStrs, 1);
+      FalseBoolStrs[0] := DefaultFalseBoolStr;
+    end;
+    if B then
+      Result := TrueBoolStrs[0]
+    else
+      Result := FalseBoolStrs[0];
+  end
+  else
+    Result := cSimpleBoolStrs[B];
+end;
+
+//------------------------------------------------------------------------------
+// 将Bool值转成字符串
+// 入参:bool
+// 返回:False,True字符串
+//------------------------------------------------------------------------------
+function BoolToString(B: Boolean; UseBoolStrs: Boolean = False): string;
+const
+  cSimpleBoolStrs: array [boolean] of String = ('False', 'True');
+begin
+  if UseBoolStrs then
+  begin
+    if Length(TrueBoolStrs) = 0 then
+    begin
+      SetLength(TrueBoolStrs, 1);
+      TrueBoolStrs[0] := DefaultTrueBoolStr;
+    end;
+    if Length(FalseBoolStrs) = 0 then
+    begin
+      SetLength(FalseBoolStrs, 1);
+      FalseBoolStrs[0] := DefaultFalseBoolStr;
+    end;
+    if B then
+      Result := TrueBoolStrs[0]
+    else
+      Result := FalseBoolStrs[0];
+  end
+  else
+    Result := cSimpleBoolStrs[B];
+end;
+
+//------------------------------------------------------------------------------
+//将日期格式转换成Unix时间戳 , 长度8字节
+//入参:Delphi日期时间
+//返回:长整形数值,从1970-01-01 00:00:00 到ADate的秒数
+//------------------------------------------------------------------------------
+function DateTimeToUnixDate(const ADate: TDateTime): Longint;
+const
+  cUnixStartDate: TDateTime = 25569.0; // 1970/01/01
+begin
+  Result := Round((ADate - cUnixStartDate) * 86400) - 8*3600;//东八区修正8小时
+end;
+
+//------------------------------------------------------------------------------
+// 将整数10241转成 '10.1KB' 字符串
+// 入参:整数
+// 返回:字符串
+//------------------------------------------------------------------------------
+function FormatFileSize(size:Int64):String;
+var
+  size1 : String;
+begin
+  //不足1KB的数据,按1K显示
+  if size<1024 then  size:=1
+  else size := floor(size/1024);
+
+  //从KB开始,添加单位后返回字符串
+  if size<1024 then
+    size1 := IntToStr(size) + ' KB'
+  else if (size>=1024)and(size<1048576) then
+    size1 := FormatFloat('#.#',size/1024) + ' MB'
+  else if (size>=1048576)and(size<1073741824) then
+    size1 := FormatFloat('#.##',size/1048576) + ' GB'
+  else
+    size1 := FormatFloat('#.##',size/1073741824) + ' TB';
+  Result := size1;
+end;
+
+//------------------------------------------------------------------------------
+// 将整数10241转成 '1.02万',120000000转成 '1.2亿' 字符串
+// 入参:整数
+// 返回:字符串
+//------------------------------------------------------------------------------
+function FormatNumberSize(num:Int64):String;
+var
+  new : String;
+begin
+  if num<10000 then
+    new := IntToStr(num)+' '
+  else if (num>=10000)and(num<100000000) then
+    new := FormatFloat('#.##',num/10000) + ' 万'
+  else
+    new := FormatFloat('#.##',num/100000000) + ' 亿';
+  Result := new;
+end;
+
+//------------------------------------------------------------------------------
+// 从字符串str中按分隔符chr截取第i个字符串,返回截取到的字符串
+//------------------------------------------------------------------------------
+function SplitStr(str:string;chr:char;i:Integer):string;
+var
+  sltemp : TStringlist;
+begin
+  sltemp := TStringlist.Create();
+  try
+    SplitString(str,chr,sltemp);
+    Result := sltemp.Strings[i];
+  finally
+    FreeAndNil(sltemp);
+  end;
+end;
+
+//返回分割后的记录条数
+function SplitStrCount(str:string; chr:char):Integer;
+var
+  sltemp : TStringlist;
+begin
+  sltemp := TStringlist.Create();
+  try
+    SplitString(str,chr,sltemp);
+    Result := sltemp.Count;
+  finally
+    FreeAndNil(sltemp);
+  end;
+end;
+
+//------------------------------------------------------------------------------
+// Windows下杀进程,根据标题查杀
+//------------------------------------------------------------------------------
+procedure KillProgram(WindowTitle: string);
+const  
+  PROCESS_TERMINATE = $0001;  
+var  
+  ProcessHandle : THandle;  
+  ProcessID: Integer;  
+  TheWindow : HWND;  
+begin  
+  TheWindow := FindWindow(nil, PChar(WindowTitle));  
+  GetWindowThreadProcessID(TheWindow, @ProcessID);
+  ProcessHandle := OpenProcess(PROCESS_TERMINATE, FALSE, ProcessId);  
+  TerminateProcess(ProcessHandle,4);  
+end;
+
+//------------------------------------------------------------------------------
+// Windows下杀进程,根据exe名称查杀
+//------------------------------------------------------------------------------
+function KillTask(ExeFileName: string): integer;
+const  
+  PROCESS_TERMINATE=$0001;  
+var  
+  ContinueLoop: BOOL;  
+  FSnapshotHandle: THandle;  
+  FProcessEntry32: TProcessEntry32;  
+begin  
+  result := 0;  
+  
+  FSnapshotHandle := CreateToolhelp32Snapshot  
+                     (TH32CS_SNAPPROCESS, 0);  
+  FProcessEntry32.dwSize := Sizeof(FProcessEntry32);  
+  ContinueLoop := Process32First(FSnapshotHandle,  
+                                 FProcessEntry32);  
+  
+  while integer(ContinueLoop) <> 0 do  
+  begin  
+    if ((UpperCase(ExtractFileName(FProcessEntry32.szExeFile)) =  
+         UpperCase(ExeFileName))  
+     or (UpperCase(FProcessEntry32.szExeFile) =  
+         UpperCase(ExeFileName))) then  
+      Result := Integer(TerminateProcess(OpenProcess(  
+                        PROCESS_TERMINATE, BOOL(0),  
+                        FProcessEntry32.th32ProcessID), 0));    
+    ContinueLoop := Process32Next(FSnapshotHandle,  
+                                  FProcessEntry32);  
+  end;  
+  
+  CloseHandle(FSnapshotHandle);  
+end;
+
+//------------------------------------------------------------------------------
+//刷新任务栏因进程关闭而残留的图标
+//------------------------------------------------------------------------------
+procedure RefreshTaskbarIcon;
+var  
+  hShellTrayWnd: HWND;   //任务栏窗口  
+  hTrayNotifyWnd: HWND;  //任务栏右边托盘图标+时间区  
+  hSysPager: HWND;     //不同系统可能有可能没有这层
+  hToolbarWindow32: HWND;  //托盘图标窗口    
+  r: TRECT;  
+  width, height: integer;  
+  x: Integer;  
+begin  
+  hShellTrayWnd  := FindWindow('Shell_TrayWnd',nil);  
+  hTrayNotifyWnd := FindWindowEx(hShellTrayWnd,0,'TrayNotifyWnd',nil);  
+  hSysPager := FindWindowEx(hTrayNotifyWnd,0,'SysPager',nil);   
+  if (hSysPager <> 0) then
+        hToolbarWindow32 := FindWindowEx(hSysPager,0,'ToolbarWindow32',nil)
+  else  
+    hToolbarWindow32 := FindWindowEx(hTrayNotifyWnd,0,'ToolbarWindow32',nil);  
+  
+  if (hToolbarWindow32 <> 0) then  
+  begin  
+    GetWindowRect(hToolbarWindow32,r);  
+    width := r.right - r.left;  
+    height := r.bottom - r.top;  
+    //从任务栏中间从左到右 MOUSEMOVE一遍,所有图标状态会被更新    
+    for x := 1 to width-1 do  
+      SendMessage(hToolbarWindow32,WM_MOUSEMOVE,0,MAKELPARAM(x,trunc(height/2)));  
+  end;  
+end;
+//另一种刷新任务栏图标的方法
+procedure RefreshTaskbarIcon2;
+var
+ TrayWindow : HWnd;  
+ WindowRect : TRect;  
+ SmallIconWidth : Integer;  
+ SmallIconHeight : Integer;  
+ CursorPos : TPoint;  
+ Row : Integer;  
+ Col : Integer;  
+begin  
+ { 获得任务栏句柄和边框}  
+ TrayWindow := FindWindowEx(FindWindow('Shell_TrayWnd',NIL),0,'TrayNotifyWnd',NIL);  
+ if not GetWindowRect(TrayWindow,WindowRect) then  
+   Exit;  
+ { 获得小图标大小}  
+ SmallIconWidth := GetSystemMetrics(SM_CXSMICON);  
+ SmallIconHeight := GetSystemMetrics(SM_CYSMICON);  
+ { 保存当前鼠标位置}  
+ GetCursorPos(CursorPos);  
+ { 使鼠标快速划过每个图标 }  
+ with WindowRect do  
+ begin  
+   for Row := 0 to (Bottom - Top) DIV SmallIconHeight do  
+   begin  
+     for Col := 0 to (Right - Left) DIV SmallIconWidth do  
+     begin  
+       SetCursorPos(Left + Col * SmallIconWidth, Top + Row * SmallIconHeight);  
+       Sleep(10);  //发现这个地方参数为 0 的时候,有时候是不够的  
+     end;  
+   end;  
+ end;  
+ {恢复鼠标位置}  
+ SetCursorPos(CursorPos.X,CursorPos.Y);  
+ { 重画任务栏 }  
+ RedrawWindow(TrayWindow,NIL,0,RDW_INVALIDATE OR RDW_ERASE OR RDW_UPDATENOW);  
+end;
+
+//------------------------------------------------------------------------------
+//强行关闭操作系统的函数
+//------------------------------------------------------------------------------
+{procedure RebootSystem();
+begin  
+  if GetOperatingSystem() = 'Windows NT/2000/XP' then  
+  begin  
+    Get_Shutdown_Privilege();  
+    //调用此函数会出现系统关机提示窗口,并允许用户取消关机动作,去掉就不显示提示窗口
+    //InitiateSystemShutDown(nil, '关机提示', 3, True, False);
+    //ExitWindowsEx(EWX_SHUTDOWN+EWX_FORCE+EWX_POWEROFF+EWX_FORCEIFHUNG,0);
+    ExitWindowsEx(EWX_REBOOT+EWX_FORCE+EWX_POWEROFF+EWX_FORCEIFHUNG, $FFFF);
+  end  
+  else
+  begin  
+    ExitWindowsEx(EWX_REBOOT+EWX_FORCE+EWX_POWEROFF+EWX_FORCEIFHUNG, $FFFF);
+  end;
+end; }
+//获取操作系统信息
+function GetOperatingSystem(): string;
+var  
+  osVerInfo: TOSVersionInfo;
+begin  
+  Result:= '';
+  osVerInfo.dwOSVersionInfoSize:= SizeOf(TOSVersionInfo);  
+  
+  if GetVersionEx(osVerInfo) then  
+    case osVerInfo.dwPlatformId of  
+    VER_PLATFORM_WIN32_NT:  
+      begin  
+        Result:= 'Windows NT/2000/XP'  
+      end;  
+    VER_PLATFORM_WIN32_WINDOWS:  
+      begin  
+        Result := 'Windows 95/98/98SE/Me';  
+      end;  
+  end;  
+end;  
+//获得用户关机特权,仅对Windows NT/2000/XP
+{procedure Get_Shutdown_Privilege();
+var
+  rl: Cardinal;    
+  hToken: Cardinal;    
+  tkp: TOKEN_PRIVILEGES;     
+begin  
+  OpenProcessToken(GetCurrentProcess, TOKEN_ADJUST_PRIVILEGES or TOKEN_QUERY, hToken);  
+  
+  if LookupPrivilegeValue(nil, 'SeShutdownPrivilege', tkp.Privileges[0].Luid) then  
+  begin    
+    tkp.Privileges[0].Attributes:= SE_PRIVILEGE_ENABLED;  
+    tkp.PrivilegeCount:= 1;  
+    AdjustTokenPrivileges(hToken, False, tkp, 0, nil, rl);    
+  end;    
+end;   }
+
+//----------------------------------------------------------------------------//
+// 根据程序名称获取 HWND的方法                                                //
+// 1.GetHWndByPID()获取PID;2.GetHwndByAppName()获取HWND                      //
+//----------------------------------------------------------------------------//
+//根据 ProcessId获取进程的窗口句柄如下:
+//1.通过EnumWindows枚举所有窗口
+//2.使用GetWindowThreadProcessID,通过窗口句柄获取进程ID
+//3.比较获取的进程ID与当前已知的进程ID,判断是否为需要的窗口
+//跟据ProcessId获取进程的窗口句柄
+function GetHWndByPID(const hPID: THandle): THandle;
+  type
+    PEnumInfo = ^TEnumInfo;
+    TEnumInfo = record
+    ProcessID: DWORD;
+    HWND: THandle;
+  end;
+
+  function EnumWindowsProc(Wnd: DWORD; var EI: TEnumInfo): Bool; stdcall;
+  var
+    PID: DWORD;  
+  begin
+    GetWindowThreadProcessID(Wnd, @PID);
+    Result := (PID <> EI.ProcessID) or  
+        (not IsWindowVisible(WND)) or  
+        (not IsWindowEnabled(WND));  
+  
+    if not Result then EI.HWND := WND;
+  end;
+  
+  function FindMainWindow(PID: DWORD): DWORD;
+  var
+    EI: TEnumInfo;
+  begin
+    EI.ProcessID := PID;  
+    EI.HWND := 0;  
+    EnumWindows(@EnumWindowsProc, Integer(@EI));  
+    Result := EI.HWND;  
+  end;
+begin  
+    if hPID<>0 then  
+    Result:=FindMainWindow(hPID)  
+    else  
+    Result:=0;  
+end;
+
+//-----------------------------------------------------------------------------
+//根据 AppName获取程序HWND
+//入参 = '应用程序名.exe'
+//返回 = 程序句柄
+//-----------------------------------------------------------------------------
+function GetHwndByAppName(const AppName: String): THandle;
+var
+  pName : string;         //进程名
+  hSnapshot : THandle;    //进程快照句柄
+  tPE : TProcessEntry32;  //进程入口的结构体信息
+  flag : BOOL;
+begin
+  Result := 0;
+  hSnapshot := CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0); //创建一个进程快照
+  tPE.dwSize:= Sizeof(tPE);
+  flag := Process32First(hSnapshot, tPE); //得到系统中第一个进程
+  //循环例举
+  while flag do begin
+    pName := tPE.szExeFile;
+    if(pName = AppName) then
+      Result := GetHWndByPID(tPE.th32ProcessID);
+    flag := Process32Next(hSnapshot, tPE);
+  end;
+  CloseHandle(hSnapshot); // 释放快照句柄
+end;
+
+
+//-----------------------------------------------------------------------------
+//封装的动态Dll函数调用方法
+//CallFunc('user32.dll', 'MessageBoxA', [0, 'hello world', 'title', MB_OK]);
+//CallFunc('user32.dll', 'MessageBeep', []);
+//CallFunc('kernel32.dll', 'Sleep', [1000]);
+//-----------------------------------------------------------------------------
+function CallFunc(dllname, funcname: string; const param: array of const): DWORD;
+var
+   hLib: THandle;
+   pFunc: Pointer;
+   intSize: Integer;
+begin
+   Result := 0;
+
+   hLib := LoadLibrary(PChar(dllname));
+   if hLib <> 0 then
+   begin
+     pFunc := GetProcAddress(hLib, PChar(funcname));
+     if pFunc <> nil then
+     begin
+       // 获取参数大小
+       intSize := Length(param);
+
+       // 自动完成函数调用, asm实现
+       asm
+         push ecx
+         push esi
+
+         mov ecx, intSize;    // 参数的个数
+         mov esi, param
+
+         test ecx, ecx        // 判断是否有参数
+         je @call             // 如果没有参数则跳转到函数调用处
+
+       @again:
+         dec ecx             
+         push dword ptr [esi + ecx * 8]   // 循环把参数压入堆栈
+         cmp ecx, 0          
+         jnz @again           // 一直循环到 ecx 为0
+
+       @call:
+         call pFunc           // 调用函数
+         mov @Result, eax     // 返回值
+
+         pop esi
+         pop ecx
+       end;
+     end;
+
+     FreeLibrary(hLib);
+   end;
+end;
+
+//------------------------------------------------------------------------------
+// 调用windows系统 ping 测试网络是否通畅
+// 包含文件 Winsock
+// 入参:IP地址
+// 返回:false or true
+//------------------------------------------------------------------------------
+function PingHost(HostIP: String): Boolean;
+type
+  PIPOptionInformation =  ^TIPOptionInformation;
+  TIPOptionInformation = packed record
+    TTL:Byte;
+    TOS:Byte;
+    Flags:Byte;
+    OptionsSize:Byte;
+    OptionsData:PChar;
+  end;
+
+  PIcmpEchoReply= ^TIcmpEchoReply;
+  TIcmpEchoReply = packed record
+    Address: DWORD;
+    Status:DWORD;
+    RTT:DWORD;
+    DataSize:Word;
+    Reserved:Word;
+    Data:Pointer;
+    Options:TIPOptionInformation;
+  end;
+  TIcmpCreateFile = function:THandle;stdcall;
+  TIcmpCloseHandle= function(IcmpHandle:THandle):Boolean;stdcall;
+  TIcmpSendEcho=function(IcmpHandle:THandle;
+                  DestinationAddress: DWORD;
+                  RequestData:   Pointer;
+                  RequestSize:   Word;
+                  RequestOptions:   PIPOptionInformation;
+                  ReplyBuffer:   Pointer;
+                  ReplySize:   DWord;
+                  Timeout:   DWord
+                  ):DWord;stdcall;
+var
+  hICMP:THandle;
+  hICMPdll:THandle;
+  IcmpCreateFile:TIcmpCreateFile;
+  IcmpCloseHandle:TIcmpCloseHandle;
+  IcmpSendEcho:TIcmpSendEcho;
+  pIPE:PIcmpEchoReply;//   ICMP   Echo   reply   buffer
+  FIPAddress:DWORD;
+  FSize:DWORD;
+  FTimeOut:DWORD;
+  BufferSize:DWORD;
+  pReqData,pRevData:PChar;
+  MyString:string;
+begin   
+  Result:=False;
+  hICMPdll:=LoadLibrary('icmp.dll');
+  if hICMPdll=0 then   exit;
+
+  @ICMPCreateFile:=GetProcAddress(hICMPdll,'IcmpCreateFile');
+  @IcmpCloseHandle:=GetProcAddress(hICMPdll,'IcmpCloseHandle');
+  @IcmpSendEcho:=GetProcAddress(hICMPdll, 'IcmpSendEcho');
+  hICMP   :=   IcmpCreateFile;
+  if (hICMP=INVALID_HANDLE_VALUE) then  exit;
+  FIPAddress:=inet_addr(PChar(HostIP));
+  MyString := 'Hello,World';                                 //send   data   buffer
+  pReqData:=PChar(MyString);
+
+  FSize:=40;                                                 //receive   data   buffer
+  BufferSize:=SizeOf(TICMPEchoReply)+FSize;
+  GetMem(pIPE,BufferSize);   
+  FillChar(pIPE^,SizeOf(pIPE^), 0);
+  GetMem(pRevData,FSize);
+  pIPE^.Data:=pRevData;
+  FTimeOut:=500;
+  try
+    Result:=IcmpSendEcho(hICMP,
+                         FIPAddress,
+                         pReqData,
+                         Length(MyString),
+                         nil,
+                         pIPE,
+                         BufferSize,
+                         FTimeOut)>0;
+  finally
+    IcmpCloseHandle(hICMP);
+    FreeLibrary(hICMPdll);
+    FreeMem(pRevData);
+    FreeMem(pIPE);
+  end;
+end;
+
+//------------------------------------------------------------------------------
+// 描述:秒转时间字符串
+// 入参:Integer-秒
+// 返回:String-HH:MM:SS格式字符串
+//------------------------------------------------------------------------------
+function SecondToTime(sec:Integer):String;
+begin
+  Result := TimeToStr(sec/86400);
+end;
+
+// 描述:秒转换成TDateTIme格式
+function SecondToTime1(second: Word): TDateTime;
+var
+  Hour, Min, Sec: Word;
+begin
+  Hour := second div 3600;
+  Min := (second div 60) mod 60;
+  Sec := second mod 60;
+  Result := EncodeTime(Hour, Min, Sec, 0);
+end;
+
+//------------------------------------------------------------------------------
+// 扩充DateUtils库,增加北京时间转Int64时间格式,注意减去时区
+// 说明:
+{uses DateUtils;
+ DateTimeToUnix(Now)可以转换到unix时间,但是注意的是,它得到的时间
+ 比c语言中time()得到的时间大了8*60*60
+ 因为Now是当前时区的时间,c语言中time()是按格林威治时间计算的,
+ 北京时间比格林威治时间多了8小时
+ DateTimeToUnix(Now)-8*60*60 就和c语言中time()得到的一样了}
+//------------------------------------------------------------------------------
+// 使用示例:DateTimeToUnixPro(VarToDateTime(edit1.Text))
+function DateTimeToUnixPro(const AValue: TDateTime): Int64;
+begin
+  Result := DateTimeToUnix(AValue)- 8*60*60 ;
+end;
+
+function UnixToDateTimePro(const AValue: Int64): TDateTime;
+begin
+  Result := UnixToDateTime(floor(AValue/1000) + 8*60*60);
+end;
+
+//------------------------------------------------------------------------------
+// 科学计数法与浮点型数字互转,采用字符串输入输出
+// uses SysUtils
+//
+// eg: '-1.4857E-02' --> '-0.014857'
+//------------------------------------------------------------------------------
+//科学计数转浮点型,'-1.4857E-02' --> '-0.014857'
+function ExpToFloat(s:String):String;
+var
+  f : Extended;
+begin
+  f := StrToFloatDef(s,0);
+  Result := FloatToStr(f);
+end;
+//浮点型转科学计数,'-0.014857' --> '-1.4857E-02'
+function FloatToExp(s:String):String;
+var
+  f : Extended;
+begin
+  f := StrToFloatDef(s,0);
+  Result := FloatToStrF(f, ffExponent,7,2);
+end;
+
+//------------------------------------------------------------------------------
+// 将Bool值转成开关字符
+// 入参:bool
+// 返回:开启,关闭字符串
+//------------------------------------------------------------------------------
+function BoolToString1(B: Boolean; UseBoolStrs: Boolean = False): string;
+const
+  cSimpleBoolStrs: array [boolean] of String = ('关闭', '开启');
+begin
+  if UseBoolStrs then
+  begin
+    if Length(TrueBoolStrs) = 0 then
+    begin
+      SetLength(TrueBoolStrs, 1);
+      TrueBoolStrs[0] := '开启';
+    end;
+    if Length(FalseBoolStrs) = 0 then
+    begin
+      SetLength(FalseBoolStrs, 1);
+      FalseBoolStrs[0] := '关闭';
+    end;
+    if B then
+      Result := TrueBoolStrs[0]
+    else
+      Result := FalseBoolStrs[0];
+  end
+  else
+    Result := cSimpleBoolStrs[B];
+end;
+
+//------------------------------------------------------------------------------
+// 将Bool值转成开关字符
+// 入参:bool
+// 返回:开,关字符串
+//------------------------------------------------------------------------------
+function BoolToString3(B: Boolean; UseBoolStrs: Boolean = False): string;
+const
+  cSimpleBoolStrs: array [boolean] of String = ('关', '开');
+begin
+  if UseBoolStrs then
+  begin
+    if Length(TrueBoolStrs) = 0 then
+    begin
+      SetLength(TrueBoolStrs, 1);
+      TrueBoolStrs[0] := '开';
+    end;
+    if Length(FalseBoolStrs) = 0 then
+    begin
+      SetLength(FalseBoolStrs, 1);
+      FalseBoolStrs[0] := '关';
+    end;
+    if B then
+      Result := TrueBoolStrs[0]
+    else
+      Result := FalseBoolStrs[0];
+  end
+  else
+    Result := cSimpleBoolStrs[B];
+end;
+
+//------------------------------------------------------------------------------
+// 将Bool值转成开关字符
+// 入参:bool
+// 返回:0,1字符串
+//------------------------------------------------------------------------------
+function BoolToString2(B: Boolean; UseBoolStrs: Boolean = False): string;
+const
+  cSimpleBoolStrs: array [boolean] of String = ('0', '1');
+begin
+  if UseBoolStrs then
+  begin
+    if Length(TrueBoolStrs) = 0 then
+    begin
+      SetLength(TrueBoolStrs, 1);
+      TrueBoolStrs[0] := '1';
+    end;
+    if Length(FalseBoolStrs) = 0 then
+    begin
+      SetLength(FalseBoolStrs, 1);
+      FalseBoolStrs[0] := '0';
+    end;
+    if B then
+      Result := TrueBoolStrs[0]
+    else
+      Result := FalseBoolStrs[0];
+  end
+  else
+    Result := cSimpleBoolStrs[B];
+end;
+
+function BoolToString4(B: Boolean; UseBoolStrs: Boolean = False): string;
+const
+  cSimpleBoolStrs: array [boolean] of String = ('false', 'true');
+begin
+  if UseBoolStrs then
+  begin
+    if Length(TrueBoolStrs) = 0 then
+    begin
+      SetLength(TrueBoolStrs, 1);
+      TrueBoolStrs[0] := DefaultTrueBoolStr;
+    end;
+    if Length(FalseBoolStrs) = 0 then
+    begin
+      SetLength(FalseBoolStrs, 1);
+      FalseBoolStrs[0] := DefaultFalseBoolStr;
+    end;
+    if B then
+      Result := TrueBoolStrs[0]
+    else
+      Result := FalseBoolStrs[0];
+  end
+  else
+    Result := cSimpleBoolStrs[B];
+end;
+
+//------------------------------------------------------------------------
+// 整形转为布尔值
+// 输入:integer
+// 输出:True/False
+// 说明:如果AValue不等于0,则Result为True,否则为False。
+//------------------------------------------------------------------------
+function IntToBool(AValue: Integer): Boolean;
+begin
+  Result := AValue <> 0; // 如果AValue不等于0,则Result为True,否则为False。
+end;
+
+//------------------------------------------------------------------------
+// 线性插值算法
+// 输入:(x0、y0)(x1、y1),及需要插值的目标点x的值
+// 输出:x对应的插值y值
+// 说明:该函数的实现原理是根据线性插值的公式,计算目标点x对应的y值。
+//       函数首先计算出目标点x在数据点x0和x1之间的位置占比,即(x - x0) / (x1 - x0),
+//       然后将该比例乘以y1 - y0,并加上y0,即可得到目标点x对应的插值y值。
+//------------------------------------------------------------------------
+function LinearInterpolation(x0, y0, x1, y1, x: Double): Double;
+begin
+  Result := y0 + (y1 - y0) * (x - x0) / (x1 - x0);
+end;
+
+//------------------------------------------------------------------------------
+// 拉格朗日插值算法
+// 入参:x:表示给定的一组 x 坐标,是一个实数数组。
+//       y:表示给定的一组 y 坐标,也是一个实数数组,与 x 数组一一对应。
+//       n:表示 x 和 y 数组中的数据点个数。
+//      xi:表示要求解的 x 坐标,即要求在 x 轴上找到与之对应的 y 坐标。
+// 返回值:返回 xi 对应的 y 坐标。
+// 函数实现:定了两个循环变量 i 和 j,用于遍历 x 和 y 数组。然后在外层循环中,
+//           遍历每个数据点 i,计算对应的 Lagrange 插值多项式 L,将每个数据点
+//           Lagrange 多项式 L 与对应的 y 坐标相乘,并求和得到 p。
+//           最后返回 p,即为所求的 xi 对应的 y 坐标。
+//------------------------------------------------------------------------------
+function LagrangeInterpolation(x, y: array of Double; n: Integer; xi: Double): Double;
+var
+  i, j: Integer;
+  p, L: Double;
+begin
+  p := 0.0;
+  for i := 0 to n do
+  begin
+    L := 1.0;
+    for j := 0 to n do
+      if j <> i then
+        L := L * (xi - x[j]) / (x[i] - x[j]);
+    p := p + y[i] * L;
+  end;
+  Result := p;
+end;
+
+//------------------------------------------------------------------------------
+// 牛顿插值算法
+// 入参:x:表示给定的一组 x 坐标,是一个实数数组。
+//       fx:表示给定的一组 y 坐标,也是一个实数数组,与 x 数组一一对应。
+//       n:表示 x 和 y 数组中的数据点个数。
+//       t:表示要求解的 x 坐标,即要求在 x 轴上找到与之对应的 y 坐标。
+// 返回值:返回 t 对应的 y 坐标。
+//------------------------------------------------------------------------------
+function NewtonInterpolation(x, fx: array of Double; n: Integer; t: Double): Double;
+var
+  i, j: Integer;
+  c: array of Double;
+  sum: Double;
+begin
+  SetLength(c, n);
+  for i := 0 to n - 1 do
+    c[i] := fx[i];
+  for i := 1 to n - 1 do
+  begin
+    for j := n - 1 downto i do
+      c[j] := (c[j] - c[j - 1]) / (x[j] - x[j - i]);
+  end;
+  sum := c[n - 1];
+  for i := n - 2 downto 0 do
+  begin
+    sum := c[i] + (t - x[i]) * sum;
+  end;
+  Result := sum;
+end;
+
+//------------------------------------------------------------------------------
+// 最小二乘法插值算法
+// 入参:数组 x 和 y
+//       数组长度 n
+//       参数 t表示要插值的位置
+// 返回:插值结果
+// 公式:f(t) = a * t + b + (y[i] - a * x[i] - b) * sum[(x[i] - t)^2] / sum[(x[i] - t)^2]
+// 解释:其中,a 和 b 是最小二乘法的系数,y[i] 和 x[i] 分别是输入数组的第 i 个
+//       元素的值。sum[] 表示求和符号。函数通过计算 a 和 b,然后计算 f(t) 来获得插值结果。
+//------------------------------------------------------------------------------
+function LeastSquaresInterpolation(x, y: array of Double; n: Integer; t: Double): Double;
+  function dot2(a, b: array of Double): Double;
+  var
+    i: Integer;
+  begin
+    Result := 0;
+    for i := 0 to Length(a) - 1 do
+      Result := Result + a[i] * b[i];
+  end;
+  function dot1(a: array of Double): Double;
+  begin
+    Result := dot2(a, a);
+  end;
+var
+  i : Integer;
+  a, b, c, d, s, ss: Double;
+begin
+  if n < 2 then
+  begin
+    Result := 0;
+    Exit;
+  end;
+  
+  s := 0;
+  ss := 0;
+  for i := 0 to n - 1 do
+  begin
+    s := s + y[i];
+    ss := ss + sqr(y[i]);
+  end;
+  
+  a := (n * dot2(x, y) - dot1(x) * s) / (n * dot2(x, x) - sqr(dot1(x)));
+  b := (s - a * dot1(x)) / n;
+  
+  c := 0;
+  d := 0;
+  for i := 0 to n - 1 do
+  begin
+    c := c + (y[i] - a * x[i] - b) * sqr(x[i] - t);
+    d := d + sqr(x[i] - t);
+  end;
+  
+  Result := a * t + b + c / d;
+end;
+
+//------------------------------------------------------------------------
+// 贝叶斯插值算法
+// 入参:x和y是已知的数据点,xi是插值的位置,sigma是高斯核函数的带宽参数
+// 输出:
+// 说明:该算法使用高斯核函数来对输入数据进行加权,以便生成插值结果。其中,
+//       GaussianKernel()计算两点之间的高斯核函数值,BayesianInterpolation()
+//       计算加权平均值并返回插值结果。
+//------------------------------------------------------------------------
+function BayesianInterpolation(x,y: array of Double; xi: Double; sigma: Double): Double;
+  function GaussianKernel(x, xi, sigma: Double): Double;
+  begin
+    GaussianKernel := exp(-(x - xi) * (x - xi) / (2 * sigma * sigma));
+  end;
+var
+  n, i: Integer;
+  k, W, Wsum, yfit: Double;
+begin
+  n := Length(x);
+  Wsum := 0;
+  yfit := 0;
+  for i := 0 to n - 1 do
+  begin
+    k := GaussianKernel(x[i], xi, sigma);
+    W := k / sigma;
+    Wsum := Wsum + W;
+    yfit := yfit + W * y[i];
+  end;
+  BayesianInterpolation := yfit / Wsum;
+end;
+
+
+//------------------------------------------------------------------------------
+// 获取13位Int64格式毫秒
+// 入参:当前时间-1970-1-1 00:00:00
+// 返回:Int64格式毫秒
+//------------------------------------------------------------------------------
+function GetTimeStampMilliseconds:string;
+var
+  SysTime:TsystemTime;
+  timen,time2:TDateTime;
+  ss2,ss3:int64;
+  str2:string;
+ 
+begin
+  GetLocalTime(SysTime);
+  timen:= SystemTimeToDateTime(SysTime);
+  time2 := EncodeDateTime( 1970, 1, 1, 0, 0, 0, 0 );
+ 
+  ss2 := 28800000;
+  ss3 := MilliSecondsBetween( timen, time2 );
+  ss3 :=ss3- ss2;
+ 
+  str2 := IntToStr(ss3);
+  result:=str2;
+end;
+ 
+function GetMillisecondTimeStamp: Int64;
+var
+  st: TDateTime;
+begin
+  st := EncodeDateTime( 1970, 1, 1, 0, 0, 0, 0 );
+  Result := MilliSecondsBetween( Now, st )-8*60*60*1000;
+end;
+
+//交换16进制数的高低位
+// ABCD--> CDAB
+function SwapHighLowWord(Value: Word): Word;
+begin
+  // 交换高低位
+  Result := (Value and $FF) shl 8 or (Value and $FF00) shr 8;
+end;
+
+end.
+

--
Gitblit v1.9.3