source: trunk/Packages/CevoComponents/BaseWin.pas

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