home *** CD-ROM | disk | FTP | other *** search
/ Chip 2002 June / Chip_2002-06_cd1.bin / zkuste / delphi / kolekce / d6 / rxlibsetup.exe / {app} / units / APPUTILS.PAS < prev    next >
Encoding:
Pascal/Delphi Source File  |  2002-02-19  |  26.3 KB  |  887 lines

  1. {*******************************************************}
  2. {                                                       }
  3. {         Delphi VCL Extensions (RX)                    }
  4. {                                                       }
  5. {         Copyright (c) 2001,2002 SGB Software          }
  6. {         Copyright (c) 1997, 1998 Fedor Koshevnikov,   }
  7. {                        Igor Pavluk and Serge Korolev  }
  8. {                                                       }
  9. {*******************************************************}
  10.  
  11.  
  12. unit AppUtils;
  13.  
  14. interface
  15.  
  16. {$I RX.INC}
  17.  
  18. uses Windows, Registry, RTLConsts, Classes, Controls, Forms, IniFiles, Grids, VCLUtils;
  19.  
  20. function GetDefaultSection(Component: TComponent): string;
  21. procedure GetDefaultIniData(Control: TControl; var IniFileName,
  22.   Section: string {$IFDEF WIN32}; UseRegistry: Boolean {$ENDIF});
  23. function GetDefaultIniName: string;
  24.  
  25. type
  26.   TOnGetDefaultIniName = function: string;
  27.  
  28. const
  29.   OnGetDefaultIniName: TOnGetDefaultIniName = nil;
  30.  
  31. {$IFDEF WIN32}
  32. var
  33.   DefCompanyName: string = '';
  34.   RegUseAppTitle: Boolean = False;
  35.  
  36. function GetDefaultIniRegKey: string;
  37. {$ENDIF}
  38.  
  39. function FindForm(FormClass: TFormClass): TForm;
  40. function FindShowForm(FormClass: TFormClass; const Caption: string): TForm;
  41. function ShowDialog(FormClass: TFormClass): Boolean;
  42. function InstantiateForm(FormClass: TFormClass; var Reference): TForm;
  43.  
  44. {$IFDEF WIN32}
  45. procedure SaveFormPlacement(Form: TForm; const IniFileName: string;
  46.   UseRegistry: Boolean);
  47. procedure RestoreFormPlacement(Form: TForm; const IniFileName: string;
  48.   UseRegistry: Boolean);
  49. procedure WriteFormPlacementReg(Form: TForm; IniFile: TRegIniFile;
  50.   const Section: string);
  51. procedure ReadFormPlacementReg(Form: TForm; IniFile: TRegIniFile;
  52.   const Section: string; LoadState, LoadPosition: Boolean);
  53. procedure SaveMDIChildrenReg(MainForm: TForm; IniFile: TRegIniFile);
  54. procedure RestoreMDIChildrenReg(MainForm: TForm; IniFile: TRegIniFile);
  55. procedure RestoreGridLayoutReg(Grid: TCustomGrid; IniFile: TRegIniFile);
  56. procedure SaveGridLayoutReg(Grid: TCustomGrid; IniFile: TRegIniFile);
  57. {$ELSE}
  58. procedure SaveFormPlacement(Form: TForm; const IniFileName: string);
  59. procedure RestoreFormPlacement(Form: TForm; const IniFileName: string);
  60. {$ENDIF WIN32}
  61.  
  62. procedure WriteFormPlacement(Form: TForm; IniFile: TIniFile;
  63.   const Section: string);
  64. procedure ReadFormPlacement(Form: TForm; IniFile: TIniFile;
  65.   const Section: string; LoadState, LoadPosition: Boolean);
  66. procedure SaveMDIChildren(MainForm: TForm; IniFile: TIniFile);
  67. procedure RestoreMDIChildren(MainForm: TForm; IniFile: TIniFile);
  68. procedure RestoreGridLayout(Grid: TCustomGrid; IniFile: TIniFile);
  69. procedure SaveGridLayout(Grid: TCustomGrid; IniFile: TIniFile);
  70.  
  71. function GetUniqueFileNameInDir(const Path, FileNameMask: string): string;
  72.  
  73. function StrToIniStr(const Str: string): string;
  74. function IniStrToStr(const Str: string): string;
  75.  
  76. function IniReadString(IniFile: TObject; const Section, Ident,
  77.   Default: string): string;
  78. procedure IniWriteString(IniFile: TObject; const Section, Ident,
  79.   Value: string);
  80. function IniReadInteger(IniFile: TObject; const Section, Ident: string;
  81.   Default: Longint): Longint;
  82. procedure IniWriteInteger(IniFile: TObject; const Section, Ident: string;
  83.   Value: Longint);
  84. function IniReadBool(IniFile: TObject; const Section, Ident: string;
  85.   Default: Boolean): Boolean;
  86. procedure IniWriteBool(IniFile: TObject; const Section, Ident: string;
  87.   Value: Boolean);
  88. procedure IniReadSections(IniFile: TObject; Strings: TStrings);
  89. procedure IniEraseSection(IniFile: TObject; const Section: string);
  90. procedure IniDeleteKey(IniFile: TObject; const Section, Ident: string);
  91.  
  92. {$IFDEF WIN32}
  93. procedure AppBroadcast(Msg, wParam: Longint; lParam: Longint);
  94. {$ELSE}
  95. procedure AppBroadcast(Msg, wParam: Word; lParam: Longint);
  96. {$ENDIF WIN32}
  97.  
  98. procedure AppTaskbarIcons(AppOnly: Boolean);
  99.  
  100. { Internal using utilities }
  101.  
  102. procedure InternalSaveGridLayout(Grid: TCustomGrid; IniFile: TObject;
  103.   const Section: string);
  104. procedure InternalRestoreGridLayout(Grid: TCustomGrid; IniFile: TObject;
  105.   const Section: string);
  106. procedure InternalSaveMDIChildren(MainForm: TForm; IniFile: TObject);
  107. procedure InternalRestoreMDIChildren(MainForm: TForm; IniFile: TObject);
  108.  
  109. implementation
  110.  
  111. uses SysUtils, Messages, Consts, rxStrUtils, FileUtil, Placemnt;
  112.  
  113. function GetDefaultSection(Component: TComponent): string;
  114. var
  115.   F: TCustomForm;
  116.   Owner: TComponent;
  117. begin
  118.   if Component <> nil then begin
  119.     if Component is TCustomForm then Result := Component.ClassName
  120.     else begin
  121.       Result := Component.Name;
  122.       if Component is TControl then begin
  123.         F := GetParentForm(TControl(Component));
  124.         if F <> nil then Result := F.ClassName + Result
  125.         else begin
  126.           if TControl(Component).Parent <> nil then
  127.             Result := TControl(Component).Parent.Name + Result;
  128.         end;
  129.       end
  130.       else begin
  131.         Owner := Component.Owner;
  132.         if Owner is TForm then
  133.           Result := Format('%s.%s', [Owner.ClassName, Result]);
  134.       end;
  135.     end;
  136.   end
  137.   else Result := '';
  138. end;
  139.  
  140. function GetDefaultIniName: string;
  141. begin
  142.   if Assigned(OnGetDefaultIniName) then
  143.     Result:= OnGetDefaultIniName
  144.   else
  145.     Result := ExtractFileName(ChangeFileExt(Application.ExeName, '.INI'));
  146. end;
  147.  
  148. {$IFDEF WIN32}
  149. function GetDefaultIniRegKey: string;
  150. begin
  151.   if RegUseAppTitle and (Application.Title <> '') then
  152.     Result := Application.Title
  153.   else Result := ExtractFileName(ChangeFileExt(Application.ExeName, ''));
  154.   if DefCompanyName <> '' then
  155.     Result := DefCompanyName + '\' + Result;
  156.   Result := 'Software\' + Result;
  157. end;
  158. {$ENDIF}
  159.  
  160. procedure GetDefaultIniData(Control: TControl; var IniFileName,
  161.   Section: string {$IFDEF WIN32}; UseRegistry: Boolean {$ENDIF});
  162. var
  163.   I: Integer;
  164. begin
  165.   IniFileName := EmptyStr;
  166.   with Control do
  167.     if Owner is TCustomForm then
  168.       for I := 0 to Owner.ComponentCount - 1 do
  169.         if (Owner.Components[I] is TFormPlacement) then begin
  170.           IniFileName := TFormPlacement(Owner.Components[I]).IniFileName;
  171.           Break;
  172.         end;
  173.   Section := GetDefaultSection(Control);
  174.   if IniFileName = EmptyStr then
  175. {$IFDEF WIN32}
  176.     if UseRegistry then IniFileName := GetDefaultIniRegKey
  177.     else
  178. {$ENDIF}
  179.     IniFileName := GetDefaultIniName;
  180. end;
  181.  
  182. function FindForm(FormClass: TFormClass): TForm;
  183. var
  184.   I: Integer;
  185. begin
  186.   Result := nil;
  187.   for I := 0 to Screen.FormCount - 1 do begin
  188.     if Screen.Forms[I] is FormClass then begin
  189.       Result := Screen.Forms[I];
  190.       Break;
  191.     end;
  192.   end;
  193. end;
  194.  
  195. function InternalFindShowForm(FormClass: TFormClass;
  196.   const Caption: string; Restore: Boolean): TForm;
  197. var
  198.   I: Integer;
  199. begin
  200.   Result := nil;
  201.   for I := 0 to Screen.FormCount - 1 do begin
  202.     if Screen.Forms[I] is FormClass then
  203.       if (Caption = '') or (Caption = Screen.Forms[I].Caption) then begin
  204.         Result := Screen.Forms[I];
  205.         Break;
  206.       end;
  207.   end;
  208.   if Result = nil then begin
  209.     Application.CreateForm(FormClass, Result);
  210.     if Caption <> '' then Result.Caption := Caption;
  211.   end;
  212.   with Result do begin
  213.     if Restore and (WindowState = wsMinimized) then WindowState := wsNormal;
  214.     Show;
  215.   end;
  216. end;
  217.  
  218. function FindShowForm(FormClass: TFormClass; const Caption: string): TForm;
  219. begin
  220.   Result := InternalFindShowForm(FormClass, Caption, True);
  221. end;
  222.  
  223. function ShowDialog(FormClass: TFormClass): Boolean;
  224. var
  225.   Dlg: TForm;
  226. begin
  227.   Application.CreateForm(FormClass, Dlg);
  228.   try
  229.     Result := Dlg.ShowModal in [mrOk, mrYes];
  230.   finally
  231.     Dlg.Free;
  232.   end;
  233. end;
  234.  
  235. function InstantiateForm(FormClass: TFormClass; var Reference): TForm;
  236. begin
  237.   if TForm(Reference) = nil then
  238.     Application.CreateForm(FormClass, Reference);
  239.   Result := TForm(Reference);
  240. end;
  241.  
  242. function StrToIniStr(const Str: string): string;
  243. var
  244. {$IFDEF WIN32}
  245.   Buffer: array[0..4095] of Char;
  246. {$ELSE}
  247.   Buffer: array[0..255] of Char;
  248. {$ENDIF}
  249.   B, S: PChar;
  250. begin
  251.   if Length(Str) > SizeOf(Buffer) then
  252.     raise Exception.Create(ResStr(SLineTooLong));
  253. {$IFDEF WIN32}
  254.   S := PChar(Str);
  255. {$ELSE}
  256.   S := StrPAlloc(Str);
  257. {$ENDIF}
  258.   try
  259.     B := Buffer;
  260.     while S^ <> #0 do
  261.       case S^ of
  262.         #13, #10:
  263.           begin
  264.             if (S^ = #13) and (S[1] = #10) then Inc(S)
  265.             else if (S^ = #10) and (S[1] = #13) then Inc(S);
  266.             B^ := '\';
  267.             Inc(B);
  268.             B^ := 'n';
  269.             Inc(B);
  270.             Inc(S);
  271.           end;
  272.       else
  273.         B^ := S^;
  274.         Inc(B);
  275.         Inc(S);
  276.       end;
  277.   finally
  278. {$IFNDEF WIN32}
  279.     StrDispose(S);
  280. {$ENDIF}
  281.   end;
  282.   B^ := #0;
  283.   Result := StrPas(Buffer);
  284. end;
  285.  
  286. function IniStrToStr(const Str: string): string;
  287. var
  288. {$IFDEF WIN32}
  289.   Buffer: array[0..4095] of Char;
  290. {$ELSE}
  291.   Buffer: array[0..255] of Char;
  292. {$ENDIF}
  293.   B, S: PChar;
  294. begin
  295.   if Length(Str) > SizeOf(Buffer) then
  296.     raise Exception.Create(ResStr(SLineTooLong));
  297. {$IFDEF WIN32}
  298.   S := PChar(Str);
  299. {$ELSE}
  300.   S := StrPAlloc(Str);
  301. {$ENDIF}
  302.   try
  303.     B := Buffer;
  304.     while S^ <> #0 do
  305.       if (S[0] = '\') and (S[1] = 'n') then
  306.       begin
  307.         B^ := #13;
  308.         Inc(B);
  309.         B^ := #10;
  310.         Inc(B);
  311.         Inc(S);
  312.         Inc(S);
  313.       end
  314.       else
  315.       begin
  316.         B^ := S^;
  317.         Inc(B);
  318.         Inc(S);
  319.       end;
  320.   finally
  321. {$IFNDEF WIN32}
  322.     StrDispose(S);
  323. {$ENDIF}
  324.   end;
  325.   B^ := #0;
  326.   Result := StrPas(Buffer);
  327. end;
  328.  
  329. const
  330. { The following strings should not be localized }
  331.   siFlags     = 'Flags';
  332.   siShowCmd   = 'ShowCmd';
  333.   siMinMaxPos = 'MinMaxPos';
  334.   siNormPos   = 'NormPos';
  335.   siPixels    = 'PixelsPerInch';
  336.   siMDIChild  = 'MDI Children';
  337.   siListCount = 'Count';
  338.   siItem      = 'Item%d';
  339.  
  340. function IniReadString(IniFile: TObject; const Section, Ident,
  341.   Default: string): string;
  342. begin
  343. {$IFDEF WIN32}
  344.   if IniFile is TRegIniFile then
  345.     Result := TRegIniFile(IniFile).ReadString(Section, Ident, Default)
  346.   else
  347. {$ENDIF}
  348.   if IniFile is TIniFile then
  349.     Result := TIniFile(IniFile).ReadString(Section, Ident, Default)
  350.   else Result := Default;
  351. end;
  352.  
  353. procedure IniWriteString(IniFile: TObject; const Section, Ident,
  354.   Value: string);
  355. var
  356.   S: string;
  357. begin
  358. {$IFDEF WIN32}
  359.   if IniFile is TRegIniFile then
  360.     TRegIniFile(IniFile).WriteString(Section, Ident, Value)
  361.   else begin
  362. {$ENDIF}
  363.     S := Value;
  364.     if S <> '' then begin
  365.       if ((S[1] = '"') and (S[Length(S)] = '"')) or
  366.         ((S[1] = '''') and (S[Length(S)] = '''')) then
  367.         S := '"' + S + '"';
  368.     end;
  369.     if IniFile is TIniFile then
  370.       TIniFile(IniFile).WriteString(Section, Ident, S);
  371. {$IFDEF WIN32}
  372.   end;
  373. {$ENDIF}
  374. end;
  375.  
  376. function IniReadInteger(IniFile: TObject; const Section, Ident: string;
  377.   Default: Longint): Longint;
  378. begin
  379. {$IFDEF WIN32}
  380.   if IniFile is TRegIniFile then
  381.     Result := TRegIniFile(IniFile).ReadInteger(Section, Ident, Default)
  382.   else
  383. {$ENDIF}
  384.   if IniFile is TIniFile then
  385.     Result := TIniFile(IniFile).ReadInteger(Section, Ident, Default)
  386.   else Result := Default;
  387. end;
  388.  
  389. procedure IniWriteInteger(IniFile: TObject; const Section, Ident: string;
  390.   Value: Longint);
  391. begin
  392. {$IFDEF WIN32}
  393.   if IniFile is TRegIniFile then
  394.     TRegIniFile(IniFile).WriteInteger(Section, Ident, Value)
  395.   else
  396. {$ENDIF}
  397.   if IniFile is TIniFile then
  398.     TIniFile(IniFile).WriteInteger(Section, Ident, Value);
  399. end;
  400.  
  401. function IniReadBool(IniFile: TObject; const Section, Ident: string;
  402.   Default: Boolean): Boolean;
  403. begin
  404. {$IFDEF WIN32}
  405.   if IniFile is TRegIniFile then
  406.     Result := TRegIniFile(IniFile).ReadBool(Section, Ident, Default)
  407.   else
  408. {$ENDIF}
  409.   if IniFile is TIniFile then
  410.     Result := TIniFile(IniFile).ReadBool(Section, Ident, Default)
  411.   else Result := Default;
  412. end;
  413.  
  414. procedure IniWriteBool(IniFile: TObject; const Section, Ident: string;
  415.   Value: Boolean);
  416. begin
  417. {$IFDEF WIN32}
  418.   if IniFile is TRegIniFile then
  419.     TRegIniFile(IniFile).WriteBool(Section, Ident, Value)
  420.   else
  421. {$ENDIF}
  422.   if IniFile is TIniFile then
  423.     TIniFile(IniFile).WriteBool(Section, Ident, Value);
  424. end;
  425.  
  426. procedure IniEraseSection(IniFile: TObject; const Section: string);
  427. begin
  428. {$IFDEF WIN32}
  429.   if IniFile is TRegIniFile then
  430.     TRegIniFile(IniFile).EraseSection(Section)
  431.   else
  432. {$ENDIF}
  433.   if IniFile is TIniFile then
  434.     TIniFile(IniFile).EraseSection(Section);
  435. end;
  436.  
  437. procedure IniDeleteKey(IniFile: TObject; const Section, Ident: string);
  438. {$IFNDEF WIN32}
  439. var
  440.   CSection: array[0..127] of Char;
  441.   CIdent: array[0..127] of Char;
  442.   CFileName: array[0..127] of Char;
  443. {$ENDIF}
  444. begin
  445. {$IFDEF WIN32}
  446.   if IniFile is TRegIniFile then
  447.     TRegIniFile(IniFile).DeleteKey(Section, Ident)
  448.   else if IniFile is TIniFile then
  449.     TIniFile(IniFile).DeleteKey(Section, Ident);
  450. {$ELSE}
  451.   if IniFile is TIniFile then begin
  452.     WritePrivateProfileString(StrPLCopy(CSection, Section, SizeOf(CSection) - 1),
  453.       StrPLCopy(CIdent, Ident, SizeOf(CIdent) - 1), nil,
  454.       StrPLCopy(CFileName, TIniFile(IniFile).FileName, SizeOf(CFileName) - 1));
  455.   end;
  456. {$ENDIF}
  457. end;
  458.  
  459. {$IFNDEF WIN32}
  460. procedure IniFileReadSections(IniFile: TIniFile; Strings: TStrings);
  461. const
  462.   BufSize = 8192;
  463. var
  464.   CFileName: array[0..127] of Char;
  465.   Buffer, P: PChar;
  466. begin
  467.   GetMem(Buffer, BufSize);
  468.   try
  469.     Strings.BeginUpdate;
  470.     try
  471.       Strings.Clear;
  472.       if GetPrivateProfileString(nil, nil, nil, Buffer, BufSize,
  473.         StrPLCopy(CFileName, IniFile.FileName, SizeOf(CFileName) - 1)) <> 0 then
  474.       begin
  475.         P := Buffer;
  476.         while P^ <> #0 do begin
  477.           Strings.Add(StrPas(P));
  478.           Inc(P, StrLen(P) + 1);
  479.         end;
  480.       end;
  481.     finally
  482.       Strings.EndUpdate;
  483.     end;
  484.   finally
  485.     FreeMem(Buffer, BufSize);
  486.   end;
  487. end;
  488. {$ENDIF}
  489.  
  490. procedure IniReadSections(IniFile: TObject; Strings: TStrings);
  491. begin
  492. {$IFDEF WIN32}
  493.   if IniFile is TIniFile then
  494.     TIniFile(IniFile).ReadSections(Strings)
  495.   else if IniFile is TRegIniFile then
  496.     TRegIniFile(IniFile).ReadSections(Strings);
  497. {$ELSE}
  498.   if IniFile is TIniFile then
  499.     IniFileReadSections(TIniFile(IniFile), Strings);
  500. {$ENDIF}
  501. end;
  502.  
  503. procedure InternalSaveMDIChildren(MainForm: TForm; IniFile: TObject);
  504. var
  505.   I: Integer;
  506. begin
  507.   if (MainForm = nil) or (MainForm.FormStyle <> fsMDIForm) then
  508.     raise EInvalidOperation.Create(ResStr(SNoMDIForm));
  509.   IniEraseSection(IniFile, siMDIChild);
  510.   if MainForm.MDIChildCount > 0 then begin
  511.     IniWriteInteger(IniFile, siMDIChild, siListCount,
  512.       MainForm.MDIChildCount);
  513.     for I := 0 to MainForm.MDIChildCount - 1 do
  514.       IniWriteString(IniFile, siMDIChild, Format(siItem, [I]),
  515.         MainForm.MDIChildren[I].ClassName);
  516.   end;
  517. end;
  518.  
  519. procedure InternalRestoreMDIChildren(MainForm: TForm; IniFile: TObject);
  520. var
  521.   I: Integer;
  522.   Count: Integer;
  523.   FormClass: TFormClass;
  524. begin
  525.   if (MainForm = nil) or (MainForm.FormStyle <> fsMDIForm) then
  526.     raise EInvalidOperation.Create(ResStr(SNoMDIForm));
  527.   StartWait;
  528.   try
  529.     Count := IniReadInteger(IniFile, siMDIChild, siListCount, 0);
  530.     if Count > 0 then begin
  531.       for I := 0 to Count - 1 do begin
  532.         FormClass := TFormClass(GetClass(IniReadString(IniFile, siMDIChild,
  533.           Format(siItem, [Count - I - 1]), '')));
  534.         if FormClass <> nil then
  535.           InternalFindShowForm(FormClass, '', False);
  536.       end;
  537.     end;
  538.   finally
  539.     StopWait;
  540.   end;
  541. end;
  542.  
  543. {$IFDEF WIN32}
  544. procedure SaveMDIChildrenReg(MainForm: TForm; IniFile: TRegIniFile);
  545. begin
  546.   InternalSaveMDIChildren(MainForm, IniFile);
  547. end;
  548.  
  549. procedure RestoreMDIChildrenReg(MainForm: TForm; IniFile: TRegIniFile);
  550. begin
  551.   InternalRestoreMDIChildren(MainForm, IniFile);
  552. end;
  553. {$ENDIF WIN32}
  554.  
  555. procedure SaveMDIChildren(MainForm: TForm; IniFile: TIniFile);
  556. begin
  557.   InternalSaveMDIChildren(MainForm, IniFile);
  558. end;
  559.  
  560. procedure RestoreMDIChildren(MainForm: TForm; IniFile: TIniFile);
  561. begin
  562.   InternalRestoreMDIChildren(MainForm, IniFile);
  563. end;
  564.  
  565. procedure InternalSaveGridLayout(Grid: TCustomGrid; IniFile: TObject;
  566.   const Section: string);
  567. var
  568.   I: Longint;
  569. begin
  570.   for I := 0 to TDrawGrid(Grid).ColCount - 1 do
  571.     IniWriteInteger(IniFile, Section, Format(siItem, [I]),
  572.       TDrawGrid(Grid).ColWidths[I]);
  573. end;
  574.  
  575. procedure InternalRestoreGridLayout(Grid: TCustomGrid; IniFile: TObject;
  576.   const Section: string);
  577. var
  578.   I: Longint;
  579. begin
  580.   for I := 0 to TDrawGrid(Grid).ColCount - 1 do
  581.     TDrawGrid(Grid).ColWidths[I] := IniReadInteger(IniFile, Section,
  582.       Format(siItem, [I]), TDrawGrid(Grid).ColWidths[I]);
  583. end;
  584.  
  585. {$IFDEF WIN32}
  586. procedure RestoreGridLayoutReg(Grid: TCustomGrid; IniFile: TRegIniFile);
  587. begin
  588.   InternalRestoreGridLayout(Grid, IniFile, GetDefaultSection(Grid));
  589. end;
  590.  
  591. procedure SaveGridLayoutReg(Grid: TCustomGrid; IniFile: TRegIniFile);
  592. begin
  593.   InternalSaveGridLayout(Grid, IniFile, GetDefaultSection(Grid));
  594. end;
  595. {$ENDIF WIN32}
  596.  
  597. procedure RestoreGridLayout(Grid: TCustomGrid; IniFile: TIniFile);
  598. begin
  599.   InternalRestoreGridLayout(Grid, IniFile, GetDefaultSection(Grid));
  600. end;
  601.  
  602. procedure SaveGridLayout(Grid: TCustomGrid; IniFile: TIniFile);
  603. begin
  604.   InternalSaveGridLayout(Grid, IniFile, GetDefaultSection(Grid));
  605. end;
  606.  
  607. function CrtResString: string;
  608. begin
  609.   Result := Format('(%dx%d)', [GetSystemMetrics(SM_CXSCREEN),
  610.     GetSystemMetrics(SM_CYSCREEN)]);
  611. end;
  612.  
  613. function ReadPosStr(IniFile: TObject; const Section, Ident: string): string;
  614. begin
  615.   Result := IniReadString(IniFile, Section, Ident + CrtResString, '');
  616.   if Result = '' then Result := IniReadString(IniFile, Section, Ident, '');
  617. end;
  618.  
  619. procedure WritePosStr(IniFile: TObject; const Section, Ident, Value: string);
  620. begin
  621.   IniWriteString(IniFile, Section, Ident + CrtResString, Value);
  622.   IniWriteString(IniFile, Section, Ident, Value);
  623. end;
  624.  
  625. procedure InternalWriteFormPlacement(Form: TForm; IniFile: TObject;
  626.   const Section: string);
  627. var
  628.   Placement: TWindowPlacement;
  629. begin
  630.   Placement.Length := SizeOf(TWindowPlacement);
  631.   GetWindowPlacement(Form.Handle, @Placement);
  632.   with Placement, TForm(Form) do begin
  633.     if (Form = Application.MainForm) and IsIconic(Application.Handle) then
  634.       ShowCmd := SW_SHOWMINIMIZED;
  635.     if (FormStyle = fsMDIChild) and (WindowState = wsMinimized) then
  636.       Flags := Flags or WPF_SETMINPOSITION;
  637.     IniWriteInteger(IniFile, Section, siFlags, Flags);
  638.     IniWriteInteger(IniFile, Section, siShowCmd, ShowCmd);
  639.     IniWriteInteger(IniFile, Section, siPixels, Screen.PixelsPerInch);
  640.     WritePosStr(IniFile, Section, siMinMaxPos, Format('%d,%d,%d,%d',
  641.       [ptMinPosition.X, ptMinPosition.Y, ptMaxPosition.X, ptMaxPosition.Y]));
  642.     WritePosStr(IniFile, Section, siNormPos, Format('%d,%d,%d,%d',
  643.       [rcNormalPosition.Left, rcNormalPosition.Top, rcNormalPosition.Right,
  644.       rcNormalPosition.Bottom]));
  645.   end;
  646. end;
  647.  
  648. {$IFDEF WIN32}
  649. procedure WriteFormPlacementReg(Form: TForm; IniFile: TRegIniFile;
  650.   const Section: string);
  651. begin
  652.   InternalWriteFormPlacement(Form, IniFile, Section);
  653. end;
  654. {$ENDIF WIN32}
  655.  
  656. procedure WriteFormPlacement(Form: TForm; IniFile: TIniFile;
  657.   const Section: string);
  658. begin
  659.   InternalWriteFormPlacement(Form, IniFile, Section);
  660. end;
  661.  
  662. {$IFDEF WIN32}
  663. procedure SaveFormPlacement(Form: TForm; const IniFileName: string;
  664.   UseRegistry: Boolean);
  665. {$ELSE}
  666. procedure SaveFormPlacement(Form: TForm; const IniFileName: string);
  667. {$ENDIF WIN32}
  668. var
  669.   IniFile: TObject;
  670. begin
  671. {$IFDEF WIN32}
  672.   if UseRegistry then IniFile := TRegIniFile.Create(IniFileName)
  673.   else IniFile := TIniFile.Create(IniFileName);
  674. {$ELSE}
  675.   IniFile := TIniFile.Create(IniFileName);
  676. {$ENDIF WIN32}
  677.   try
  678.     InternalWriteFormPlacement(Form, IniFile, Form.ClassName);
  679.   finally
  680.     IniFile.Free;
  681.   end;
  682. end;
  683.  
  684. {$IFDEF WIN32}
  685.   {$HINTS OFF}
  686. {$ENDIF}
  687.  
  688. type
  689.  
  690. {*******************************************************}
  691. { !! ATTENTION Nasty implementation                     }
  692. {*******************************************************}
  693. {                                                       }
  694. { This class definition was copied from FORMS.PAS.      }
  695. { It is needed to access some private fields of TForm.  }
  696. {                                                       }
  697. { Any changes in the underlying classes may cause       }
  698. { errors in this implementation!                        }
  699. {                                                       }
  700. {*******************************************************}
  701.  
  702.   TNastyForm = class(TScrollingWinControl)
  703.   private
  704.     FActiveControl: TWinControl;
  705.     FFocusedControl: TWinControl;
  706.     FBorderIcons: TBorderIcons;
  707.     FBorderStyle: TFormBorderStyle;
  708. {$IFDEF RX_D4}
  709.     FSizeChanging: Boolean;
  710. {$ENDIF}
  711.     FWindowState: TWindowState; { !! }
  712.   end;
  713.  
  714.   THackComponent = class(TComponent);
  715. {$IFDEF WIN32}
  716.   {$HINTS ON}
  717. {$ENDIF}
  718.  
  719. procedure InternalReadFormPlacement(Form: TForm; IniFile: TObject;
  720.   const Section: string; LoadState, LoadPosition: Boolean);
  721. const
  722.   Delims = [',',' '];
  723. var
  724.   PosStr: string;
  725.   Placement: TWindowPlacement;
  726.   WinState: TWindowState;
  727.   DataFound: Boolean;
  728. begin
  729.   if not (LoadState or LoadPosition) then Exit;
  730.   Placement.Length := SizeOf(TWindowPlacement);
  731.   GetWindowPlacement(Form.Handle, @Placement);
  732.   with Placement, TForm(Form) do begin
  733.     if not IsWindowVisible(Form.Handle) then
  734.       ShowCmd := SW_HIDE;
  735.     if LoadPosition then begin
  736.       DataFound := False;
  737.       Flags := IniReadInteger(IniFile, Section, siFlags, Flags);
  738.       PosStr := ReadPosStr(IniFile, Section, siMinMaxPos);
  739.       if PosStr <> '' then begin
  740.         DataFound := True;
  741.         ptMinPosition.X := StrToIntDef(ExtractWord(1, PosStr, Delims), 0);
  742.         ptMinPosition.Y := StrToIntDef(ExtractWord(2, PosStr, Delims), 0);
  743.         ptMaxPosition.X := StrToIntDef(ExtractWord(3, PosStr, Delims), 0);
  744.         ptMaxPosition.Y := StrToIntDef(ExtractWord(4, PosStr, Delims), 0);
  745.       end;
  746.       PosStr := ReadPosStr(IniFile, Section, siNormPos);
  747.       if PosStr <> '' then begin
  748.         DataFound := True;
  749.         rcNormalPosition.Left := StrToIntDef(ExtractWord(1, PosStr, Delims), Left);
  750.         rcNormalPosition.Top := StrToIntDef(ExtractWord(2, PosStr, Delims), Top);
  751.         rcNormalPosition.Right := StrToIntDef(ExtractWord(3, PosStr, Delims), Left + Width);
  752.         rcNormalPosition.Bottom := StrToIntDef(ExtractWord(4, PosStr, Delims), Top + Height);
  753.       end;
  754.       if Screen.PixelsPerInch <> IniReadInteger(IniFile, Section, siPixels,
  755.         Screen.PixelsPerInch) then DataFound := False;
  756.       if DataFound then begin
  757.         if not (BorderStyle in [bsSizeable {$IFDEF WIN32}, bsSizeToolWin {$ENDIF}]) then
  758.           rcNormalPosition := Rect(rcNormalPosition.Left, rcNormalPosition.Top,
  759.             rcNormalPosition.Left + Width, rcNormalPosition.Top + Height);
  760.         if rcNormalPosition.Right > rcNormalPosition.Left then begin
  761.           if (Position in [poScreenCenter {$IFDEF RX_D4}, poDesktopCenter {$ENDIF}]) and
  762.             not (csDesigning in ComponentState) then
  763.           begin
  764.             THackComponent(Form).SetDesigning(True);
  765.             try
  766.               Position := poDesigned;
  767.             finally
  768.               THackComponent(Form).SetDesigning(False);
  769.             end;
  770.           end;
  771.           SetWindowPlacement(Handle, @Placement);
  772.         end;
  773.       end;
  774.     end;
  775.     if LoadState then begin
  776.       WinState := wsNormal;
  777.       { default maximize MDI main form }
  778.       if ((Application.MainForm = Form) {$IFDEF RX_D4} or
  779.         (Application.MainForm = nil) {$ENDIF}) and ((FormStyle = fsMDIForm) or
  780.         ((FormStyle = fsNormal) and (Position = poDefault))) then
  781.         WinState := wsMaximized;
  782.       ShowCmd := IniReadInteger(IniFile, Section, siShowCmd, SW_HIDE);
  783.       case ShowCmd of
  784.         SW_SHOWNORMAL, SW_RESTORE, SW_SHOW:
  785.           WinState := wsNormal;
  786.         SW_MINIMIZE, SW_SHOWMINIMIZED, SW_SHOWMINNOACTIVE:
  787.           WinState := wsMinimized;
  788.         SW_MAXIMIZE: WinState := wsMaximized;
  789.       end;
  790. {$IFDEF WIN32}
  791.       if (WinState = wsMinimized) and ((Form = Application.MainForm)
  792.         {$IFDEF RX_D4} or (Application.MainForm = nil) {$ENDIF}) then
  793.       begin
  794.         TNastyForm(Form).FWindowState := wsNormal;
  795.         PostMessage(Application.Handle, WM_SYSCOMMAND, SC_MINIMIZE, 0);
  796.         Exit;
  797.       end;
  798. {$ENDIF}
  799.       if FormStyle in [fsMDIChild, fsMDIForm] then
  800.         TNastyForm(Form).FWindowState := WinState
  801.       else WindowState := WinState;
  802.     end;
  803.     Update;
  804.   end;
  805. end;
  806.  
  807. {$IFDEF WIN32}
  808. procedure ReadFormPlacementReg(Form: TForm; IniFile: TRegIniFile;
  809.   const Section: string; LoadState, LoadPosition: Boolean);
  810. begin
  811.   InternalReadFormPlacement(Form, IniFile, Section, LoadState, LoadPosition);
  812. end;
  813. {$ENDIF WIN32}
  814.  
  815. procedure ReadFormPlacement(Form: TForm; IniFile: TIniFile;
  816.   const Section: string; LoadState, LoadPosition: Boolean);
  817. begin
  818.   InternalReadFormPlacement(Form, IniFile, Section, LoadState, LoadPosition);
  819. end;
  820.  
  821. {$IFDEF WIN32}
  822. procedure RestoreFormPlacement(Form: TForm; const IniFileName: string;
  823.   UseRegistry: Boolean);
  824. {$ELSE}
  825. procedure RestoreFormPlacement(Form: TForm; const IniFileName: string);
  826. {$ENDIF}
  827. var
  828.   IniFile: TObject;
  829. begin
  830. {$IFDEF WIN32}
  831.   if UseRegistry then begin
  832.     IniFile := TRegIniFile.Create(IniFileName);
  833.   {$IFDEF RX_D5} 
  834.     TRegIniFile(IniFile).Access := KEY_READ;
  835.   {$ENDIF}
  836.   end
  837.   else 
  838.     IniFile := TIniFile.Create(IniFileName);
  839. {$ELSE}
  840.   IniFile := TIniFile.Create(IniFileName);
  841. {$ENDIF WIN32}
  842.   try
  843.     InternalReadFormPlacement(Form, IniFile, Form.ClassName, True, True);
  844.   finally
  845.     IniFile.Free;
  846.   end;
  847. end;
  848.  
  849. function GetUniqueFileNameInDir(const Path, FileNameMask: string): string;
  850. var
  851.   CurrentName: string;
  852.   I: Integer;
  853. begin
  854.   Result := '';
  855.   for I := 0 to MaxInt do begin
  856.     CurrentName := Format(FileNameMask, [I]);
  857.     if not FileExists(NormalDir(Path) + CurrentName) then begin
  858.       Result := CurrentName;
  859.       Exit;
  860.     end;
  861.   end;
  862. end;
  863.  
  864. {$IFDEF WIN32}
  865. procedure AppBroadcast(Msg, wParam: Longint; lParam: Longint);
  866. {$ELSE}
  867. procedure AppBroadcast(Msg, wParam: Word; lParam: Longint);
  868. {$ENDIF WIN32}
  869. var
  870.   I: Integer;
  871. begin
  872.   for I := 0 to Screen.FormCount - 1 do
  873.     SendMessage(Screen.Forms[I].Handle, Msg, wParam, lParam);
  874. end;
  875.  
  876. procedure AppTaskbarIcons(AppOnly: Boolean);
  877. var
  878.   Style: Longint;
  879. begin
  880.   Style := GetWindowLong(Application.Handle, GWL_STYLE);
  881.   if AppOnly then Style := Style or WS_CAPTION
  882.   else Style := Style and not WS_CAPTION;
  883.   SetWindowLong(Application.Handle, GWL_STYLE, Style);
  884.   if AppOnly then SwitchToWindow(Application.Handle, False);
  885. end;
  886.  
  887. end.