source: branches/ByteArray/Packages/Common/PersistentForm.pas

Last change on this file was 11, checked in by chronos, 2 months ago
  • Modified: Updated Common package.
  • Fixed: Wrong return address from CALL instruction.
File size: 11.8 KB
Line 
1unit PersistentForm;
2
3interface
4
5uses
6 Classes, SysUtils, Forms, RegistryEx, LCLIntf, Registry, Controls, ComCtrls,
7 ExtCtrls, LCLType;
8
9type
10
11 { TPersistentForm }
12
13 TPersistentForm = class(TComponent)
14 private
15 FEntireVisible: Boolean;
16 FMinVisiblePart: Integer;
17 FRegistryContext: TRegistryContext;
18 FResizeEventOccured: Boolean;
19 procedure LoadControl(Control: TControl);
20 procedure SaveControl(Control: TControl);
21 procedure WindowStateChange(Sender: TObject);
22 public
23 FormRestoredSize: TRect;
24 FormWindowState: TWindowState;
25 FormFullScreen: Boolean;
26 Form: TForm;
27 procedure LoadFromRegistry(RegistryContext: TRegistryContext);
28 procedure SaveToRegistry(RegistryContext: TRegistryContext);
29 function CheckEntireVisible(Rect: TRect): TRect;
30 function CheckPartVisible(Rect: TRect; Part: Integer): TRect;
31 procedure Load(Form: TForm; DefaultMaximized: Boolean = False;
32 DefaultFullScreen: Boolean = False);
33 procedure Save(Form: TForm);
34 constructor Create(AOwner: TComponent); override;
35 procedure SetFullScreen(State: Boolean);
36 property RegistryContext: TRegistryContext read FRegistryContext
37 write FRegistryContext;
38 published
39 property MinVisiblePart: Integer read FMinVisiblePart write FMinVisiblePart;
40 property EntireVisible: Boolean read FEntireVisible write FEntireVisible;
41 end;
42
43procedure Register;
44
45
46implementation
47
48procedure Register;
49begin
50 RegisterComponents('Common', [TPersistentForm]);
51end;
52
53{ TPersistentForm }
54
55procedure TPersistentForm.LoadControl(Control: TControl);
56var
57 I: Integer;
58 WinControl: TWinControl;
59begin
60 if Control is TListView then begin
61 with Form, TRegistryEx.Create do
62 try
63 RootKey := RegistryContext.RootKey;
64 OpenKey(RegistryContext.Key + '\Forms\' + Form.Name + '\' + Control.Name, True);
65 for I := 0 to TListView(Control).Columns.Count - 1 do begin
66 if ValueExists('ColWidth' + IntToStr(I)) then
67 TListView(Control).Columns[I].Width := ReadInteger('ColWidth' + IntToStr(I));
68 end;
69 finally
70 Free;
71 end;
72 end;
73
74 if (Control is TPanel) then begin
75 with Form, TRegistryEx.Create do
76 try
77 RootKey := RegistryContext.RootKey;
78 OpenKey(RegistryContext.Key + '\Forms\' + Form.Name + '\' + Control.Name, True);
79 if (TPanel(Control).Align = alRight) or (TPanel(Control).Align = alLeft) then begin
80 if ValueExists('Width') then
81 TPanel(Control).Width := ReadInteger('Width');
82 end;
83 if (TPanel(Control).Align = alTop) or (TPanel(Control).Align = alBottom) then begin
84 if ValueExists('Height') then
85 TPanel(Control).Height := ReadInteger('Height');
86 end;
87 finally
88 Free;
89 end;
90 end;
91
92 if Control is TWinControl then begin
93 WinControl := TWinControl(Control);
94 if WinControl.ControlCount > 0 then begin
95 for I := 0 to WinControl.ControlCount - 1 do begin
96 if WinControl.Controls[I] is TControl then begin
97 LoadControl(WinControl.Controls[I]);
98 end;
99 end;
100 end;
101 end;
102end;
103
104procedure TPersistentForm.SaveControl(Control: TControl);
105var
106 I: Integer;
107 WinControl: TWinControl;
108begin
109 if Control is TListView then begin
110 with Form, TRegistryEx.Create do
111 try
112 RootKey := RegistryContext.RootKey;
113 OpenKey(RegistryContext.Key + '\Forms\' + Form.Name + '\' + Control.Name, True);
114 for I := 0 to TListView(Control).Columns.Count - 1 do begin
115 WriteInteger('ColWidth' + IntToStr(I), TListView(Control).Columns[I].Width);
116 end;
117 finally
118 Free;
119 end;
120 end;
121
122 if (Control is TPanel) then begin
123 with Form, TRegistryEx.Create do
124 try
125 RootKey := RegistryContext.RootKey;
126 OpenKey(RegistryContext.Key + '\Forms\' + Form.Name + '\' + Control.Name, True);
127 if (TPanel(Control).Align = alRight) or (TPanel(Control).Align = alLeft) then begin
128 WriteInteger('Width', TPanel(Control).Width);
129 end;
130 if (TPanel(Control).Align = alTop) or (TPanel(Control).Align = alBottom) then begin
131 WriteInteger('Height', TPanel(Control).Height);
132 end;
133 finally
134 Free;
135 end;
136 end;
137
138 if Control is TWinControl then begin
139 WinControl := TWinControl(Control);
140 if WinControl.ControlCount > 0 then begin
141 for I := 0 to WinControl.ControlCount - 1 do begin
142 if WinControl.Controls[I] is TControl then begin
143 SaveControl(WinControl.Controls[I]);
144 end;
145 end;
146 end;
147 end;
148end;
149
150procedure TPersistentForm.LoadFromRegistry(RegistryContext: TRegistryContext);
151begin
152 with TRegistryEx.Create do
153 try
154 RootKey := RegistryContext.RootKey;
155 OpenKey(RegistryContext.Key + '\Forms\' + Form.Name, True);
156
157 // Restored size
158 FormRestoredSize.Left := ReadIntegerWithDefault('RestoredLeft', FormRestoredSize.Left);
159 FormRestoredSize.Top := ReadIntegerWithDefault('RestoredTop', FormRestoredSize.Top);
160 FormRestoredSize.Right := ReadIntegerWithDefault('RestoredWidth', FormRestoredSize.Right - FormRestoredSize.Left)
161 + FormRestoredSize.Left;
162 FormRestoredSize.Bottom := ReadIntegerWithDefault('RestoredHeight', FormRestoredSize.Bottom - FormRestoredSize.Top)
163 + FormRestoredSize.Top;
164
165 // Other state
166 FormWindowState := TWindowState(ReadIntegerWithDefault('WindowState', Integer(FormWindowState)));
167 FormFullScreen := ReadBoolWithDefault('FullScreen', FormFullScreen);
168 finally
169 Free;
170 end;
171end;
172
173procedure TPersistentForm.SaveToRegistry(RegistryContext: TRegistryContext);
174begin
175 with Form, TRegistryEx.Create do
176 try
177 RootKey := RegistryContext.RootKey;
178 OpenKey(RegistryContext.Key + '\Forms\' + Form.Name, True);
179
180 // Restored size
181 WriteInteger('RestoredWidth', FormRestoredSize.Right - FormRestoredSize.Left);
182 WriteInteger('RestoredHeight', FormRestoredSize.Bottom - FormRestoredSize.Top);
183 WriteInteger('RestoredTop', FormRestoredSize.Top);
184 WriteInteger('RestoredLeft', FormRestoredSize.Left);
185
186 // Other state
187 WriteInteger('WindowState', Integer(FormWindowState));
188 WriteBool('FullScreen', FormFullScreen);
189 finally
190 Free;
191 end;
192end;
193
194function TPersistentForm.CheckEntireVisible(Rect: TRect): TRect;
195var
196 Width: Integer;
197 Height: Integer;
198begin
199 Result := Rect;
200 Width := Rect.Right - Rect.Left;
201 Height := Rect.Bottom - Rect.Top;
202 if Result.Left < (Screen.DesktopLeft) then begin
203 Result.Left := Screen.DesktopLeft;
204 Result.Right := Screen.DesktopLeft + Width;
205 end;
206 if Result.Right > (Screen.DesktopLeft + Screen.DesktopWidth) then begin
207 Result.Left := Screen.DesktopLeft + Screen.DesktopWidth - Width;
208 Result.Right := Screen.DesktopLeft + Screen.DesktopWidth;
209 end;
210 if Result.Top < Screen.DesktopTop then begin
211 Result.Top := Screen.DesktopTop;
212 Result.Bottom := Screen.DesktopTop + Height;
213 end;
214 if Result.Bottom > (Screen.DesktopTop + Screen.DesktopHeight) then begin
215 Result.Top := Screen.DesktopTop + Screen.DesktopHeight - Height;
216 Result.Bottom := Screen.DesktopTop + Screen.DesktopHeight;
217 end;
218end;
219
220function TPersistentForm.CheckPartVisible(Rect: TRect; Part: Integer): TRect;
221var
222 Width: Integer;
223 Height: Integer;
224begin
225 Result := Rect;
226 Width := Rect.Right - Rect.Left;
227 Height := Rect.Bottom - Rect.Top;
228 if Result.Right < (Screen.DesktopLeft + Part) then begin
229 Result.Left := Screen.DesktopLeft + Part - Width;
230 Result.Right := Screen.DesktopLeft + Part;
231 end;
232 if Result.Left > (Screen.DesktopLeft + Screen.DesktopWidth - Part) then begin
233 Result.Left := Screen.DesktopLeft + Screen.DesktopWidth - Part;
234 Result.Right := Screen.DesktopLeft + Screen.DesktopWidth - Part + Width;
235 end;
236 if Result.Bottom < (Screen.DesktopTop + Part) then begin
237 Result.Top := Screen.DesktopTop + Part - Height;
238 Result.Bottom := Screen.DesktopTop + Part;
239 end;
240 if Result.Top > (Screen.DesktopTop + Screen.DesktopHeight - Part) then begin
241 Result.Top := Screen.DesktopTop + Screen.DesktopHeight - Part;
242 Result.Bottom := Screen.DesktopTop + Screen.DesktopHeight - Part + Height;
243 end;
244end;
245
246procedure TPersistentForm.Load(Form: TForm; DefaultMaximized: Boolean = False;
247 DefaultFullScreen: Boolean = False);
248begin
249 Self.Form := Form;
250
251 // Set default
252 FormRestoredSize := Bounds((Screen.Width - Form.Width) div 2,
253 (Screen.Height - Form.Height) div 2, Form.Width, Form.Height);
254 FormWindowState := Form.WindowState;
255 FormFullScreen := DefaultFullScreen;
256
257 LoadFromRegistry(RegistryContext);
258
259 if (FormWindowState = wsMaximized) or DefaultMaximized then begin
260 // Restore to maximized state
261 Form.WindowState := wsNormal;
262 if not EqualRect(FormRestoredSize, Form.BoundsRect) then
263 Form.BoundsRect := FormRestoredSize;
264 Form.WindowState := wsMaximized;
265 end else begin
266 // Restore to normal state
267 Form.WindowState := wsNormal;
268 if FEntireVisible then FormRestoredSize := CheckEntireVisible(FormRestoredSize)
269 else if FMinVisiblePart > 0 then
270 FormRestoredSize := CheckPartVisible(FormRestoredSize, FMinVisiblePart);
271 if not EqualRect(FormRestoredSize, Form.BoundsRect) then
272 Form.BoundsRect := FormRestoredSize;
273 end;
274 if FormFullScreen then SetFullScreen(True);
275 LoadControl(Form);
276end;
277
278procedure TPersistentForm.Save(Form: TForm);
279begin
280 Self.Form := Form;
281 if not FormFullScreen then begin
282 FormWindowState := Form.WindowState;
283 if FormWindowState = wsMaximized then begin
284 FormRestoredSize := Bounds(Form.RestoredLeft, Form.RestoredTop, Form.RestoredWidth,
285 Form.RestoredHeight);
286 end else
287 if FormWindowState = wsNormal then begin
288 FormRestoredSize := Bounds(Form.Left, Form.Top, Form.Width, Form.Height);
289 end;
290 end;
291 SaveToRegistry(RegistryContext);
292 SaveControl(Form);
293end;
294
295constructor TPersistentForm.Create(AOwner: TComponent);
296begin
297 inherited;
298 if AOwner is TForm then Form := TForm(AOwner)
299 else Form := nil;
300 FMinVisiblePart := 50;
301 FRegistryContext.RootKey := HKEY_CURRENT_USER;
302end;
303
304procedure TPersistentForm.SetFullScreen(State: Boolean);
305{$IFDEF UNIX}
306var
307 OldHandler: TNotifyEvent;
308var
309 I: Integer;
310{$ENDIF}
311begin
312 if State then begin
313 FormFullScreen := True;
314 if Form.WindowState = wsMaximized then begin
315 FormRestoredSize := Bounds(Form.RestoredLeft, Form.RestoredTop, Form.RestoredWidth,
316 Form.RestoredHeight);
317 end else
318 if Form.WindowState = wsNormal then begin
319 FormRestoredSize := Bounds(Form.Left, Form.Top, Form.Width, Form.Height);
320 end;
321 FormWindowState := Form.WindowState;
322 {$IFDEF WINDOWS}
323 Form.BorderStyle := bsNone;
324 {$ENDIF}
325 Form.WindowState := wsFullscreen;
326 {$IFDEF UNIX}
327 // Workaround on Linux, WindowState is rewriten by WMSize event to wsNormal.
328 // We need for that even to occure
329 OldHandler := Form.OnWindowStateChange;
330 Form.OnWindowStateChange := WindowStateChange;
331 FResizeEventOccured := False;
332 for I := 0 to 10 do begin
333 if FResizeEventOccured then Break;
334 Application.ProcessMessages;
335 Sleep(1);
336 end;
337 Form.OnWindowStateChange := OldHandler;
338 {$ENDIF}
339 end else begin
340 FormFullScreen := False;
341 Form.WindowState := wsNormal;
342 {$IFDEF WINDOWS}
343 Form.BorderStyle := bsSizeable;
344 {$ENDIF}
345 if FormWindowState = wsNormal then begin
346 Form.WindowState := wsNormal;
347 Form.BoundsRect := FormRestoredSize;
348 end else
349 if FormWindowState = wsMaximized then begin
350 Form.BoundsRect := FormRestoredSize;
351 Form.WindowState := wsMaximized;
352 end;
353 end;
354end;
355
356procedure TPersistentForm.WindowStateChange(Sender: TObject);
357begin
358 Form.WindowState := wsFullscreen;
359 FResizeEventOccured := True;
360end;
361
362end.
Note: See TracBrowser for help on using the repository browser.