UtilMethods.pas 36 KB

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