UtilMethods.pas 36 KB

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