source: branches/zoom/Packages/CevoComponents/DrawDlg.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: 9.0 KB
Line 
1unit DrawDlg;
2
3interface
4
5uses
6 Classes, SysUtils, LCLIntf, LCLType, {$IFDEF UNIX}LMessages,{$ENDIF}
7 Messages, ButtonBase, ButtonA, ButtonB, Area, ScreenTools
8 {$IFDEF LCLGTK2}, Gtk2Globals{$ENDIF},
9 {$IFDEF DPI}Dpi.Forms, Dpi.Common, Dpi.Graphics, Dpi.Controls{$ELSE}
10 Forms, Graphics, Controls{$ENDIF};
11
12type
13 { TDrawDlg }
14
15 TDrawDlg = class(TForm)
16 private
17 MoveFormPos: TPoint;
18 MoveMousePos: TPoint;
19 MoveActive: Boolean;
20 procedure VisibleChangedHandler(Sender: TObject);
21 procedure DoDeactivate(Sender: TObject);
22 protected
23 // Defines area to grip the window for moving (from top)
24 TitleHeight: Integer;
25 procedure InitButtons;
26 procedure OnEraseBkgnd(var Msg: TMessage); message WM_ERASEBKGND;
27 procedure MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
28 override;
29 procedure MouseMove(Shift: TShiftState; X, Y: Integer); override;
30 procedure MouseUp(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); override;
31 procedure MouseLeave; override;
32 procedure KeyDown(var Key: Word; Shift: TShiftState); override;
33 public
34 constructor Create(AOwner: TComponent); override;
35 destructor Destroy; override;
36 procedure SmartInvalidate; virtual;
37 procedure CenterToScreen; overload;
38 procedure CenterToScreen(AWidth, AHeight: Integer); overload;
39 end;
40
41 { TBaseMessgDlg }
42
43 TBaseMessgDlg = class(TDrawDlg)
44 procedure FormCreate(Sender: TObject);
45 procedure FormPaint(Sender: TObject);
46 protected
47 Lines: Integer;
48 TopSpace: Integer;
49 procedure SplitText(Preview: Boolean);
50 procedure CorrectHeight;
51 public
52 MessgText: string;
53 end;
54
55const
56 Border = 3;
57 MessageLineSpacing = 20;
58
59procedure Register;
60
61
62implementation
63
64procedure Register;
65begin
66 RegisterNoIcon([TDrawDlg]);
67 RegisterNoIcon([TBaseMessgDlg]);
68end;
69
70{ TDrawDlg }
71
72constructor TDrawDlg.Create(AOwner: TComponent);
73begin
74 inherited;
75
76 // Make all dialogs resizable
77 //BorderStyle := TBorderStyle.bsSizeable;
78 //BorderIcons := [TBorderIcon.biSystemMenu, TBorderIcon.biMinimize, TBorderIcon.biMaximize];
79
80 Color := clBlack;
81 TitleHeight := 0;
82 MoveActive := False;
83 AddHandlerOnVisibleChanged(VisibleChangedHandler);
84 {$IFDEF UNIX}
85 OnDeactivate := DoDeactivate;
86 {$ENDIF}
87end;
88
89destructor TDrawDlg.Destroy;
90begin
91 RemoveHandlerOnVisibleChanged(VisibleChangedHandler);
92 inherited;
93end;
94
95procedure TDrawDlg.OnEraseBkgnd(var Msg: TMessage);
96begin
97 // Full area should be covered by Paint method
98end;
99
100procedure TDrawDlg.MouseDown(Button: TMouseButton; Shift: TShiftState; X,
101 Y: Integer);
102var
103 MousePos1: TPoint;
104 MousePos2: TPoint;
105 NewFormPos: TPoint;
106begin
107 MousePos1 := Mouse.CursorPos;
108 inherited;
109 MousePos2 := Mouse.CursorPos;
110 if not Assigned(OnMouseDown) or not Assigned(OnMouseMove) or not Assigned(OnMouseUp) then begin
111 NewFormPos := ScreenToClient(Mouse.CursorPos);
112 if (NewFormPos.X >= 0) and (NewFormPos.X < Width) and
113 (NewFormPos.Y >= 0) and (NewFormPos.Y < Height) and
114 (NewFormPos.Y < TitleHeight) then begin
115 MoveMousePos := ClientToScreen(Point(X, Y));
116 MoveFormPos := Point(Left, Top);
117 // Activate move only if mouse position was not changed during inherited call
118 if (MousePos1.X = MousePos2.X) and (MousePos1.Y = MousePos2.Y) then begin
119 MoveActive := True;
120 end;
121 end else MoveActive := False;
122 end;
123end;
124
125procedure TDrawDlg.MouseMove(Shift: TShiftState; X, Y: Integer);
126var
127 MousePos: TPoint;
128begin
129 inherited;
130 if MoveActive then begin
131 MousePos := Mouse.CursorPos;
132 SetBounds(MoveFormPos.X + MousePos.X - MoveMousePos.X,
133 MoveFormPos.Y + MousePos.Y - MoveMousePos.Y, Width, Height);
134 end;
135end;
136
137procedure TDrawDlg.MouseUp(Button: TMouseButton; Shift: TShiftState; X,
138 Y: Integer);
139begin
140 MoveActive := False;
141 inherited;
142end;
143
144procedure TDrawDlg.MouseLeave;
145begin
146 MoveActive := False;
147 inherited;
148end;
149
150procedure TDrawDlg.KeyDown(var Key: Word; Shift: TShiftState);
151begin
152 if Key = VK_ESCAPE then Close;
153 inherited;
154end;
155
156procedure TDrawDlg.VisibleChangedHandler(Sender: TObject);
157begin
158 // LCL hides all StayOnTop forms during ShowModal.
159 // Fix this to keep them visible.
160 if (TFormStateType.fsModal in FormState) and Visible then
161 Application.RestoreStayOnTop(True);
162
163 MoveActive := False;
164
165{$IFDEF LCLGTK2}
166 // GTK2 bug workaround https://bugs.freepascal.org/view.php?id=35720
167 {$IFDEF DPI}
168 if Visible then LastMouse.WinControl := Self.NativeForm;
169 {$ELSE}
170 if Visible then LastMouse.WinControl := Self;
171 {$ENDIF}
172{$ENDIF}
173end;
174
175procedure TDrawDlg.DoDeactivate(Sender: TObject);
176begin
177 MoveActive := False;
178end;
179
180procedure TDrawDlg.InitButtons;
181var
182 cix: Integer;
183 // ButtonDownSound, ButtonUpSound: string;
184begin
185 // ButtonDownSound := Sounds.Lookup('BUTTON_DOWN');
186 // ButtonUpSound := Sounds.Lookup('BUTTON_UP');
187 for cix := 0 to ComponentCount - 1 do
188 if Components[cix] is TButtonBase then
189 begin
190 TButtonBase(Components[cix]).Graphic := HGrSystem.Data;
191 // if ButtonDownSound <> '*' then
192 // DownSound := GetSoundsDir + DirectorySeparator + ButtonDownSound + '.wav';
193 // if ButtonUpSound <> '*' then
194 // UpSound := GetSoundsDir + DirectorySeparator + ButtonUpSound + '.wav';
195 if Components[cix] is TButtonA then
196 TButtonA(Components[cix]).Font := UniFont[ftButton];
197 if Components[cix] is TButtonB then
198 TButtonB(Components[cix]).Mask := HGrSystem.Mask;
199 end;
200end;
201
202procedure TDrawDlg.SmartInvalidate;
203var
204 I: Integer;
205 R0, R1: HRgn;
206begin
207 R0 := CreateRectRgn(0, 0, Width, Height);
208 for I := 0 to ControlCount - 1 do
209 if not (Controls[I] is TArea) and Controls[I].Visible then begin
210 with Controls[I].BoundsRect do
211 R1 := CreateRectRgn(Left, Top, Right, Bottom);
212 CombineRgn(R0, R0, R1, RGN_DIFF);
213 DeleteObject(R1);
214 end;
215 InvalidateRgn(Handle, R0, False);
216 DeleteObject(R0);
217end;
218
219procedure TDrawDlg.CenterToScreen;
220begin
221 BoundsRect := Bounds(
222 Screen.PrimaryMonitor.Left + (Screen.PrimaryMonitor.Width - Width) div 2,
223 Screen.PrimaryMonitor.Top + (Screen.PrimaryMonitor.Height - Height) div 2,
224 Width, Height);
225end;
226
227procedure TDrawDlg.CenterToScreen(AWidth, AHeight: Integer);
228begin
229 BoundsRect := Bounds(
230 Screen.PrimaryMonitor.Left + (Screen.PrimaryMonitor.Width - AWidth) div 2,
231 Screen.PrimaryMonitor.Top + (Screen.PrimaryMonitor.Height - AHeight) div 2,
232 Width, Height);
233end;
234
235{ TBaseMessgDlg }
236
237procedure TBaseMessgDlg.FormCreate(Sender: TObject);
238begin
239 Left := Screen.PrimaryMonitor.Left + (Screen.PrimaryMonitor.Width - Width) div 2;
240 Canvas.Font.Assign(UniFont[ftNormal]);
241 Canvas.Brush.Style := TBrushStyle.bsClear;
242 MessgText := '';
243 TopSpace := 0;
244 TitleHeight := Screen.PrimaryMonitor.Height;
245 if csDesigning in ComponentState then Exit;
246 InitButtons;
247end;
248
249procedure TBaseMessgDlg.FormPaint(Sender: TObject);
250var
251 I, cix: Integer;
252begin
253 if csDesigning in ComponentState then Exit;
254 PaintBackground(Canvas, 3 + Border, 3 + Border, Width - (6 + 2 * Border),
255 Height - (6 + 2 * Border), Width, Height);
256 for I := 0 to Border do
257 Frame(Canvas, I, I, Width - 1 - I, Height - 1 - I, $000000, $000000);
258 Frame(Canvas, Border + 1, Border + 1, Width - (2 + Border),
259 Height - (2 + Border), MainTexture.ColorBevelLight,
260 MainTexture.ColorBevelShade);
261 Frame(Canvas, 2 + Border, 2 + Border, Width - (3 + Border),
262 Height - (3 + Border), MainTexture.ColorBevelLight,
263 MainTexture.ColorBevelShade);
264 SplitText(False);
265
266 for cix := 0 to ControlCount - 1 do
267 if (Controls[cix].Visible) and (Controls[cix] is TButtonBase) then
268 BtnFrame(Canvas, Controls[cix].BoundsRect, MainTexture);
269end;
270
271procedure TBaseMessgDlg.SplitText(Preview: Boolean);
272var
273 Start, Stop, OrdinaryStop, LinesCount: Integer;
274 S: string;
275begin
276 Start := 1;
277 LinesCount := 0;
278 while Start < Length(MessgText) do
279 begin
280 Stop := Start;
281 while (Stop < Length(MessgText)) and (MessgText[Stop] <> '\') and
282 (BiColorTextWidth(Canvas, Copy(MessgText, Start, Stop - Start + 1)) <
283 Width - 56) do
284 Inc(Stop);
285 if Stop <> Length(MessgText) then
286 begin
287 OrdinaryStop := Stop;
288 repeat
289 Dec(OrdinaryStop)
290 until (MessgText[OrdinaryStop + 1] = ' ') or
291 (MessgText[OrdinaryStop + 1] = '\');
292 if (OrdinaryStop + 1 - Start) * 2 >= Stop - Start then
293 Stop := OrdinaryStop;
294 end;
295 if not Preview then
296 begin
297 S := Copy(MessgText, Start, Stop - Start + 1);
298 LoweredTextOut(Canvas, -1, MainTexture,
299 (Width - BiColorTextWidth(Canvas, S)) div 2,
300 19 + Border + TopSpace + LinesCount * MessageLineSpacing, S);
301 end;
302 Start := Stop + 2;
303 Inc(LinesCount);
304 end;
305 if Preview then
306 Lines := LinesCount;
307end;
308
309procedure TBaseMessgDlg.CorrectHeight;
310var
311 I: Integer;
312 NewHeight: Integer;
313 NewTop: Integer;
314begin
315 NewHeight := 72 + Border + TopSpace + Lines * MessageLineSpacing;
316 NewTop := Screen.PrimaryMonitor.Top + (Screen.PrimaryMonitor.Height - NewHeight) div 2;
317 BoundsRect := Bounds(Left, NewTop, Width, NewHeight);
318 for I := 0 to ControlCount - 1 do
319 Controls[I].Top := NewHeight - (34 + Border);
320end;
321
322end.
323
324
Note: See TracBrowser for help on using the repository browser.