UtilMethods.pas 37 KB

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