UtilMethods.pas 25 KB

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