source: branches/zoom/Packages/CevoComponents/BaseWin.pas

Last change on this file was 684, checked in by chronos, 6 weeks ago
  • Modified: Improved forms painting if resized to bigger dimensions.
File size: 16.0 KB
Line 
1unit BaseWin;
2
3interface
4
5uses
6 ScreenTools, LCLIntf, LCLType, SysUtils, Classes, DrawDlg,
7 {$IFDEF DPI}Dpi.Graphics, Dpi.Controls, Dpi.Forms, Dpi.Common, System.UITypes{$ELSE}
8 Graphics, Controls, Forms{$ENDIF};
9
10type
11 TWindowMode = (wmNone, wmModal, wmPersistent, wmSubmodal);
12 TShowNewContent = procedure (NewMode: TWindowMode; HelpContext: string) of object;
13
14 { TBufferedDrawDlg }
15
16 TBufferedDrawDlg = class(TDrawDlg)
17 protected
18 FWindowMode: TWindowMode;
19 ModalFrameIndent: Integer;
20 HelpContext: string;
21 procedure ShowNewContent(NewMode: TWindowMode; ForceClose: Boolean = False);
22 procedure MarkUsedOffscreen(xMax, yMax: Integer);
23 procedure OffscreenPaint; virtual;
24 procedure VPaint; virtual;
25 procedure DoOnResize; override;
26 public
27 UserLeft: Integer;
28 UserTop: Integer;
29 UsedOffscreenWidth: Integer;
30 UsedOffscreenHeight: Integer;
31 Offscreen: TBitmap;
32 OffscreenUser: TForm;
33 constructor Create(AOwner: TComponent); override;
34 destructor Destroy; override;
35 procedure FormClose(Sender: TObject; var Action: TCloseAction);
36 procedure FormPaint(Sender: TObject);
37 procedure FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
38 procedure FormDeactivate(Sender: TObject);
39 procedure SmartUpdateContent(ImmediateUpdate: Boolean = False);
40 property WindowMode: TWindowMode read FWindowMode;
41 end;
42
43 { TFramedDlg }
44
45 TFramedDlg = class(TBufferedDrawDlg)
46 protected
47 CaptionLeft: Integer;
48 CaptionRight: Integer;
49 InnerWidth: Integer;
50 InnerHeight: Integer;
51 WideBottom: Boolean;
52 FullCaption: Boolean;
53 TexOverride: Boolean;
54 ModalIndication: Boolean;
55 procedure InitWindowRegion;
56 procedure VPaint; override;
57 procedure FillOffscreen(Left, Top, Width, Height: Integer);
58 procedure DoOnResize; override;
59 public
60 constructor Create(AOwner: TComponent); override;
61 procedure FormCreate(Sender: TObject);
62 procedure SmartInvalidate; override;
63 end;
64
65var
66 ShowNewContentProc: TShowNewContent;
67 MainFormKeyDown: TKeyEvent;
68
69const
70 NarrowFrame = 11;
71 WideFrame = 36;
72 SideFrame = 9;
73
74procedure CreateOffscreen(var Offscreen: TBitmap; Width, Height: Integer);
75function WindowModeMakePersistent(Mode: TWindowMode): TWindowMode;
76procedure Register;
77
78
79implementation
80
81uses
82 ButtonBase, Area;
83
84function WindowModeMakePersistent(Mode: TWindowMode): TWindowMode;
85begin
86 if Mode = wmModal then Result := wmSubmodal
87 else Result := wmPersistent;
88end;
89
90procedure Register;
91begin
92 RegisterNoIcon([TBufferedDrawDlg]);
93 RegisterNoIcon([TFramedDlg]);
94end;
95
96constructor TBufferedDrawDlg.Create(AOwner: TComponent);
97begin
98 BaseWin.CreateOffscreen(Offscreen, Width, Height);
99 OnClose := FormClose;
100 OnPaint := FormPaint;
101 OnKeyDown := FormKeyDown;
102 OnDeactivate := FormDeactivate;
103 inherited;
104 FWindowMode := wmNone;
105 HelpContext := 'CONCEPTS';
106 TitleHeight := WideFrame;
107 ModalFrameIndent := 45;
108 UserLeft := Screen.PrimaryMonitor.Left + (Screen.PrimaryMonitor.Width - Width) div 2;
109 UserTop := Screen.PrimaryMonitor.Top + (Screen.PrimaryMonitor.Height - Height) div 2;
110end;
111
112destructor TBufferedDrawDlg.Destroy;
113begin
114 FreeAndNil(Offscreen);
115 inherited;
116end;
117
118procedure TBufferedDrawDlg.FormClose(Sender: TObject; var Action: TCloseAction);
119begin
120 if FWindowMode = wmPersistent then begin
121 UserLeft := Left;
122 UserTop := Top;
123 end;
124 if OffscreenUser = Self then
125 OffscreenUser := nil;
126end;
127
128procedure TBufferedDrawDlg.FormPaint(Sender: TObject);
129begin
130 if OffscreenUser <> Self then
131 OffscreenPaint;
132 VPaint;
133end;
134
135procedure TBufferedDrawDlg.FormKeyDown(Sender: TObject; var Key: Word;
136 Shift: TShiftState);
137begin
138 if Key = VK_ESCAPE then begin
139 if TFormStateType.fsModal in FormState then
140 ModalResult := mrCancel;
141 end else
142 if Key = VK_RETURN then begin
143 if TFormStateType.fsModal in FormState then
144 ModalResult := mrOK;
145 end else
146 if Key = VK_F1 then begin
147 if Assigned(ShowNewContentProc) then
148 ShowNewContentProc(WindowModeMakePersistent(FWindowMode), HelpContext);
149 end else
150 if FWindowMode = wmPersistent then begin
151 if Assigned(MainFormKeyDown) then
152 MainFormKeyDown(Sender, Key, Shift);
153 end;
154end;
155
156procedure TBufferedDrawDlg.FormDeactivate(Sender: TObject);
157begin
158 if FWindowMode = wmSubmodal then
159 Close;
160end;
161
162procedure TBufferedDrawDlg.OffscreenPaint;
163begin
164 BaseWin.CreateOffscreen(Offscreen, Width, Height);
165 if (OffscreenUser <> nil) and (OffscreenUser <> Self) then
166 OffscreenUser.Update; // complete working with old owner to prevent rebound
167 OffscreenUser := Self;
168end;
169
170procedure TBufferedDrawDlg.VPaint;
171begin
172 BitBltCanvas(Canvas, 0, 0, ClientWidth, ClientHeight, Offscreen.Canvas, 0, 0);
173end;
174
175procedure TBufferedDrawDlg.DoOnResize;
176begin
177 inherited;
178 SmartUpdateContent;
179end;
180
181procedure TBufferedDrawDlg.ShowNewContent(NewMode: TWindowMode;
182 ForceClose: Boolean);
183begin
184 if Visible then begin
185 Assert((NewMode = wmModal) or (FWindowMode <> wmModal));
186 // don't make modal window non-modal
187 if (NewMode = wmModal) and (ForceClose or (FWindowMode <> wmModal)) then
188 begin // make modal
189 UserLeft := Left;
190 UserTop := Top;
191 Visible := False;
192 FWindowMode := NewMode;
193 ShowModal;
194 end
195 else if ForceClose then
196 begin // make modal
197 Visible := False;
198 FWindowMode := NewMode;
199 Left := UserLeft;
200 Top := UserTop;
201 Show;
202 end
203 else
204 begin
205 FWindowMode := NewMode;
206 if @OnShow <> nil then
207 OnShow(nil);
208 Invalidate;
209 BringToFront;
210 end;
211 end
212 else
213 begin
214 FWindowMode := NewMode;
215 Left := UserLeft;
216 Top := UserTop;
217 if FWindowMode = wmModal then begin
218 Gtk2Fix;
219 ShowModal;
220 end
221 else
222 Show;
223 end;
224end;
225
226procedure TBufferedDrawDlg.SmartUpdateContent(ImmediateUpdate: Boolean);
227begin
228 if Visible then begin
229 OffscreenPaint;
230 SmartInvalidate;
231 if ImmediateUpdate then
232 Update;
233 end;
234end;
235
236procedure TBufferedDrawDlg.MarkUsedOffscreen(xMax, yMax: Integer);
237begin
238 if xMax > UsedOffscreenWidth then
239 UsedOffscreenWidth := xMax;
240 if yMax > UsedOffscreenHeight then
241 UsedOffscreenHeight := yMax;
242end;
243
244constructor TFramedDlg.Create(AOwner: TComponent);
245begin
246 OnCreate := FormCreate;
247 inherited;
248end;
249
250procedure TFramedDlg.FormCreate(Sender: TObject);
251begin
252 CaptionLeft := 0;
253 CaptionRight := $FFFF;
254 WideBottom := False;
255 FullCaption := True;
256 TexOverride := False;
257 ModalIndication := True;
258 Canvas.Brush.Style := TBrushStyle.bsClear;
259 DoOnResize;
260end;
261
262procedure TFramedDlg.SmartInvalidate;
263var
264 I, BottomFrame: Integer;
265 r0, r1: HRgn;
266begin
267 if WideBottom then
268 BottomFrame := WideFrame
269 else
270 BottomFrame := NarrowFrame;
271 r0 := CreateRectRgn(SideFrame, TitleHeight, ClientWidth - SideFrame,
272 ClientHeight - BottomFrame);
273 for I := 0 to ControlCount - 1 do
274 if not (Controls[I] is TArea) and Controls[I].Visible then
275 begin
276 with Controls[I].BoundsRect do
277 r1 := CreateRectRgn(Left, Top, Right, Bottom);
278 CombineRgn(r0, r0, r1, RGN_DIFF);
279 DeleteObject(r1);
280 end;
281 InvalidateRgn(Handle, r0, False);
282 DeleteObject(r0);
283end;
284
285procedure TFramedDlg.VPaint;
286
287 procedure CornerFrame(x0, y0, x1, y1: Integer);
288 begin
289 Frame(Canvas, x0 + 1, y0 + 1, x1 - 2, y1 - 2, MainTexture.ColorBevelLight,
290 MainTexture.ColorBevelShade);
291 Frame(Canvas, x0 + 2, y0 + 2, x1 - 3, y1 - 3, MainTexture.ColorBevelLight,
292 MainTexture.ColorBevelShade);
293 Corner(Canvas, x0 + 1, y0 + 1, 0, MainTexture);
294 Corner(Canvas, x1 - 9, y0 + 1, 1, MainTexture);
295 Corner(Canvas, x0 + 1, y1 - 9, 2, MainTexture);
296 Corner(Canvas, x1 - 9, y1 - 9, 3, MainTexture);
297 end;
298
299var
300 I, L, FrameTop, FrameBottom, InnerBottom, Cut, xTexOffset,
301 yTexOffset: Integer;
302 R: TRect;
303begin
304 if not TexOverride then
305 begin
306 if (FWindowMode = wmModal) and ModalIndication then
307 MainTexture := MainTexture
308 else
309 MainTexture := MainTexture;
310 MainTexture := MainTexture;
311 end;
312 Canvas.Font.Assign(UniFont[ftCaption]);
313 L := BiColorTextWidth(Canvas, Caption);
314 Cut := (ClientWidth - L) div 2;
315 xTexOffset := 0; //(Maintexture.Width - ClientWidth) div 2;
316 yTexOffset := 0; //(Maintexture.Height - ClientHeight) div 2;
317 if WideBottom then
318 InnerBottom := ClientHeight - WideFrame
319 else
320 InnerBottom := ClientHeight - NarrowFrame;
321 if FullCaption then
322 begin
323 FrameTop := 0;
324 FrameBottom := ClientHeight;
325 end
326 else
327 begin
328 FrameTop := TitleHeight - NarrowFrame;
329 if WideBottom then
330 FrameBottom := ClientHeight - (WideFrame - NarrowFrame)
331 else
332 FrameBottom := ClientHeight;
333 end;
334 Fill(Canvas, 3, InnerBottom + 1, ClientWidth - 6, ClientHeight - InnerBottom -
335 4, xTexOffset, yTexOffset);
336 Fill(Canvas, 3, TitleHeight - 2, SideFrame - 3, InnerBottom - TitleHeight + 4,
337 xTexOffset, yTexOffset);
338 Fill(Canvas, ClientWidth - SideFrame, TitleHeight - 2, SideFrame - 3,
339 InnerBottom - TitleHeight + 4, xTexOffset, yTexOffset);
340 Frame(Canvas, 0, FrameTop, ClientWidth - 1, FrameBottom - 1, 0, 0);
341 Frame(Canvas, SideFrame - 1, TitleHeight - 1, ClientWidth - SideFrame,
342 InnerBottom, MainTexture.ColorBevelShade, MainTexture.ColorBevelLight);
343
344 // RFrame(Canvas,SideFrame - 2, TitleHeight - 2, ClientWidth - SideFrame + 1,
345 // InnerBottom + 1, MainTexture.ColorBevelShade, MainTexture.ColorBevelLight);
346 if FullCaption then begin
347 if (FWindowMode <> wmModal) or not ModalIndication then
348 begin
349 Fill(Canvas, 3, 3 + FrameTop, ClientWidth - 6, TitleHeight - FrameTop - 4,
350 xTexOffset, yTexOffset);
351 CornerFrame(0, FrameTop, ClientWidth, FrameBottom);
352 end
353 else
354 with Canvas do
355 begin
356 Fill(Canvas, 3 + ModalFrameIndent, 3 + FrameTop,
357 ClientWidth - 6 - 2 * ModalFrameIndent, TitleHeight - FrameTop - 4,
358 xTexOffset, yTexOffset);
359 Fill(Canvas, ClientWidth - 3 - ModalFrameIndent, 3 + FrameTop,
360 ModalFrameIndent, TitleHeight - FrameTop - 4, xTexOffset, yTexOffset);
361 Fill(Canvas, 3, 3 + FrameTop, ModalFrameIndent, TitleHeight - FrameTop -
362 4, xTexOffset, yTexOffset);
363 CornerFrame(0, FrameTop, ClientWidth, FrameBottom);
364 Pen.Color := MainTexture.ColorBevelShade;
365 MoveTo(3 + ModalFrameIndent, 2);
366 LineTo(3 + ModalFrameIndent, TitleHeight);
367 Pen.Color := MainTexture.ColorBevelShade;
368 MoveTo(4 + ModalFrameIndent, TitleHeight - 1);
369 LineTo(ClientWidth - 4 - ModalFrameIndent, TitleHeight - 1);
370 LineTo(ClientWidth - 4 - ModalFrameIndent, 1);
371 Pen.Color := MainTexture.ColorBevelLight;
372 MoveTo(ClientWidth - 5 - ModalFrameIndent, 2);
373 LineTo(4 + ModalFrameIndent, 2);
374 LineTo(4 + ModalFrameIndent, TitleHeight);
375 MoveTo(ClientWidth - 4 - ModalFrameIndent, 1);
376 LineTo(3 + ModalFrameIndent, 1);
377 Pen.Color := MainTexture.ColorBevelLight;
378 MoveTo(ClientWidth - 3 - ModalFrameIndent, 3);
379 LineTo(ClientWidth - 3 - ModalFrameIndent, TitleHeight);
380 end;
381 end
382 else
383 begin
384 Fill(Canvas, 3, 3 + FrameTop, ClientWidth - 6, TitleHeight - FrameTop - 4,
385 xTexOffset, yTexOffset);
386 CornerFrame(0, FrameTop, ClientWidth, FrameBottom);
387
388 Frame(Canvas, CaptionLeft, 0, ClientWidth - CaptionLeft - 1,
389 FrameTop, 0, 0);
390 Fill(Canvas, CaptionLeft + 3, 3, ClientWidth - 2 * (CaptionLeft) - 6,
391 TitleHeight - 4, xTexOffset, yTexOffset);
392
393 Frame(Canvas, CaptionLeft + 1, 0 + 1, ClientWidth - CaptionLeft - 2,
394 TitleHeight - 1, MainTexture.ColorBevelLight, MainTexture.ColorBevelShade);
395 Frame(Canvas, CaptionLeft + 2, 0 + 2, ClientWidth - CaptionLeft - 3,
396 TitleHeight - 1, MainTexture.ColorBevelLight, MainTexture.ColorBevelShade);
397 Corner(Canvas, CaptionLeft + 1, 0 + 1, 0, MainTexture);
398 Corner(Canvas, ClientWidth - CaptionLeft - 9, 0 + 1, 1, MainTexture);
399
400 with Canvas do
401 begin
402 Pen.Color := MainTexture.ColorBevelShade;
403 MoveTo(CaptionLeft + 1, FrameTop + 2);
404 LineTo(CaptionLeft + 1, TitleHeight);
405 Pen.Color := MainTexture.ColorBevelLight;
406 MoveTo(ClientWidth - CaptionLeft - 2, FrameTop + 2);
407 LineTo(ClientWidth - CaptionLeft - 2, TitleHeight);
408 end;
409 if WideBottom then
410 begin
411 Frame(Canvas, CaptionLeft, FrameBottom, ClientWidth - CaptionLeft - 1,
412 ClientHeight - 1, 0, 0);
413 Fill(Canvas, CaptionLeft + 3, ClientHeight - 3 - (WideFrame - 5),
414 ClientWidth - 2 * (CaptionLeft) - 6, WideFrame - 5, xTexOffset,
415 yTexOffset);
416 Frame(Canvas, CaptionLeft + 1, ClientHeight - WideFrame - 1 + 1,
417 ClientWidth - CaptionLeft - 2, ClientHeight - 2,
418 MainTexture.ColorBevelLight, MainTexture.ColorBevelShade);
419 Frame(Canvas, CaptionLeft + 2, ClientHeight - WideFrame - 1 + 1,
420 ClientWidth - CaptionLeft - 3, ClientHeight - 3,
421 MainTexture.ColorBevelLight, MainTexture.ColorBevelShade);
422 Corner(Canvas, CaptionLeft + 1, ClientHeight - 9, 2, MainTexture);
423 Corner(Canvas, ClientWidth - CaptionLeft - 9, ClientHeight - 9, 3,
424 MainTexture);
425
426 with Canvas do
427 begin
428 Pen.Color := MainTexture.ColorBevelShade;
429 MoveTo(CaptionLeft + 1, ClientHeight - WideFrame);
430 LineTo(CaptionLeft + 1, FrameBottom - 2);
431 Pen.Color := MainTexture.ColorBevelLight;
432 MoveTo(ClientWidth - CaptionLeft - 2, ClientHeight - WideFrame);
433 LineTo(ClientWidth - CaptionLeft - 2, FrameBottom - 2);
434 end;
435 end;
436 end;
437 RisedTextOut(Canvas, Cut - 1, 7, Caption);
438
439 for I := 0 to ControlCount - 1 do
440 if Controls[I].Visible and (Controls[I] is TButtonBase) then
441 begin
442 R := Controls[I].BoundsRect;
443 if (R.Bottom <= TitleHeight) or (R.Top >= InnerBottom) then
444 BtnFrame(Canvas, R, MainTexture);
445 end;
446
447 BitBltCanvas(Canvas, SideFrame, TitleHeight, ClientWidth - 2 * SideFrame,
448 InnerBottom - TitleHeight, Offscreen.Canvas, 0, 0);
449end;
450
451procedure TFramedDlg.InitWindowRegion;
452var
453 r0, r1: HRgn;
454begin
455 if FullCaption then
456 Exit;
457 r0 := CreateRectRgn(0, 0, ClientWidth, ClientHeight);
458 r1 := CreateRectRgn(0, 0, CaptionLeft, TitleHeight - NarrowFrame);
459 CombineRgn(r0, r0, r1, RGN_DIFF);
460 // DeleteObject(r1);
461 r1 := CreateRectRgn(ClientWidth - CaptionLeft, 0, ClientWidth,
462 TitleHeight - NarrowFrame);
463 CombineRgn(r0, r0, r1, RGN_DIFF);
464 // DeleteObject(r1);
465 if WideBottom then
466 begin
467 r1 := CreateRectRgn(0, ClientHeight - (WideFrame - NarrowFrame),
468 CaptionLeft, ClientHeight);
469 CombineRgn(r0, r0, r1, RGN_DIFF);
470 // DeleteObject(r1);
471 r1 := CreateRectRgn(ClientWidth - CaptionLeft,
472 ClientHeight - (WideFrame - NarrowFrame), ClientWidth, ClientHeight);
473 CombineRgn(r0, r0, r1, RGN_DIFF);
474 // DeleteObject(r1);
475 end;
476 SetWindowRgn(Handle, r0, False);
477 // DeleteObject(r0); // causes crash with Windows 95
478end;
479
480procedure TFramedDlg.FillOffscreen(Left, Top, Width, Height: Integer);
481begin
482 Fill(Offscreen.Canvas, Left, Top, Width, Height,
483 SideFrame, TitleHeight);
484end;
485
486procedure TFramedDlg.DoOnResize;
487begin
488 inherited;
489 InnerWidth := Width - 2 * SideFrame;
490 InnerHeight := Height - TitleHeight - NarrowFrame;
491 SmartUpdateContent;
492end;
493
494procedure CreateOffscreen(var Offscreen: TBitmap; Width, Height: Integer);
495begin
496 if not Assigned(Offscreen) then begin
497 Offscreen := TBitmap.Create;
498 Offscreen.PixelFormat := TPixelFormat.pf24bit;
499 end;
500 if (Offscreen.Width <> Width) or (Offscreen.Height <> Height) then begin
501 Offscreen.SetSize(Width, Height);
502 Offscreen.Canvas.Brush.Color := clBlack;
503 Offscreen.Canvas.Brush.Style := TBrushStyle.bsSolid;
504 Offscreen.Canvas.FillRect(0, 0, Offscreen.Width, OffScreen.Height);
505 Offscreen.Canvas.Brush.Style := TBrushStyle.bsClear;
506 end;
507end;
508
509initialization
510
511ShowNewContentProc := nil;
512MainFormKeyDown := nil;
513
514end.
Note: See TracBrowser for help on using the repository browser.