UtilMethods.pas 33 KB

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