UtilMethods.pas 34 KB

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