UtilMethods.pas 32 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279
  1. unit UtilMethods;
  2. interface
  3. uses
  4. Controls, ZhAPI, ActnList, ZjIDTree, DB, ZjGridDBA, ZjGrid, Windows, Messages,
  5. sdDB, VCLZip, VCLUnZip, Dialogs, Forms, ShlObj, Classes, StrUtils, Math, ADODB,
  6. IdGlobal;
  7. type
  8. TRoundMode = (rmNearest, rmUp, rmDown);
  9. TBookmarkRefreshEvent = procedure (AExpandFrame: Boolean) of object;
  10. {RoundTo}
  11. function QuantityRoundTo(AValue: Double): Double;
  12. function PriceRoundTo(AValue: Double): Double;
  13. function TotalPriceRoundTo(AValue: Double): Double;
  14. function CommonRoundTo(AValue: Double; ADigit: Integer; RoundMode: TRoundMode = rmNearest): Double;
  15. {Interface Control}
  16. procedure AlignControl(AControl, AParent: TWinControl; AAlign: TAlign);
  17. procedure SetDxBtnAction(AAction: TAction; ADxBtn: TObject);
  18. {DataBase Rela}
  19. function GetsdDataSetNewID(ADataSet: TsdDataSet; const AIndex: string): Integer;
  20. procedure ExecuteSql(AConnection: TADOConnection; const ASql: string);
  21. function QueryData(AConnection: TADOConnection; const ASql: string): TADOQuery;
  22. {Message}
  23. procedure WarningMessage(const AMsg: string; AHandle: THandle = 0);
  24. procedure ErrorMessage(const AMsg: string; AHandle: THandle = 0);
  25. function QuestMessage(const AMsg: string; AHandle: THandle = 0): Boolean;
  26. function QuestMessageYesNo(const AMsg: string; AHandle: THandle = 0): Boolean;
  27. procedure TipMessage(const AMsg: string; AHandle: THandle = 0);
  28. procedure DataSetErrorMessage(var Allow: Boolean; const AMsg: string);
  29. {Get Common Path}
  30. function GetAppFilePath: string;
  31. function GetMyProjectsFilePath: string;
  32. function GetEmptyDataBaseFileName: string;
  33. function GetTemplateBillsFileName: string;
  34. function GetTemplateXlsFileName: string;
  35. function GetBackupFilePath: string;
  36. function GetReportTemplatePath: string;
  37. function GetAppTempPath: string;
  38. {Select & Save File Choose}
  39. function GetFilter(AExt: string): string;
  40. function SelectFile(var AFileName: string; const AExt: string): Boolean;
  41. function SelectFiles(AFiles: TStrings; const AExt: string): Boolean;
  42. function SaveFile(var FileName: string; const AExt: string): Boolean;
  43. function SelectOutputDirectory(const ATitle: string; var ADirectory: string;
  44. AParentHandle: THandle = 0; AHasNewFolderBtn: Boolean = True): Boolean;
  45. function FixPathByAppPath(AFileName: string): string;
  46. function BrowseFolder(var APath: string; const ATitle: string;
  47. AParentHandle: THandle; AHasNewFolderBtn: Boolean = True): Boolean;
  48. {CheckStrings}
  49. function CheckPeg(const AStr: string): Boolean;
  50. function CheckValidPassword(APassword: string): Boolean;
  51. function ValidInteger(var AKey: Char): Boolean;
  52. {MergeStrings}
  53. function MergeRelaBGL(const ABGLCode1, ABGLCode2: string): string;
  54. procedure MergeRelaBGLAndNum(var ABGLCode1, ABGLNum1: string; const ABGLCode2, ABGLNum2: string);
  55. {CodeTransform}
  56. function B_CodeToIndexCode(const AB_Code: string): string;
  57. function ChinessNum(const ADigitNum: Integer): string;
  58. function Num2Peg(ANum: Double): string;
  59. {Compare Code}
  60. //function CompareCodeWithChar(const ACode1, ACode2: string): Integer;
  61. {Tree Relative}
  62. function CreateTree: TZjIDTree;
  63. procedure DisConnectTree(ATree: TZjIDTree);
  64. procedure ConnectTree(ATree: TZjIDTree; ADataset: TDataSet);
  65. procedure InitGridHead(AGridDBA: TZjGridDBA; AGrid: TZJGrid);
  66. {Generate Name/Directory/Path}
  67. function GetTempFileDir: string;
  68. function GetTempFilePath: string;
  69. function GetTempName(ALength: Integer = 8): string;
  70. function GetTempFileName: string; overload;
  71. function GetTempFileName(const APath, AExt: string): string; overload;
  72. function GenerateTempFolder(AGeneratePath: string): string;
  73. function GetNewGUIDFileName(const AGeneratePath: string): string;
  74. {Progress bar Control}
  75. procedure UpdateSysProgress(APosition: Integer; const AHint: string);
  76. procedure UpdateProgress(APosition: Integer; const AHint: string);
  77. procedure DisableSysProgress;
  78. procedure EnableSysProgress;
  79. {Interface RePaint Control}
  80. procedure BeginUpdateWindow(AHandle: THandle);
  81. procedure EndUpdateWindow(AHandle: THandle);
  82. {Zip}
  83. procedure ZipFolder(AFileFolder, AFileName: string; ACheckMode: Integer = 0);
  84. function UnZipFile(AFileName, AFileFolder: string): Boolean;
  85. {Copy By Stream}
  86. procedure CopyFileByStream(const ASourceFile, ADestFile: string);
  87. procedure AppendTestLog(const AFileName, ALog: string);
  88. // Add by chenshilong, 2014-04-11
  89. function GetVersion(APartCount: Integer = 4): string;
  90. function ExtractFileNameWithoutExt(const AFileName: string): string;
  91. function ShortText(AText: string; AWidth: Integer): string; // 文本缩略显示
  92. function CustomWidthText(AText: string; AWidth: Integer): string;
  93. function ReplaceCharsForJson(AText: string): string; // 替换Json文本中的特殊字符
  94. function RecoverCharsFromJson(AText: string): string; // 下载得到的Json文本恢复成用户需要的文本
  95. procedure FindFiles(APath, AExtName: string; AFileList: TStrings);
  96. function DeleteFolder(const FolderStr: string): Boolean;
  97. function HasExt(const AFileName: string): Boolean;
  98. function CopyFolder(const SrcFolder, DstFolder: string): Boolean;
  99. function FileCount(APath: string): Integer;
  100. implementation
  101. uses
  102. SysUtils, dxBar, MainFrm, ConstUnit, Globals, StdCtrls, ShellAPI;
  103. var
  104. SysProgressDisabled: Boolean;
  105. {RoundTo}
  106. function InnerRoundTo(const AValue: Extended; const ADigit: Integer; RoundMode: TRoundMode): Extended;
  107. var
  108. LFactor, Offset: Extended;
  109. HFactor: Integer;
  110. begin
  111. LFactor := IntPower(10, ADigit);
  112. HFactor := Trunc(IntPower(10, abs(ADigit)));
  113. Result := AValue;
  114. case RoundMode of
  115. rmNearest:
  116. begin
  117. if AValue >= 0 then
  118. Offset := 0.5
  119. else
  120. Offset := -0.5;
  121. Result := Trunc((AValue * HFactor) + Offset) * LFactor;
  122. end;
  123. rmUP:
  124. begin
  125. if Frac(AValue / LFactor) > 0 then
  126. Result := Trunc(AValue * HFactor + 1) * LFactor
  127. else
  128. Result := Trunc(AValue * HFactor) * LFactor;
  129. end;
  130. rmDown:
  131. begin
  132. Result := Trunc(AValue * HFactor) * LFactor;
  133. end;
  134. end;
  135. end;
  136. function QuantityRoundTo(AValue: Double): Double;
  137. begin
  138. if Assigned(OpenProjectManager.CurProjectData) then
  139. Result := CommonRoundTo(AValue, -OpenProjectManager.CurProjectData.ProjProperties.QuantityDigit)
  140. else
  141. Result := CommonRoundTo(AValue, iQuantityDigit);
  142. end;
  143. function PriceRoundTo(AValue: Double): Double;
  144. begin
  145. if Assigned(OpenProjectManager.CurProjectData) then
  146. Result := CommonRoundTo(AValue, -OpenProjectManager.CurProjectData.ProjProperties.PriceDigit)
  147. else
  148. Result := CommonRoundTo(AValue, iPriceDigit);
  149. end;
  150. function TotalPriceRoundTo(AValue: Double): Double;
  151. begin
  152. if Assigned(OpenProjectManager.CurProjectData) then
  153. Result := CommonRoundTo(AValue, -OpenProjectManager.CurProjectData.ProjProperties.TotalPriceDigit)
  154. else
  155. Result := CommonRoundTo(AValue, iTotalPriceDigit);
  156. end;
  157. function CommonRoundTo(AValue: Double; ADigit: Integer; RoundMode: TRoundMode = rmNearest): Double;
  158. var
  159. X: Double;
  160. P: Pointer;
  161. I: Integer;
  162. Buf: array [0..7] of Byte;
  163. begin
  164. P := @AValue;
  165. CopyMemory(@Buf[0], P, SizeOf(AValue));
  166. // 进位处理,从后往前,如果当前byte为$FF,则往前一byte进1
  167. // 注意到尾数开始的位置停止
  168. // 这里说的前后是二进制串,实际存储前后相反
  169. for I := 0 to 6 do
  170. if (I < 6) and (Buf[I] = $FF) then
  171. Buf[I] := 0
  172. else
  173. begin
  174. Buf[I] := Buf[I] + 1;
  175. Break;
  176. end;
  177. P := @X;
  178. CopyMemory(P, @Buf[0], SizeOf(X));
  179. Result := InnerRoundTo(X, ADigit, RoundMode);
  180. end;
  181. {Interface Control}
  182. procedure AlignControl(AControl, AParent: TWinControl; AAlign: TAlign);
  183. begin
  184. if Assigned(AControl) then
  185. begin
  186. if Assigned(AControl.Parent) then
  187. AControl.Parent.RemoveControl(AControl);
  188. AControl.Parent := AParent;
  189. AControl.Align := AAlign;
  190. end;
  191. end;
  192. procedure SetDxBtnAction(AAction: TAction; ADxBtn: TObject);
  193. begin
  194. if Assigned(ADxBtn) then
  195. if ADxBtn is TdxBarButton then
  196. TdxBarButton(ADxBtn).Action := AAction;
  197. end;
  198. {DataBase Rela}
  199. function GetsdDataSetNewID(ADataSet: TsdDataSet; const AIndex: string): Integer;
  200. var
  201. idx: TsdIndex;
  202. begin
  203. idx := ADataSet.FindIndex(AIndex);
  204. if idx.RecordCount > 0 then
  205. Result := idx.Records[idx.RecordCount - 1].ValueByName('ID').AsInteger + 1
  206. else
  207. Result := 1;
  208. end;
  209. procedure ExecuteSql(AConnection: TADOConnection; const ASql: string);
  210. var
  211. vQuery: TADOQuery;
  212. begin
  213. vQuery := TADOQuery.Create(nil);
  214. try
  215. vQuery.Connection := AConnection;
  216. vQuery.SQL.Add(ASql);
  217. vQuery.ExecSQL;
  218. finally
  219. vQuery.Free;
  220. end;
  221. end;
  222. function QueryData(AConnection: TADOConnection; const ASql: string): TADOQuery;
  223. begin
  224. Result := TADOQuery.Create(nil);
  225. Result.Connection := AConnection;
  226. Result.SQL.Clear;
  227. Result.SQL.Add(ASql);
  228. Result.Open;
  229. end;
  230. {Message}
  231. function GetValidHandle(AHandle: THandle = 0): THandle;
  232. begin
  233. if AHandle = 0 then
  234. begin
  235. if (Screen.ActiveForm <> nil) and (Screen.ActiveForm.HandleAllocated) then
  236. Result := Screen.ActiveForm.Handle
  237. else
  238. Result := Application.Handle;
  239. end
  240. else
  241. Result := AHandle;
  242. end;
  243. procedure WarningMessage(const AMsg: string; AHandle: THandle = 0);
  244. begin
  245. MessageBox(GetValidHandle(AHandle), PChar(AMsg), PChar('警告'), MB_OK or MB_ICONWARNING);
  246. end;
  247. procedure ErrorMessage(const AMsg: string; AHandle: THandle = 0);
  248. begin
  249. MessageBox(GetValidHandle(AHandle), PChar(AMsg), PChar('错误'), MB_OK or MB_ICONERROR);
  250. end;
  251. function QuestMessage(const AMsg: string; AHandle: THandle = 0): Boolean;
  252. begin
  253. Result := MessageBox(GetValidHandle(AHandle), PChar(AMsg), PChar('询问'), MB_OKCANCEL or MB_ICONQUESTION) = IDOK;
  254. end;
  255. function QuestMessageYesNo(const AMsg: string; AHandle: THandle = 0): Boolean;
  256. begin
  257. Result := MessageBox(GetValidHandle(AHandle), PChar(AMsg), PChar('询问'), MB_YESNO or MB_ICONQUESTION) = IDYes;
  258. end;
  259. procedure TipMessage(const AMsg: string; AHandle: THandle = 0);
  260. begin
  261. MessageBox(GetValidHandle(AHandle), PChar(AMsg), PChar('提示'), MB_OK or MB_ICONINFORMATION);
  262. end;
  263. procedure DataSetErrorMessage(var Allow: Boolean; const AMsg: string);
  264. begin
  265. Allow := False;
  266. ErrorMessage(AMsg);
  267. end;
  268. {Get Common Path}
  269. function GetAppFilePath: string;
  270. begin
  271. Result := ExtractFilePath(ParamStr(0));
  272. end;
  273. function GetMyProjectsFilePath: string;
  274. begin
  275. Result := GetAppFilePath + '我的项目\';
  276. end;
  277. function GetEmptyDataBaseFileName: string;
  278. begin
  279. Result := GetAppFilePath + 'Data\Base.dat';
  280. end;
  281. function GetTemplateBillsFileName: string;
  282. begin
  283. Result := GetAppFilePath + 'Data\Template.xls';
  284. end;
  285. function GetTemplateXlsFileName: string;
  286. begin
  287. Result := GetAppFilePath + 'Data\Basic.xls';
  288. end;
  289. function GetBackupFilePath: string;
  290. begin
  291. Result := GetAppFilePath + 'TenderBackup\';
  292. end;
  293. function GetReportTemplatePath: string;
  294. begin
  295. Result := GetAppFilePath + 'ReportTemplates\';
  296. end;
  297. function GetAppTempPath: string;
  298. begin
  299. Result := GetAppFilePath + 'Temp\';
  300. if DirectoryExists(Result) then
  301. CreateDirectoryInDeep(Result);
  302. end;
  303. {Select & Save File Choose}
  304. function GetFilter(AExt: string): string;
  305. begin
  306. if AExt = '' then
  307. Result := '所有文件(*.*)|*.*'
  308. else
  309. begin
  310. if AExt[1] <> '.' then
  311. AExt := '.' + AExt;
  312. Result := Format('(*%s)|*%s', [AExt, AExt]);
  313. end;
  314. end;
  315. function SelectFile(var AFileName: string; const AExt: string): Boolean;
  316. var
  317. odFile: TOpenDialog;
  318. begin
  319. odFile := TOpenDialog.Create(nil);
  320. try
  321. odFile.Filter := GetFilter(AExt);
  322. if odFile.Execute then
  323. begin
  324. Application.ProcessMessages;
  325. AFileName := odFile.FileName;
  326. Result := True;
  327. end
  328. else
  329. Result := False;
  330. finally
  331. odFile.Free;
  332. end;
  333. end;
  334. function SelectFiles(AFiles: TStrings; const AExt: string): Boolean;
  335. var
  336. odFile: TOpenDialog;
  337. begin
  338. odFile := TOpenDialog.Create(nil);
  339. try
  340. odFile.Options := odFile.Options + [ofAllowMultiSelect];
  341. odFile.Filter := GetFilter(AExt);
  342. if odFile.Execute then
  343. begin
  344. Application.ProcessMessages;
  345. AFiles.Assign(odFile.Files);
  346. Result := True;
  347. end
  348. else
  349. Result := False;
  350. finally
  351. odFile.Free;
  352. end;
  353. end;
  354. function SaveFile(var FileName: string; const AExt: string): Boolean;
  355. var
  356. sdFile: TSaveDialog;
  357. begin
  358. sdFile := TSaveDialog.Create(nil);
  359. try
  360. sdFile.FileName := FileName;
  361. sdFile.DefaultExt := AExt;
  362. sdFile.Filter := GetFilter(AExt);
  363. Result := sdFile.Execute;
  364. if Result then
  365. FileName := sdFile.FileName;
  366. Application.ProcessMessages;
  367. finally
  368. sdFile.Free;
  369. end;
  370. end;
  371. function SelectOutputDirectory(const ATitle: string; var ADirectory: string;
  372. AParentHandle: THandle; AHasNewFolderBtn: Boolean): Boolean;
  373. var
  374. pID: PItemIDList;
  375. bInfo: TBrowseInfo;
  376. AHandle: THandle;
  377. PStr: array[0..1023] of Char;
  378. sPath: string;
  379. function BFCallBack(Hwnd: HWND; uMsg: UINT; lParam, lpData: LPARAM): Integer; stdcall;
  380. begin
  381. if uMsg = BFFM_INITIALIZED then
  382. begin
  383. SendMessage(Hwnd, BFFM_SETSELECTION, 1, lpData);
  384. end;
  385. Result := 0;
  386. end;
  387. begin
  388. Result := False;
  389. if AParentHandle = 0 then
  390. AHandle := Screen.ActiveForm.Handle
  391. else
  392. AHandle := AParentHandle;
  393. if ADirectory = '' then
  394. sPath := GetAppFilePath
  395. else
  396. sPath := ADirectory;
  397. with bInfo do
  398. begin
  399. hwndOwner := AParentHandle;
  400. iImage := 0;
  401. lParam := Integer(PChar(sPath));
  402. lpszTitle := PChar(ATitle);
  403. pidlRoot := nil;
  404. pszDisplayName := nil;
  405. if AHasNewFolderBtn then
  406. ulFlags := BIF_RETURNONLYFSDIRS or BIF_USENEWUI
  407. else
  408. ulFlags := BIF_RETURNONLYFSDIRS;
  409. lpfn := @BFCallBack;
  410. end;
  411. pID := SHBrowseForFolder(bInfo);
  412. if pID <> nil then
  413. begin
  414. SHGetPathFromIDList(pID, PStr);
  415. ADirectory := StrPas(PStr);
  416. if (ADirectory <> '') and (ADirectory[Length(ADirectory)] <> '\') then
  417. ADirectory := ADirectory + '\';
  418. Result := True;
  419. end;
  420. end;
  421. function FixPathByAppPath(AFileName: string): string;
  422. begin
  423. Result := AFileName;
  424. if AnsiPos(':\', Result) = 0 then
  425. begin
  426. if (Result <> '') and (Result[1] = '\') then
  427. Delete(Result, 1, 1);
  428. Result := ExtractFilePath(Application.ExeName) + Result;
  429. end;
  430. end;
  431. var
  432. PathStr: string;
  433. function BrowseFolder(var APath: string; const ATitle: string; AParentHandle: THandle;
  434. AHasNewFolderBtn: Boolean): Boolean;
  435. function BFCallBackFunc(hwnd: HWND; uMsg: UINT; lParam: LPARAM; lpData: LPARAM): Integer; stdcall;
  436. begin
  437. Result := 0;
  438. case uMsg of
  439. BFFM_INITIALIZED : // 初始化设置目录。
  440. begin
  441. SendMessage(Hwnd,BFFM_SETSELECTION,-1,Integer(PathStr));
  442. end;
  443. end;
  444. end;
  445. var
  446. pID: PItemIDList;
  447. bInfo: TBrowseInfo;
  448. PStr: array[0..1023] of Char;
  449. sPath: string;
  450. Hdl: THandle;
  451. begin
  452. Result := False;
  453. PathStr := '';
  454. if AParentHandle = 0 then
  455. Hdl := Screen.ActiveForm.Handle
  456. else
  457. Hdl := AParentHandle;
  458. sPath := FixPathByAppPath(APath);
  459. if DirectoryExists(sPath) then
  460. PathStr := sPath;
  461. bInfo.hwndOwner := Hdl;
  462. bInfo.iImage := 0;
  463. bInfo.lParam := 0;
  464. bInfo.lpszTitle := PChar(ATitle);
  465. bInfo.pidlRoot := nil;
  466. bInfo.pszDisplayName := nil;
  467. if (not AHasNewFolderBtn) then
  468. bInfo.ulFlags := BIF_RETURNONLYFSDIRS
  469. else
  470. bInfo.ulFlags := BIF_RETURNONLYFSDIRS or BIF_USENEWUI;
  471. bInfo.lpfn := @BFCallBackFunc;
  472. pID := SHBrowseForFolder(bInfo);
  473. if pID <> nil then
  474. begin
  475. SHGetPathFromIDList(pID,pStr);
  476. APath := StrPas(pStr);
  477. if (APath <> '') and (APath[Length(APath)] <> '\') then
  478. APath := APath + '\';
  479. Result := True;
  480. end;
  481. end;
  482. {CheckStrings}
  483. function CheckPeg(const AStr: string): Boolean;
  484. function GetPosition(const AName, AStr, AStrSpare: string): Integer;
  485. begin
  486. Result := Pos(AStr, AName);
  487. if Result = 0 then
  488. Result := Pos(AStrSpare, AName);
  489. end;
  490. var
  491. iPosK, iPosPlus: Integer;
  492. fNum: Double;
  493. begin
  494. Result := False;
  495. iPosK := GetPosition(AStr, 'K', 'k');
  496. iPosPlus := GetPosition(AStr, '+', '+');
  497. if (iPosK = 0) or (iPosPlus = 0) or (iPosPlus < iPosK) then Exit;
  498. Result := TryStrToFloat(Copy(AStr, iPosK + 1, iPosPlus - iPosK - 1), fNum);
  499. end;
  500. function CheckValidPassword(APassword: string): Boolean;
  501. var
  502. iIndex, iLength: Integer;
  503. begin
  504. Result := True;
  505. if APassword = '' then Exit;
  506. iIndex := 1;
  507. iLength := Length(APassword);
  508. Result := (iLength >= 6) and (iLength <= 16);
  509. while Result and (iIndex < iLength) do
  510. begin
  511. Result := APassword[iIndex] in ['A'..'Z', 'a'..'z', '0'..'9'];
  512. Inc(iIndex);
  513. end;
  514. end;
  515. function ValidInteger(var AKey: Char): Boolean;
  516. begin
  517. if AKey in ['+', '-', '0'..'9', #8, #13, #35, #36,
  518. #37, #38, #39, #40, #46] then
  519. begin
  520. Result := True;
  521. end
  522. else
  523. begin
  524. AKey := #0;
  525. Result := False;
  526. end;
  527. end;
  528. {MergeStrings}
  529. function MergeRelaBGL(const ABGLCode1, ABGLCode2: string): string;
  530. var
  531. sgs1, sgs2: TStrings;
  532. i1, i2: Integer;
  533. bExist: Boolean;
  534. begin
  535. Result := ABGLCode1;
  536. sgs1 := TStringList.Create;
  537. sgs2 := TStringList.Create;
  538. try
  539. sgs1.Delimiter := ';';
  540. sgs2.Delimiter := ';';
  541. sgs1.DelimitedText := ABGLCode1;
  542. sgs2.DelimitedText := ABGLCode2;
  543. for i2 := 0 to sgs2.Count - 1 do
  544. begin
  545. bExist := False;
  546. for i1 := 0 to sgs1.Count - 1 do
  547. if SameText(sgs2[i2], sgs1[i1]) then
  548. begin
  549. bExist := True;
  550. Break;
  551. end;
  552. if not bExist then
  553. sgs1.Add(sgs2[i2]);
  554. end;
  555. Result := sgs1.DelimitedText;
  556. finally
  557. sgs1.Free;
  558. sgs2.Free;
  559. end;
  560. end;
  561. procedure MergeRelaBGLAndNum(var ABGLCode1, ABGLNum1: string; const ABGLCode2, ABGLNum2: string);
  562. var
  563. sgsC1, sgsC2, sgsN1, sgsN2: TStrings;
  564. i1, i2: Integer;
  565. bExist: Boolean;
  566. begin
  567. sgsC1 := TStringList.Create;
  568. sgsC2 := TStringList.Create;
  569. sgsN1 := TStringList.Create;
  570. sgsN2 := TStringList.Create;
  571. try
  572. sgsC1.Delimiter := ';';
  573. sgsC2.Delimiter := ';';
  574. sgsC1.DelimitedText := ABGLCode1;
  575. sgsC2.DelimitedText := ABGLCode2;
  576. sgsN1.Delimiter := ';';
  577. sgsN2.Delimiter := ';';
  578. sgsN1.DelimitedText := ABGLNum1;
  579. sgsN2.DelimitedText := ABGLNum2;
  580. for i2 := 0 to sgsC2.Count - 1 do
  581. begin
  582. bExist := False;
  583. for i1 := 0 to sgsC1.Count - 1 do
  584. if SameText(sgsC2[i2], sgsC1[i1]) then
  585. begin
  586. bExist := True;
  587. Break;
  588. end;
  589. if bExist then
  590. begin
  591. sgsN1[i1] := FloatToStr(StrToFloatDef(sgsN1[i1], 0) + StrToFloatDef(sgsN2[i2], 0))
  592. end
  593. else
  594. begin
  595. sgsC1.Add(sgsC2[i2]);
  596. sgsN1.Add(sgsN2[i2]);
  597. end;
  598. end;
  599. ABGLCode1 := sgsC1.DelimitedText;
  600. ABGLNum1 := sgsN1.DelimitedText;
  601. finally
  602. sgsC1.Free;
  603. sgsC2.Free;
  604. sgsN1.Free;
  605. sgsN2.Free;
  606. end;
  607. end;
  608. function B_CodeToIndexCode(const AB_Code: string): string;
  609. var
  610. sgs: TStrings;
  611. i, iNum, iError: Integer;
  612. sError: string;
  613. begin
  614. sgs := TStringList.Create;
  615. try
  616. Result := '';
  617. sgs.Delimiter := '-';
  618. sgs.DelimitedText := AB_Code;
  619. for i := 0 to sgs.Count - 1 do
  620. begin
  621. Val(sgs[i], iNum, iError);
  622. if iError = 0 then
  623. sError := ''
  624. else
  625. sError := Copy(sgs[i], iError, Length(sgs[i])-iError+1);
  626. if iError = 0 then
  627. Result := Result + Format('%4d', [iNum]) + Format('%-4s', [sError])
  628. else if iNum = 0 then
  629. Result := Result + '9999' + Format('%-4s', [sError])
  630. else
  631. Result := Result + Format('%4d', [iNum]) + Format('%-4s', [sError]);
  632. end;
  633. finally
  634. sgs.Free;
  635. end;
  636. end;
  637. function ChinessNum(const ADigitNum: Integer): string;
  638. function TransChineseNum(const ANum, AZeroNum: Integer): string;
  639. begin
  640. Result := '';
  641. case ANum of
  642. 1: if AZeroNum <> 1 then Result := '一';
  643. 2: Result := '二';
  644. 3: Result := '三';
  645. 4: Result := '四';
  646. 5: Result := '五';
  647. 6: Result := '六';
  648. 7: Result := '七';
  649. 8: Result := '八';
  650. 9: Result := '九';
  651. end;
  652. if (Result = '') and ((AZeroNum <> 1) or (ANum = 0)) then Exit;
  653. case AZeroNum of
  654. 0: Result := Result;
  655. 1: Result := Result + '十';
  656. 2: Result := Result + '百';
  657. 3: Result := Result + '千';
  658. 4: Result := Result + '万';
  659. end;
  660. end;
  661. var
  662. iBai, iShi, iGe: Integer;
  663. begin
  664. Result := '';
  665. if (ADigitNum < 0) and (ADigitNum > 10000) then Exit;
  666. iBai := ADigitNum div 100;
  667. iShi := (ADigitNum mod 100) div 10;
  668. iGe := (ADigitNum mod 100) mod 10;
  669. Result := TransChineseNum(iBai, 2) + TransChineseNum(iShi, 1) + TransChineseNum(iGe, 0);
  670. end;
  671. function CheckDigit(ANum: Double): Integer;
  672. begin
  673. if abs(ANum - advRoundTo(ANum, -2)) > 0.0001 then
  674. Result := 3
  675. else if abs(ANum - advRoundTo(ANum, -1)) > 0.001 then
  676. Result := 2
  677. else if abs(ANum - AdvRoundTo(ANum, 0)) > 0.01 then
  678. Result := 1
  679. else
  680. Result := 0;
  681. end;
  682. function Num2Peg(ANum: Double): string;
  683. var
  684. fMod: Double;
  685. iK, iDigit: Integer;
  686. sDigit: string;
  687. begin
  688. iK := Trunc(ANum/1000);
  689. fMod := Frac(ANum/1000)*1000;
  690. iDigit := CheckDigit(fMod);
  691. case iDigit of
  692. 3: sDigit := FormatFloat('000.000', AdvRoundTo(fMod, -3));
  693. 2: sDigit := FormatFloat('000.00', AdvRoundTo(fMod, -2));
  694. 1: sDigit := FormatFloat('000.0', AdvRoundTo(fMod, -1));
  695. 0: sDigit := FormatFloat('000', Trunc(AdvRoundTo(fMod, 0)));
  696. end;
  697. { case iDigit of
  698. 3: Result := Format('K%d+%3.3f', [iK, ]);
  699. 2: Result := Format('K%d+%3.2f', [iK, AdvRoundTo(fMod, -2)]);
  700. 1: Result := Format('K%d+%3.1f', [iK, AdvRoundTo(fMod, -1)]);
  701. 0: Result := Format('K%d+%s', [iK, FormatFloat('000', [])]);
  702. end; }
  703. Result := Format('K%d+%s', [iK, sDigit]);
  704. end;
  705. {Tree Relative}
  706. function CreateTree: TZjIDTree;
  707. begin
  708. Result := TZjIDTree.Create;
  709. Result.KeyFieldName := 'ID';
  710. Result.ParentFieldName := 'ParentID';
  711. Result.NextSiblingFieldName := 'NextSiblingID';
  712. Result.AutoCreateKeyID := True;
  713. Result.AutoExpand := True;
  714. end;
  715. procedure DisConnectTree(ATree: TZjIDTree);
  716. begin
  717. ATree.DataSet := nil;
  718. ATree.Active := False;
  719. end;
  720. procedure ConnectTree(ATree: TZjIDTree; ADataset: TDataSet);
  721. begin
  722. ATree.DataSet := ADataset;
  723. ATree.Active := True;
  724. end;
  725. procedure InitGridHead(AGridDBA: TZjGridDBA; AGrid: TZJGrid);
  726. var
  727. I: Integer;
  728. begin
  729. for I := 0 to AGridDBA.Columns.Count - 1 do
  730. AGrid.Cells[I + 1, 0].Text := AGridDBA.Columns[I].Title.Caption;
  731. end;
  732. {Generate Name/Path}
  733. function GetTempFileDir: string;
  734. var
  735. TempPath: string;
  736. begin
  737. TempPath := GetEnvironmentVariable('TMP');
  738. if TempPath = '' then
  739. TempPath := GetEnvironmentVariable('TEMP');
  740. if TempPath = '' then
  741. begin
  742. if not DirectoryExists(ExtractFileDir(ParamStr(0)) + '\Temp') then
  743. CreateDir(ExtractFileDir(ParamStr(0)) + '\Temp');
  744. TempPath := ExtractFileDir(ParamStr(0)) + '\Temp';
  745. end;
  746. Result := TempPath;
  747. end;
  748. function GetTempFilePath: string;
  749. begin
  750. Result := GetTempFileDir + '\';
  751. end;
  752. function GetTempName(ALength: Integer): string;
  753. const
  754. CodedBuf: array[0..35] of Char = ('0', '1', '2', '3', '4', '5',
  755. '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I',
  756. 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V',
  757. 'W', 'X', 'Y', 'Z');
  758. var
  759. Temp: string;
  760. Num: Integer;
  761. begin
  762. Randomize;
  763. Temp := '';
  764. while Length(Temp) < ALength do
  765. begin
  766. Num := Random(37);
  767. If Num <> 36 Then
  768. Temp := Temp + CodedBuf[Num]; // 0..35
  769. end;
  770. Result := Temp;
  771. end;
  772. function GetTempFileName: string;
  773. var
  774. TempExt: string;
  775. begin
  776. Result := GetTempFilePath + GetTempName;
  777. TempExt := '.' + GetTempName(3);
  778. while SameText(TempExt, '.mdb') or SameText(TempExt, '.db') or
  779. SameText(TempExt, '.ldb') do
  780. TempExt := '.' + GetTempName(3);
  781. Result := Result + TempExt;
  782. while FileExists(Result) do
  783. begin
  784. Result := GetTempFilePath + GetTempName;
  785. TempExt := '.' + GetTempName(3);
  786. while SameText(TempExt, '.mdb') or SameText(TempExt, '.db') or
  787. SameText(TempExt, '.ldb') do
  788. TempExt := '.' + GetTempName(3);
  789. Result := Result + TempExt;
  790. end;
  791. end;
  792. function GetTempFileName(const APath, AExt: string): string;
  793. begin
  794. Result := APath + GetTempName + AExt;
  795. while FileExists(Result) do
  796. Result := APath + GetTempName + AExt;
  797. end;
  798. function GenerateTempFolder(AGeneratePath: string): string;
  799. begin
  800. Result := AGeneratePath + GetTempName;
  801. while DirectoryExists(Result) do
  802. Result := AGeneratePath + GetTempName;
  803. CreateDirectoryInDeep(Result);
  804. end;
  805. function GetNewGUIDFileName(const AGeneratePath: string): string;
  806. var
  807. gFile: TGUID;
  808. begin
  809. repeat
  810. CreateGUID(gFile);
  811. Result := AGeneratePath + GUIDToString(gFile);
  812. until not FileExists(Result);
  813. end;
  814. {Progress bar Control}
  815. procedure UpdateSysProgress(APosition: Integer; const AHint: string);
  816. begin
  817. if not SysProgressDisabled then
  818. UpdateProgress(APosition, AHint);
  819. end;
  820. procedure UpdateProgress(APosition: Integer; const AHint: string);
  821. begin
  822. MainForm.UpdateProgress(APosition, AHint);
  823. end;
  824. procedure DisableSysProgress;
  825. begin
  826. SysProgressDisabled := True;
  827. end;
  828. procedure EnableSysProgress;
  829. begin
  830. SysProgressDisabled := False;
  831. end;
  832. {Interface RePaint Control}
  833. procedure BeginUpdateWindow(AHandle: THandle);
  834. begin
  835. SendMessage(AHandle, WM_SETREDRAW, 0, 0);
  836. end;
  837. procedure EndUpdateWindow(AHandle: THandle);
  838. begin
  839. SendMessage(AHandle, WM_SETREDRAW, 1, 0);
  840. end;
  841. {Zip}
  842. function ZipComplete(const AFileName: string; ACheckMode: Integer): Boolean;
  843. const
  844. i4k = 4096;
  845. var
  846. iSize1, iSize2: Integer;
  847. begin
  848. iSize1 := FileSizeByName(AFileName);
  849. Sleep(300);
  850. iSize2 := FileSizeByName(AFileName);
  851. Result := (iSize1 = iSize2);
  852. if ACheckMode = 0 then
  853. Result := Result and (iSize1 > i4k);
  854. end;
  855. procedure ZipFolder(AFileFolder, AFileName: string; ACheckMode: Integer = 0);
  856. procedure AppendLog(const ALog: string);
  857. begin
  858. if SupportManager.ConfigInfo.IsLog then
  859. MeasureLog.AppendLogTo(ALog);
  860. end;
  861. var
  862. sTempFile: string;
  863. vZip: TVCLZip;
  864. iCount: Integer;
  865. begin
  866. AppendLog('Zip');
  867. sTempFile := GetTempFileName;
  868. vZip := TVCLZip.Create(nil);
  869. iCount := 0;
  870. try
  871. vZip.FilesList.Clear;
  872. vZip.ZipName := sTempFile;
  873. vzip.RootDir := AFileFolder;
  874. vZip.OverwriteMode := Always;
  875. //vZip.AddDirEntriesOnRecurse:=True;
  876. vZip.RelativePaths := True;
  877. //vZip.RecreateDirs := True;
  878. vZip.FilesList.Add(AFileFolder + '\*.*');
  879. vZip.Zip;
  880. AppendLog(Format('Check Zip File, FileSize - %d', [FileSizeByName(sTempFile)]));
  881. while not ZipComplete(sTempFile, ACheckMode) and (iCount < 10) do
  882. begin
  883. Sleep(200);
  884. Inc(iCount);
  885. AppendLog(Format('Check Zip File - %d, FileSize - %d', [iCount + 1, FileSizeByName(sTempFile)]));
  886. end;
  887. AppendLog('Check Zip File --> Pass');
  888. CopyFileOrFolder(sTempFile, AFileName);
  889. AppendLog('Zip --> Pass');
  890. finally
  891. vZip.Free;
  892. if FileExists(sTempFile) then
  893. DeleteFile(sTempFile);
  894. end;
  895. end;
  896. function UnZipFile(AFileName, AFileFolder: string): Boolean;
  897. var
  898. vUnZip: TVCLZip;
  899. begin
  900. Result := True;
  901. vUnZip := TVCLZip.Create(nil);
  902. try
  903. vUnZip.FilesList.Clear;
  904. vUnZip.ZipName := AFileName;
  905. vUnZip.ReadZip;
  906. vUnZip.DestDir := AFileFolder;
  907. vUnZip.OverwriteMode := Always;
  908. vUnZip.RecreateDirs := True;
  909. vUnZip.RelativePaths := True;
  910. vUnZip.DoAll := True;
  911. vUnZip.FilesList.Add('*.*');
  912. try
  913. vUnZip.UnZip;
  914. except
  915. Result := False;
  916. end;
  917. finally
  918. vUnZip.Free;
  919. end;
  920. end;
  921. {Copy By Stream}
  922. procedure CopyFileByStream(const ASourceFile, ADestFile: string);
  923. var
  924. MS: TMemoryStream;
  925. begin
  926. MS := TMemoryStream.Create;
  927. try
  928. MS.LoadFromFile(ASourceFile);
  929. if FileExists(ADestFile) then
  930. DeleteFile(ADestFile);
  931. MS.SaveToFile(ADestFile);
  932. finally
  933. MS.Free;
  934. end;
  935. end;
  936. procedure AppendTestLog(const AFileName, ALog: string);
  937. var
  938. f: TextFile;
  939. begin
  940. try
  941. if FileExists(AFileName) then
  942. begin
  943. AssignFile(f, AFileName);
  944. Append(f);
  945. Writeln(f, ALog);
  946. end
  947. else
  948. begin
  949. AssignFile(f, AFileName);
  950. Rewrite(f);
  951. Writeln(f, ALog);
  952. end;
  953. finally
  954. CloseFile(f);
  955. end;
  956. end;
  957. function GetVersion(APartCount: Integer = 4): string;
  958. var
  959. V1, V2, V3, V4: Word;
  960. FInfoSize, FF: Cardinal;
  961. FInfo: Pointer;
  962. FFixed: PVSFIXEDFILEINFO;
  963. begin
  964. FInfoSize := GetFileVersionInfoSize(PChar(Application.ExeName), FF);
  965. FInfo := AllocMem(FInfoSize);
  966. try
  967. GetFileVersionInfo(PChar(Application.ExeName), FF, FInfoSize, FInfo);
  968. VerQueryValue(FInfo, '\', Pointer(FFixed), FInfoSize);
  969. V1 := FFixed.dwFileVersionMS shr 16;
  970. V2 := FFixed.dwFileVersionMS and $FFFF;
  971. V3 := FFixed.dwFileVersionLS shr 16;
  972. V4 := FFixed.dwFileVersionLS and $FFFF;
  973. finally
  974. Dispose(FInfo);
  975. end;
  976. Result := '';
  977. case APartCount of
  978. 1:
  979. Result := Format('%d', [V1]);
  980. 2:
  981. Result := Format('%d.%d', [V1, V2]);
  982. 3:
  983. Result := Format('%d.%d.%d', [V1, V2, V3]);
  984. 4:
  985. Result := Format('%d.%d.%d.%d', [V1, V2, V3, V4]);
  986. end;
  987. end;
  988. function ExtractFileNameWithoutExt(const AFileName: string): string;
  989. var
  990. sFileName, Ext: string;
  991. begin
  992. Result := '';
  993. if AFileName = '' then
  994. Exit;
  995. sFileName := AFileName;
  996. if sFileName[Length(sFileName)] = '\' then
  997. Delete(sFileName, Length(sFileName), 1);
  998. Result := ExtractFileName(sFileName);
  999. Ext := ExtractFileExt(sFileName);
  1000. Delete(Result, Length(Result) - Length(Ext) + 1, Length(Ext));
  1001. end;
  1002. function ShortText(AText: string; AWidth: Integer): string;
  1003. var vMM: TMemo;
  1004. begin
  1005. if Trim(AText) = '' then
  1006. begin
  1007. Result := '';
  1008. Exit;
  1009. end;
  1010. vMM := TMemo.Create(nil);
  1011. try
  1012. vMM.Visible := False;
  1013. vMM.WordWrap := True;
  1014. vMM.parent := Application.MainForm;
  1015. vMM.Width := AWidth - 10; // 10像素留给3个小点
  1016. vMM.Text := AText;
  1017. if vMM.Lines.Count > 1 then
  1018. Result := vMM.Lines[0] + '...'
  1019. else
  1020. Result := AText;
  1021. finally
  1022. vMM.Free;
  1023. end;
  1024. end;
  1025. function CustomWidthText(AText: string; AWidth: Integer): string;
  1026. var vMM: TMemo;
  1027. i: Integer;
  1028. begin
  1029. if Trim(AText) = '' then
  1030. begin
  1031. Result := '';
  1032. Exit;
  1033. end;
  1034. vMM := TMemo.Create(nil);
  1035. try
  1036. vMM.Visible := False;
  1037. vMM.WordWrap := True;
  1038. vMM.parent := Application.MainForm;
  1039. vMM.Width := AWidth;
  1040. vMM.Text := AText;
  1041. for i := 0 to vMM.Lines.Count - 1 do
  1042. begin
  1043. if i = 0 then
  1044. Result := vMM.Lines[i]
  1045. else
  1046. Result := Result + #10#13 + vMM.Lines[i];
  1047. end;
  1048. finally
  1049. vMM.Free;
  1050. end;
  1051. end;
  1052. function ReplaceCharsForJson(AText: string): string;
  1053. const
  1054. BefChar: array [0..7] of Char = ('{', '}', ',', ':', '"', '[', ']', '%');
  1055. AftChar: array [0..7] of string = ('{', '}', ',', ':', '"', '【', '】', '♂');
  1056. var I: Integer;
  1057. begin
  1058. AText := Trim(AText);
  1059. Result := AText;
  1060. if AText = '' then Exit;
  1061. for I := low(BefChar) to High(BefChar) do
  1062. begin
  1063. if Pos(BefChar[I], AText) > 0 then
  1064. AText := StringReplace(AText, BefChar[I], AftChar[I], [rfReplaceAll]);
  1065. end;
  1066. Result := AText;
  1067. end;
  1068. function RecoverCharsFromJson(AText: string): string;
  1069. const
  1070. BefStr: array [0..3] of string = ('♂', '\r\n', '\r', '\n');
  1071. AftStr: array [0..3] of string = ('%', '', '', '');
  1072. var I: Integer;
  1073. begin
  1074. AText := Trim(AText);
  1075. Result := AText;
  1076. if AText = '' then Exit;
  1077. for I := low(BefStr) to High(BefStr) do
  1078. begin
  1079. if Pos(BefStr[I], AText) > 0 then
  1080. AText := StringReplace(AText, BefStr[I], AftStr[I], [rfReplaceAll]);
  1081. end;
  1082. Result := AText;
  1083. end;
  1084. procedure FindFiles(APath, AExtName: string; AFileList: TStrings);
  1085. var
  1086. SRec: TSearchRec;
  1087. retval: Integer;
  1088. begin
  1089. AFileList.Clear;
  1090. retval := FindFirst(APath + AExtName, faAnyFile, sRec);
  1091. try
  1092. while retval = 0 do
  1093. begin
  1094. if (SRec.Attr and faDirectory) = 0 then
  1095. AFileList.Add(Srec.Name);
  1096. retval := FindNext(SRec);
  1097. end;
  1098. finally
  1099. FindClose(SRec);
  1100. end;
  1101. end;
  1102. function DeleteFolder(const FolderStr: string): Boolean;
  1103. var
  1104. fos: SHFILEOPSTRUCT;
  1105. begin
  1106. ZeroMemory(@fos, SizeOf(fos));
  1107. fos.Wnd := HWND_DESKTOP;
  1108. fos.wFunc := FO_DELETE;
  1109. fos.fFlags := FOF_SILENT OR FOF_ALLOWUNDO OR FOF_NOCONFIRMATION;
  1110. fos.pFrom := PChar(FolderStr + #0);
  1111. Result := SHFileOperation(fos) <> 0;
  1112. end;
  1113. function HasExt(const AFileName: string): Boolean;
  1114. begin
  1115. Result := ExtractFileExt(AFileName) <> '';
  1116. end;
  1117. function CopyFolder(const SrcFolder, DstFolder: string): Boolean;
  1118. var
  1119. fos: SHFILEOPSTRUCT;
  1120. begin
  1121. ZeroMemory(@fos, SizeOf(fos));
  1122. fos.Wnd := HWND_DESKTOP;
  1123. fos.wFunc := FO_COPY;
  1124. fos.fFlags := FOF_SILENT OR FOF_ALLOWUNDO;
  1125. fos.pFrom := PChar(SrcFolder + #0);
  1126. fos.pTo := PChar(DstFolder + #0);
  1127. Result := SHFileOperation(fos) <> 0;
  1128. end;
  1129. function FileCount(APath: string): Integer;
  1130. var
  1131. vSR: TSearchRec;
  1132. iRetval: Integer;
  1133. vSL: TStringList;
  1134. begin
  1135. vSL := TStringList.Create;
  1136. iRetval := FindFirst(APath + '*.*', faAnyFile, vSR);
  1137. try
  1138. while iRetval = 0 do
  1139. begin
  1140. if (vSR.Attr and faDirectory) = 0 then
  1141. vSL.Add(vSR.Name);
  1142. iRetval := FindNext(vSR);
  1143. end;
  1144. Result := vSL.Count;
  1145. finally
  1146. FindClose(vSR);
  1147. vSL.Free;
  1148. end;
  1149. end;
  1150. end.