source: trunk/Packages/CevoComponents/BaseWin.pas

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