UtilMethods.pas 25 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015
  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;
  6. type
  7. TBookmarkRefreshEvent = procedure (AExpandFrame: Boolean) of object;
  8. {RoundTo}
  9. function QuantityRoundTo(AValue: Double): Double;
  10. function PriceRoundTo(AValue: Double): Double;
  11. function TotalPriceRoundTo(AValue: Double): Double;
  12. {Interface Control}
  13. procedure AlignControl(AControl, AParent: TWinControl; AAlign: TAlign);
  14. procedure SetDxBtnAction(AAction: TAction; ADxBtn: TObject);
  15. {Message}
  16. procedure WarningMessage(const AMsg: string);
  17. procedure ErrorMessage(const AMsg: string);
  18. function QuestMessage(const AMsg: string): Boolean;
  19. procedure DataSetErrorMessage(var Allow: Boolean; const AMsg: string);
  20. {Get Common Path}
  21. function GetAppFilePath: string;
  22. function GetMyProjectsFilePath: string;
  23. function GetEmptyDataBaseFileName: string;
  24. function GetTemplateBillsFileName: string;
  25. function GetTemplateXlsFileName: string;
  26. function GetBackupFilePath: string;
  27. function GetReportTemplatePath: string;
  28. {Select & Save File Choose}
  29. function GetFilter(AExt: string): string;
  30. function SelectFile(var AFileName: string; const AExt: string): Boolean;
  31. function SaveFile(var FileName: string; const AExt: string): Boolean;
  32. function SelectOutputDirectory(const ATitle: string; var ADirectory: string;
  33. AParentHandle: THandle = 0; AHasNewFolderBtn: Boolean = True): Boolean;
  34. function FixPathByAppPath(AFileName: string): string;
  35. function BrowseFolder(var APath: string; const ATitle: string;
  36. AParentHandle: THandle; AHasNewFolderBtn: Boolean = True): Boolean;
  37. {CheckStrings}
  38. function CheckPeg(const AStr: string): Boolean;
  39. function CheckValidPassword(APassword: string): Boolean;
  40. function ValidInteger(var AKey: Char): Boolean;
  41. {MergeStrings}
  42. function MergeRelaBGL(const ABGLCode1, ABGLCode2: string): string;
  43. procedure MergeRelaBGLAndNum(var ABGLCode1, ABGLNum1: string; const ABGLCode2, ABGLNum2: string);
  44. {CodeTransform}
  45. function B_CodeToIndexCode(const AB_Code: string): string;
  46. function ChinessNum(const ADigitNum: Integer): string;
  47. {Compare Code}
  48. //function CompareCodeWithChar(const ACode1, ACode2: string): Integer;
  49. {Tree Relative}
  50. function CreateTree: TZjIDTree;
  51. procedure DisConnectTree(ATree: TZjIDTree);
  52. procedure ConnectTree(ATree: TZjIDTree; ADataset: TDataSet);
  53. procedure InitGridHead(AGridDBA: TZjGridDBA; AGrid: TZJGrid);
  54. {Generate Name/Directory/Path}
  55. function GetTempFileDir: string;
  56. function GetTempFilePath: string;
  57. function GetTempName(ALength: Integer = 8): string;
  58. function GetTempFileName: string;
  59. function GenerateTempFolder(AGeneratePath: string): string;
  60. function GetNewGUIDFileName(const AGeneratePath: string): string;
  61. {Progress bar Control}
  62. procedure UpdateSysProgress(APosition: Integer; const AHint: string);
  63. procedure UpdateProgress(APosition: Integer; const AHint: string);
  64. procedure DisableSysProgress;
  65. procedure EnableSysProgress;
  66. {Interface RePaint Control}
  67. procedure BeginUpdateWindow(AHandle: THandle);
  68. procedure EndUpdateWindow(AHandle: THandle);
  69. {Zip}
  70. procedure ZipFolder(AFileFolder, AFileName: string);
  71. procedure UnZipFile(AFileName, AFileFolder: string);
  72. {Copy By Stream}
  73. procedure CopyFileByStream(const ASourceFile, ADestFile: string);
  74. // Add by chenshilong, 2014-04-11
  75. function GetVersion(APartCount: Integer = 4): string;
  76. function ExtractFileNameWithoutExt(const AFileName: string): string;
  77. function ShortText(AText: string; AWidth: Integer): string; // 文本缩略显示
  78. function CustomWidthText(AText: string; AWidth: Integer): string;
  79. function ReplaceCharsForJson(AText: string): string; // 替换Json文本中的特殊字符
  80. function RecoverCharsFromJson(AText: string): string; // 下载得到的Json文本恢复成用户需要的文本
  81. procedure FindFiles(APath, AExtName: string; AFileList: TStrings);
  82. function DeleteFolder(const FolderStr: string): Boolean;
  83. function HasExt(const AFileName: string): Boolean;
  84. function CopyFolder(const SrcFolder, DstFolder: string): Boolean;
  85. function FileCount(APath: string): Integer;
  86. implementation
  87. uses
  88. SysUtils, dxBar, MainFrm, ConstUnit, Globals, StdCtrls, ShellAPI,
  89. ScUtils;
  90. var
  91. SysProgressDisabled: Boolean;
  92. {RoundTo}
  93. function QuantityRoundTo(AValue: Double): Double;
  94. begin
  95. if Assigned(OpenProjectManager.CurProjectData) then
  96. Result := ScRoundTo(AValue, -OpenProjectManager.CurProjectData.ProjProperties.QuantityDigit)
  97. else
  98. Result := ScRoundTo(AValue, iQuantityDigit);
  99. end;
  100. function PriceRoundTo(AValue: Double): Double;
  101. begin
  102. if Assigned(OpenProjectManager.CurProjectData) then
  103. Result := ScRoundTo(AValue, -OpenProjectManager.CurProjectData.ProjProperties.PriceDigit)
  104. else
  105. Result := ScRoundTo(AValue, iPriceDigit);
  106. end;
  107. function TotalPriceRoundTo(AValue: Double): Double;
  108. begin
  109. if Assigned(OpenProjectManager.CurProjectData) then
  110. Result := ScRoundTo(AValue, -OpenProjectManager.CurProjectData.ProjProperties.TotalPriceDigit)
  111. else
  112. Result := ScRoundTo(AValue, iTotalPriceDigit);
  113. end;
  114. {Interface Control}
  115. procedure AlignControl(AControl, AParent: TWinControl; AAlign: TAlign);
  116. begin
  117. if Assigned(AControl) then
  118. begin
  119. if Assigned(AControl.Parent) then
  120. AControl.Parent.RemoveControl(AControl);
  121. AControl.Parent := AParent;
  122. AControl.Align := AAlign;
  123. end;
  124. end;
  125. procedure SetDxBtnAction(AAction: TAction; ADxBtn: TObject);
  126. begin
  127. if Assigned(ADxBtn) then
  128. if ADxBtn is TdxBarButton then
  129. TdxBarButton(ADxBtn).Action := AAction;
  130. end;
  131. {Message}
  132. procedure WarningMessage(const AMsg: string);
  133. begin
  134. MessageBox(Application.Handle, PChar(AMsg), PChar('警告'), MB_OK or MB_ICONWARNING);
  135. Application.ProcessMessages;
  136. end;
  137. procedure ErrorMessage(const AMsg: string);
  138. begin
  139. MessageBox(Application.Handle, PChar(AMsg), PChar('错误'), MB_OK or MB_ICONERROR);
  140. Application.ProcessMessages;
  141. end;
  142. function QuestMessage(const AMsg: string): Boolean;
  143. begin
  144. Result := MessageBox(Application.Handle, PChar(AMsg), PChar('询问'), MB_OKCANCEL or MB_ICONQUESTION) = IDOK;
  145. Application.ProcessMessages;
  146. end;
  147. procedure DataSetErrorMessage(var Allow: Boolean; const AMsg: string);
  148. begin
  149. Allow := False;
  150. ErrorMessage(AMsg);
  151. end;
  152. {Get Common Path}
  153. function GetAppFilePath: string;
  154. begin
  155. Result := ExtractFilePath(ParamStr(0));
  156. end;
  157. function GetMyProjectsFilePath: string;
  158. begin
  159. Result := GetAppFilePath + '我的项目\';
  160. end;
  161. function GetEmptyDataBaseFileName: string;
  162. begin
  163. Result := GetAppFilePath + 'Data\Base.dat';
  164. end;
  165. function GetTemplateBillsFileName: string;
  166. begin
  167. Result := GetAppFilePath + 'Data\Template.xls';
  168. end;
  169. function GetTemplateXlsFileName: string;
  170. begin
  171. Result := GetAppFilePath + 'Data\Basic.xls';
  172. end;
  173. function GetBackupFilePath: string;
  174. begin
  175. Result := GetAppFilePath + 'TenderBackup\';
  176. end;
  177. function GetReportTemplatePath: string;
  178. begin
  179. Result := GetAppFilePath + 'ReportTemplates\';
  180. end;
  181. {Select & Save File Choose}
  182. function GetFilter(AExt: string): string;
  183. begin
  184. if AExt = '' then
  185. Result := '所有文件(*.*)|*.*'
  186. else
  187. begin
  188. if AExt[1] <> '.' then
  189. AExt := '.' + AExt;
  190. Result := Format('(*%s)|*%s', [AExt, AExt]);
  191. end;
  192. end;
  193. function SelectFile(var AFileName: string; const AExt: string): Boolean;
  194. var
  195. odFile: TOpenDialog;
  196. begin
  197. odFile := TOpenDialog.Create(nil);
  198. try
  199. odFile.Filter := GetFilter(AExt);
  200. if odFile.Execute then
  201. begin
  202. Application.ProcessMessages;
  203. AFileName := odFile.FileName;
  204. Result := True;
  205. end
  206. else
  207. Result := False;
  208. finally
  209. odFile.Free;
  210. end;
  211. end;
  212. function SaveFile(var FileName: string; const AExt: string): Boolean;
  213. var
  214. sdFile: TSaveDialog;
  215. begin
  216. sdFile := TSaveDialog.Create(nil);
  217. try
  218. sdFile.FileName := FileName;
  219. sdFile.DefaultExt := AExt;
  220. sdFile.Filter := GetFilter(AExt);
  221. Result := sdFile.Execute;
  222. if Result then
  223. FileName := sdFile.FileName;
  224. Application.ProcessMessages;
  225. finally
  226. sdFile.Free;
  227. end;
  228. end;
  229. function SelectOutputDirectory(const ATitle: string; var ADirectory: string;
  230. AParentHandle: THandle; AHasNewFolderBtn: Boolean): Boolean;
  231. var
  232. pID: PItemIDList;
  233. bInfo: TBrowseInfo;
  234. AHandle: THandle;
  235. PStr: array[0..1023] of Char;
  236. sPath: string;
  237. function BFCallBack(Hwnd: HWND; uMsg: UINT; lParam, lpData: LPARAM): Integer; stdcall;
  238. begin
  239. if uMsg = BFFM_INITIALIZED then
  240. begin
  241. SendMessage(Hwnd, BFFM_SETSELECTION, 1, lpData);
  242. end;
  243. Result := 0;
  244. end;
  245. begin
  246. Result := False;
  247. if AParentHandle = 0 then
  248. AHandle := Screen.ActiveForm.Handle
  249. else
  250. AHandle := AParentHandle;
  251. if ADirectory = '' then
  252. sPath := GetAppFilePath
  253. else
  254. sPath := ADirectory;
  255. with bInfo do
  256. begin
  257. hwndOwner := AParentHandle;
  258. iImage := 0;
  259. lParam := Integer(PChar(sPath));
  260. lpszTitle := PChar(ATitle);
  261. pidlRoot := nil;
  262. pszDisplayName := nil;
  263. if AHasNewFolderBtn then
  264. ulFlags := BIF_RETURNONLYFSDIRS or BIF_USENEWUI
  265. else
  266. ulFlags := BIF_RETURNONLYFSDIRS;
  267. lpfn := @BFCallBack;
  268. end;
  269. pID := SHBrowseForFolder(bInfo);
  270. if pID <> nil then
  271. begin
  272. SHGetPathFromIDList(pID, PStr);
  273. ADirectory := StrPas(PStr);
  274. if (ADirectory <> '') and (ADirectory[Length(ADirectory)] <> '\') then
  275. ADirectory := ADirectory + '\';
  276. Result := True;
  277. end;
  278. end;
  279. function FixPathByAppPath(AFileName: string): string;
  280. begin
  281. Result := AFileName;
  282. if AnsiPos(':\', Result) = 0 then
  283. begin
  284. if (Result <> '') and (Result[1] = '\') then
  285. Delete(Result, 1, 1);
  286. Result := ExtractFilePath(Application.ExeName) + Result;
  287. end;
  288. end;
  289. var
  290. PathStr: string;
  291. function BrowseFolder(var APath: string; const ATitle: string; AParentHandle: THandle;
  292. AHasNewFolderBtn: Boolean): Boolean;
  293. function BFCallBackFunc(hwnd: HWND; uMsg: UINT; lParam: LPARAM; lpData: LPARAM): Integer; stdcall;
  294. begin
  295. Result := 0;
  296. case uMsg of
  297. BFFM_INITIALIZED : // 初始化设置目录。
  298. begin
  299. SendMessage(Hwnd,BFFM_SETSELECTION,-1,Integer(PathStr));
  300. end;
  301. end;
  302. end;
  303. var
  304. pID: PItemIDList;
  305. bInfo: TBrowseInfo;
  306. PStr: array[0..1023] of Char;
  307. sPath: string;
  308. Hdl: THandle;
  309. begin
  310. Result := False;
  311. PathStr := '';
  312. if AParentHandle = 0 then
  313. Hdl := Screen.ActiveForm.Handle
  314. else
  315. Hdl := AParentHandle;
  316. sPath := FixPathByAppPath(APath);
  317. if DirectoryExists(sPath) then
  318. PathStr := sPath;
  319. bInfo.hwndOwner := Hdl;
  320. bInfo.iImage := 0;
  321. bInfo.lParam := 0;
  322. bInfo.lpszTitle := PChar(ATitle);
  323. bInfo.pidlRoot := nil;
  324. bInfo.pszDisplayName := nil;
  325. if (not AHasNewFolderBtn) then
  326. bInfo.ulFlags := BIF_RETURNONLYFSDIRS
  327. else
  328. bInfo.ulFlags := BIF_RETURNONLYFSDIRS or BIF_USENEWUI;
  329. bInfo.lpfn := @BFCallBackFunc;
  330. pID := SHBrowseForFolder(bInfo);
  331. if pID <> nil then
  332. begin
  333. SHGetPathFromIDList(pID,pStr);
  334. APath := StrPas(pStr);
  335. if (APath <> '') and (APath[Length(APath)] <> '\') then
  336. APath := APath + '\';
  337. Result := True;
  338. end;
  339. end;
  340. {CheckStrings}
  341. function CheckPeg(const AStr: string): Boolean;
  342. function GetPosition(const AName, AStr, AStrSpare: string): Integer;
  343. begin
  344. Result := Pos(AStr, AName);
  345. if Result = 0 then
  346. Result := Pos(AStrSpare, AName);
  347. end;
  348. var
  349. iPosK, iPosPlus: Integer;
  350. fNum: Double;
  351. begin
  352. Result := False;
  353. iPosK := GetPosition(AStr, 'K', 'k');
  354. iPosPlus := GetPosition(AStr, '+', '+');
  355. if (iPosK = 0) or (iPosPlus = 0) or (iPosPlus < iPosK) then Exit;
  356. Result := TryStrToFloat(Copy(AStr, iPosK + 1, iPosPlus - iPosK - 1), fNum);
  357. end;
  358. function CheckValidPassword(APassword: string): Boolean;
  359. var
  360. iIndex, iLength: Integer;
  361. begin
  362. Result := True;
  363. if APassword = '' then Exit;
  364. iIndex := 1;
  365. iLength := Length(APassword);
  366. Result := (iLength >= 6) and (iLength <= 16);
  367. while Result and (iIndex < iLength) do
  368. begin
  369. Result := APassword[iIndex] in ['A'..'Z', 'a'..'z', '0'..'9'];
  370. Inc(iIndex);
  371. end;
  372. end;
  373. function ValidInteger(var AKey: Char): Boolean;
  374. begin
  375. if AKey in ['+', '-', '0'..'9', #8, #13, #35, #36,
  376. #37, #38, #39, #40, #46] then
  377. begin
  378. Result := True;
  379. end
  380. else
  381. begin
  382. AKey := #0;
  383. Result := False;
  384. end;
  385. end;
  386. {MergeStrings}
  387. function MergeRelaBGL(const ABGLCode1, ABGLCode2: string): string;
  388. var
  389. sgs1, sgs2: TStrings;
  390. i1, i2: Integer;
  391. bExist: Boolean;
  392. begin
  393. Result := ABGLCode1;
  394. sgs1 := TStringList.Create;
  395. sgs2 := TStringList.Create;
  396. try
  397. sgs1.Delimiter := ';';
  398. sgs2.Delimiter := ';';
  399. sgs1.DelimitedText := ABGLCode1;
  400. sgs2.DelimitedText := ABGLCode2;
  401. for i2 := 0 to sgs2.Count - 1 do
  402. begin
  403. bExist := False;
  404. for i1 := 0 to sgs1.Count - 1 do
  405. if SameText(sgs2[i2], sgs1[i1]) then
  406. begin
  407. bExist := True;
  408. Break;
  409. end;
  410. if not bExist then
  411. sgs1.Add(sgs2[i2]);
  412. end;
  413. Result := sgs1.DelimitedText;
  414. finally
  415. sgs1.Free;
  416. sgs2.Free;
  417. end;
  418. end;
  419. procedure MergeRelaBGLAndNum(var ABGLCode1, ABGLNum1: string; const ABGLCode2, ABGLNum2: string);
  420. var
  421. sgsC1, sgsC2, sgsN1, sgsN2: TStrings;
  422. i1, i2: Integer;
  423. bExist: Boolean;
  424. begin
  425. sgsC1 := TStringList.Create;
  426. sgsC2 := TStringList.Create;
  427. sgsN1 := TStringList.Create;
  428. sgsN2 := TStringList.Create;
  429. try
  430. sgsC1.Delimiter := ';';
  431. sgsC2.Delimiter := ';';
  432. sgsC1.DelimitedText := ABGLCode1;
  433. sgsC2.DelimitedText := ABGLCode2;
  434. sgsN1.Delimiter := ';';
  435. sgsN2.Delimiter := ';';
  436. sgsN1.DelimitedText := ABGLNum1;
  437. sgsN2.DelimitedText := ABGLNum2;
  438. for i2 := 0 to sgsC2.Count - 1 do
  439. begin
  440. bExist := False;
  441. for i1 := 0 to sgsC1.Count - 1 do
  442. if SameText(sgsC2[i2], sgsC1[i1]) then
  443. begin
  444. bExist := True;
  445. Break;
  446. end;
  447. if bExist then
  448. begin
  449. sgsN1[i1] := FloatToStr(StrToFloatDef(sgsN1[i1], 0) + StrToFloatDef(sgsN2[i2], 0))
  450. end
  451. else
  452. begin
  453. sgsC1.Add(sgsC2[i2]);
  454. sgsN1.Add(sgsN2[i2]);
  455. end;
  456. end;
  457. ABGLCode1 := sgsC1.DelimitedText;
  458. ABGLNum1 := sgsN1.DelimitedText;
  459. finally
  460. sgsC1.Free;
  461. sgsC2.Free;
  462. sgsN1.Free;
  463. sgsN2.Free;
  464. end;
  465. end;
  466. function B_CodeToIndexCode(const AB_Code: string): string;
  467. var
  468. sgs: TStrings;
  469. i, iNum, iError: Integer;
  470. sError: string;
  471. begin
  472. sgs := TStringList.Create;
  473. try
  474. Result := '';
  475. sgs.Delimiter := '-';
  476. sgs.DelimitedText := AB_Code;
  477. for i := 0 to sgs.Count - 1 do
  478. begin
  479. Val(sgs[i], iNum, iError);
  480. if iError = 0 then
  481. sError := ''
  482. else
  483. sError := Copy(sgs[i], iError, Length(sgs[i])-iError+1);
  484. if iError = 0 then
  485. Result := Result + Format('%4d', [iNum]) + Format('%-3s', [sError])
  486. else if iNum = 0 then
  487. Result := Result + '9999' + Format('%3s', [sError])
  488. else
  489. Result := Result + Format('%4d', [iNum]) + Format('%-3s', [sError]);
  490. end;
  491. finally
  492. sgs.Free;
  493. end;
  494. end;
  495. function ChinessNum(const ADigitNum: Integer): string;
  496. function TransChineseNum(const ANum, AZeroNum: Integer): string;
  497. begin
  498. Result := '';
  499. case ANum of
  500. 1: if AZeroNum <> 1 then Result := '一';
  501. 2: Result := '二';
  502. 3: Result := '三';
  503. 4: Result := '四';
  504. 5: Result := '五';
  505. 6: Result := '六';
  506. 7: Result := '七';
  507. 8: Result := '八';
  508. 9: Result := '九';
  509. end;
  510. if (Result = '') and ((AZeroNum <> 1) or (ANum = 0)) then Exit;
  511. case AZeroNum of
  512. 0: Result := Result;
  513. 1: Result := Result + '十';
  514. 2: Result := Result + '百';
  515. 3: Result := Result + '千';
  516. 4: Result := Result + '万';
  517. end;
  518. end;
  519. var
  520. iBai, iShi, iGe: Integer;
  521. begin
  522. Result := '';
  523. if (ADigitNum < 0) and (ADigitNum > 10000) then Exit;
  524. iBai := ADigitNum div 100;
  525. iShi := (ADigitNum mod 100) div 10;
  526. iGe := (ADigitNum mod 100) mod 10;
  527. Result := TransChineseNum(iBai, 2) + TransChineseNum(iShi, 1) + TransChineseNum(iGe, 0);
  528. end;
  529. {Tree Relative}
  530. function CreateTree: TZjIDTree;
  531. begin
  532. Result := TZjIDTree.Create;
  533. Result.KeyFieldName := 'ID';
  534. Result.ParentFieldName := 'ParentID';
  535. Result.NextSiblingFieldName := 'NextSiblingID';
  536. Result.AutoCreateKeyID := True;
  537. Result.AutoExpand := True;
  538. end;
  539. procedure DisConnectTree(ATree: TZjIDTree);
  540. begin
  541. ATree.DataSet := nil;
  542. ATree.Active := False;
  543. end;
  544. procedure ConnectTree(ATree: TZjIDTree; ADataset: TDataSet);
  545. begin
  546. ATree.DataSet := ADataset;
  547. ATree.Active := True;
  548. end;
  549. procedure InitGridHead(AGridDBA: TZjGridDBA; AGrid: TZJGrid);
  550. var
  551. I: Integer;
  552. begin
  553. for I := 0 to AGridDBA.Columns.Count - 1 do
  554. AGrid.Cells[I + 1, 0].Text := AGridDBA.Columns[I].Title.Caption;
  555. end;
  556. {Generate Name/Path}
  557. function GetTempFileDir: string;
  558. var
  559. TempPath: string;
  560. begin
  561. TempPath := GetEnvironmentVariable('TMP');
  562. if TempPath = '' then
  563. TempPath := GetEnvironmentVariable('TEMP');
  564. if TempPath = '' then
  565. begin
  566. if not DirectoryExists(ExtractFileDir(ParamStr(0)) + '\Temp') then
  567. CreateDir(ExtractFileDir(ParamStr(0)) + '\Temp');
  568. TempPath := ExtractFileDir(ParamStr(0)) + '\Temp';
  569. end;
  570. Result := TempPath;
  571. end;
  572. function GetTempFilePath: string;
  573. begin
  574. Result := GetTempFileDir + '\';
  575. end;
  576. function GetTempName(ALength: Integer): string;
  577. const
  578. CodedBuf: array[0..35] of Char = ('0', '1', '2', '3', '4', '5',
  579. '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I',
  580. 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V',
  581. 'W', 'X', 'Y', 'Z');
  582. var
  583. Temp: string;
  584. Num: Integer;
  585. begin
  586. Randomize;
  587. Temp := '';
  588. while Length(Temp) < ALength do
  589. begin
  590. Num := Random(37);
  591. If Num <> 36 Then
  592. Temp := Temp + CodedBuf[Num]; // 0..35
  593. end;
  594. Result := Temp;
  595. end;
  596. function GetTempFileName: string;
  597. var
  598. TempExt: string;
  599. begin
  600. Result := GetTempFilePath + GetTempName;
  601. TempExt := '.' + GetTempName(3);
  602. while SameText(TempExt, '.mdb') or SameText(TempExt, '.db') or
  603. SameText(TempExt, '.ldb') do
  604. TempExt := '.' + GetTempName(3);
  605. Result := Result + TempExt;
  606. while FileExists(Result) do
  607. begin
  608. Result := GetTempFilePath + GetTempName;
  609. TempExt := '.' + GetTempName(3);
  610. while SameText(TempExt, '.mdb') or SameText(TempExt, '.db') or
  611. SameText(TempExt, '.ldb') do
  612. TempExt := '.' + GetTempName(3);
  613. Result := Result + TempExt;
  614. end;
  615. end;
  616. function GenerateTempFolder(AGeneratePath: string): string;
  617. begin
  618. Result := AGeneratePath + GetTempName;
  619. while DirectoryExists(Result) do
  620. Result := AGeneratePath + GetTempName;
  621. CreateDirectoryInDeep(Result);
  622. end;
  623. function GetNewGUIDFileName(const AGeneratePath: string): string;
  624. var
  625. gFile: TGUID;
  626. begin
  627. repeat
  628. CreateGUID(gFile);
  629. Result := AGeneratePath + GUIDToString(gFile);
  630. until not FileExists(Result);
  631. end;
  632. {Progress bar Control}
  633. procedure UpdateSysProgress(APosition: Integer; const AHint: string);
  634. begin
  635. if not SysProgressDisabled then
  636. UpdateProgress(APosition, AHint);
  637. end;
  638. procedure UpdateProgress(APosition: Integer; const AHint: string);
  639. begin
  640. MainForm.UpdateProgress(APosition, AHint);
  641. end;
  642. procedure DisableSysProgress;
  643. begin
  644. SysProgressDisabled := True;
  645. end;
  646. procedure EnableSysProgress;
  647. begin
  648. SysProgressDisabled := False;
  649. end;
  650. {Interface RePaint Control}
  651. procedure BeginUpdateWindow(AHandle: THandle);
  652. begin
  653. SendMessage(AHandle, WM_SETREDRAW, 0, 0);
  654. end;
  655. procedure EndUpdateWindow(AHandle: THandle);
  656. begin
  657. SendMessage(AHandle, WM_SETREDRAW, 1, 0);
  658. end;
  659. {Zip}
  660. procedure ZipFolder(AFileFolder, AFileName: string);
  661. var
  662. vZip: TVCLZip;
  663. begin
  664. vZip := TVCLZip.Create(nil);
  665. try
  666. vZip.FilesList.Clear;
  667. vZip.ZipName := AFileName;
  668. vzip.RootDir := AFileFolder;
  669. vZip.OverwriteMode := Always;
  670. //vZip.AddDirEntriesOnRecurse:=True;
  671. vZip.RelativePaths := True;
  672. //vZip.RecreateDirs := True;
  673. vZip.FilesList.Add(AFileFolder + '\*.*');
  674. vZip.Zip;
  675. finally
  676. vZip.Free;
  677. end;
  678. end;
  679. procedure UnZipFile(AFileName, AFileFolder: string);
  680. var
  681. vUnZip: TVCLZip;
  682. begin
  683. vUnZip := TVCLZip.Create(nil);
  684. try
  685. vUnZip.FilesList.Clear;
  686. vUnZip.ZipName := AFileName;
  687. vUnZip.ReadZip;
  688. vUnZip.DestDir := AFileFolder;
  689. vUnZip.OverwriteMode := Always;
  690. vUnZip.RecreateDirs := True;
  691. vUnZip.RelativePaths := True;
  692. vUnZip.DoAll := True;
  693. vUnZip.FilesList.Add('*.*');
  694. vUnZip.UnZip;
  695. finally
  696. vUnZip.Free;
  697. end;
  698. end;
  699. {Copy By Stream}
  700. procedure CopyFileByStream(const ASourceFile, ADestFile: string);
  701. var
  702. MS: TMemoryStream;
  703. begin
  704. MS := TMemoryStream.Create;
  705. try
  706. MS.LoadFromFile(ASourceFile);
  707. if FileExists(ADestFile) then
  708. DeleteFile(ADestFile);
  709. MS.SaveToFile(ADestFile);
  710. finally
  711. MS.Free;
  712. end;
  713. end;
  714. function GetVersion(APartCount: Integer = 4): string;
  715. var
  716. V1, V2, V3, V4: Word;
  717. FInfoSize, FF: Cardinal;
  718. FInfo: Pointer;
  719. FFixed: PVSFIXEDFILEINFO;
  720. begin
  721. FInfoSize := GetFileVersionInfoSize(PChar(Application.ExeName), FF);
  722. FInfo := AllocMem(FInfoSize);
  723. try
  724. GetFileVersionInfo(PChar(Application.ExeName), FF, FInfoSize, FInfo);
  725. VerQueryValue(FInfo, '\', Pointer(FFixed), FInfoSize);
  726. V1 := FFixed.dwFileVersionMS shr 16;
  727. V2 := FFixed.dwFileVersionMS and $FFFF;
  728. V3 := FFixed.dwFileVersionLS shr 16;
  729. V4 := FFixed.dwFileVersionLS and $FFFF;
  730. finally
  731. Dispose(FInfo);
  732. end;
  733. Result := '';
  734. case APartCount of
  735. 1:
  736. Result := Format('%d', [V1]);
  737. 2:
  738. Result := Format('%d.%d', [V1, V2]);
  739. 3:
  740. Result := Format('%d.%d.%d', [V1, V2, V3]);
  741. 4:
  742. Result := Format('%d.%d.%d.%d', [V1, V2, V3, V4]);
  743. end;
  744. end;
  745. function ExtractFileNameWithoutExt(const AFileName: string): string;
  746. var
  747. sFileName, Ext: string;
  748. begin
  749. Result := '';
  750. if AFileName = '' then
  751. Exit;
  752. sFileName := AFileName;
  753. if sFileName[Length(sFileName)] = '\' then
  754. Delete(sFileName, Length(sFileName), 1);
  755. Result := ExtractFileName(sFileName);
  756. Ext := ExtractFileExt(sFileName);
  757. Delete(Result, Length(Result) - Length(Ext) + 1, Length(Ext));
  758. end;
  759. function ShortText(AText: string; AWidth: Integer): string;
  760. var vMM: TMemo;
  761. begin
  762. if Trim(AText) = '' then
  763. begin
  764. Result := '';
  765. Exit;
  766. end;
  767. vMM := TMemo.Create(nil);
  768. try
  769. vMM.Visible := False;
  770. vMM.WordWrap := True;
  771. vMM.parent := Application.MainForm;
  772. vMM.Width := AWidth - 10; // 10像素留给3个小点
  773. vMM.Text := AText;
  774. if vMM.Lines.Count > 1 then
  775. Result := vMM.Lines[0] + '...'
  776. else
  777. Result := AText;
  778. finally
  779. vMM.Free;
  780. end;
  781. end;
  782. function CustomWidthText(AText: string; AWidth: Integer): string;
  783. var vMM: TMemo;
  784. i: Integer;
  785. begin
  786. if Trim(AText) = '' then
  787. begin
  788. Result := '';
  789. Exit;
  790. end;
  791. vMM := TMemo.Create(nil);
  792. try
  793. vMM.Visible := False;
  794. vMM.WordWrap := True;
  795. vMM.parent := Application.MainForm;
  796. vMM.Width := AWidth;
  797. vMM.Text := AText;
  798. for i := 0 to vMM.Lines.Count - 1 do
  799. begin
  800. if i = 0 then
  801. Result := vMM.Lines[i]
  802. else
  803. Result := Result + #10#13 + vMM.Lines[i];
  804. end;
  805. finally
  806. vMM.Free;
  807. end;
  808. end;
  809. function ReplaceCharsForJson(AText: string): string;
  810. const
  811. BefChar: array [0..7] of Char = ('{', '}', ',', ':', '"', '[', ']', '%');
  812. AftChar: array [0..7] of string = ('{', '}', ',', ':', '"', '【', '】', '♂');
  813. var I: Integer;
  814. begin
  815. AText := Trim(AText);
  816. Result := AText;
  817. if AText = '' then Exit;
  818. for I := low(BefChar) to High(BefChar) do
  819. begin
  820. if Pos(BefChar[I], AText) > 0 then
  821. AText := StringReplace(AText, BefChar[I], AftChar[I], [rfReplaceAll]);
  822. end;
  823. Result := AText;
  824. end;
  825. function RecoverCharsFromJson(AText: string): string;
  826. const
  827. BefStr: array [0..1] of string = ('♂', '\r\n');
  828. AftStr: array [0..1] of string = ('%', '');
  829. var I: Integer;
  830. begin
  831. AText := Trim(AText);
  832. Result := AText;
  833. if AText = '' then Exit;
  834. for I := low(BefStr) to High(BefStr) do
  835. begin
  836. if Pos(BefStr[I], AText) > 0 then
  837. AText := StringReplace(AText, BefStr[I], AftStr[I], [rfReplaceAll]);
  838. end;
  839. Result := AText;
  840. end;
  841. procedure FindFiles(APath, AExtName: string; AFileList: TStrings);
  842. var
  843. SRec: TSearchRec;
  844. retval: Integer;
  845. begin
  846. AFileList.Clear;
  847. retval := FindFirst(APath + AExtName, faAnyFile, sRec);
  848. try
  849. while retval = 0 do
  850. begin
  851. if (SRec.Attr and faDirectory) = 0 then
  852. AFileList.Add(Srec.Name);
  853. retval := FindNext(SRec);
  854. end;
  855. finally
  856. FindClose(SRec);
  857. end;
  858. end;
  859. function DeleteFolder(const FolderStr: string): Boolean;
  860. var
  861. fos: SHFILEOPSTRUCT;
  862. begin
  863. ZeroMemory(@fos, SizeOf(fos));
  864. fos.Wnd := HWND_DESKTOP;
  865. fos.wFunc := FO_DELETE;
  866. fos.fFlags := FOF_SILENT OR FOF_ALLOWUNDO OR FOF_NOCONFIRMATION;
  867. fos.pFrom := PChar(FolderStr + #0);
  868. Result := SHFileOperation(fos) <> 0;
  869. end;
  870. function HasExt(const AFileName: string): Boolean;
  871. begin
  872. Result := ExtractFileExt(AFileName) <> '';
  873. end;
  874. function CopyFolder(const SrcFolder, DstFolder: string): Boolean;
  875. var
  876. fos: SHFILEOPSTRUCT;
  877. begin
  878. ZeroMemory(@fos, SizeOf(fos));
  879. fos.Wnd := HWND_DESKTOP;
  880. fos.wFunc := FO_COPY;
  881. fos.fFlags := FOF_SILENT OR FOF_ALLOWUNDO;
  882. fos.pFrom := PChar(SrcFolder + #0);
  883. fos.pTo := PChar(DstFolder + #0);
  884. Result := SHFileOperation(fos) <> 0;
  885. end;
  886. function FileCount(APath: string): Integer;
  887. var
  888. vSR: TSearchRec;
  889. iRetval: Integer;
  890. vSL: TStringList;
  891. begin
  892. vSL := TStringList.Create;
  893. iRetval := FindFirst(APath + '*.*', faAnyFile, vSR);
  894. try
  895. while iRetval = 0 do
  896. begin
  897. if (vSR.Attr and faDirectory) = 0 then
  898. vSL.Add(vSR.Name);
  899. iRetval := FindNext(vSR);
  900. end;
  901. Result := vSL.Count;
  902. finally
  903. FindClose(vSR);
  904. vSL.Free;
  905. end;
  906. end;
  907. end.