source: trunk/Packages/CevoComponents/DrawDlg.pas

Last change on this file was 622, checked in by chronos, 10 months ago
  • Modified: Show windows by default on primary screen if multiple monitors present.
File size: 8.8 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 Color := clBlack;
76 TitleHeight := 0;
77 MoveActive := False;
78 AddHandlerOnVisibleChanged(VisibleChangedHandler);
79 {$IFDEF UNIX}
80 OnDeactivate := DoDeactivate;
81 {$ENDIF}
82end;
83
84destructor TDrawDlg.Destroy;
85begin
86 RemoveHandlerOnVisibleChanged(VisibleChangedHandler);
87 inherited;
88end;
89
90procedure TDrawDlg.OnEraseBkgnd(var Msg: TMessage);
91begin
92 // Full area should be covered by Paint method
93end;
94
95procedure TDrawDlg.MouseDown(Button: TMouseButton; Shift: TShiftState; X,
96 Y: Integer);
97var
98 MousePos1: TPoint;
99 MousePos2: TPoint;
100 NewFormPos: TPoint;
101begin
102 MousePos1 := Mouse.CursorPos;
103 inherited;
104 MousePos2 := Mouse.CursorPos;
105 if not Assigned(OnMouseDown) or not Assigned(OnMouseMove) or not Assigned(OnMouseUp) then begin
106 NewFormPos := ScreenToClient(Mouse.CursorPos);
107 if (NewFormPos.X >= 0) and (NewFormPos.X < Width) and
108 (NewFormPos.Y >= 0) and (NewFormPos.Y < Height) and
109 (NewFormPos.Y < TitleHeight) then begin
110 MoveMousePos := ClientToScreen(Point(X, Y));
111 MoveFormPos := Point(Left, Top);
112 // Activate move only if mouse position was not changed during inherited call
113 if (MousePos1.X = MousePos2.X) and (MousePos1.Y = MousePos2.Y) then begin
114 MoveActive := True;
115 end;
116 end else MoveActive := False;
117 end;
118end;
119
120procedure TDrawDlg.MouseMove(Shift: TShiftState; X, Y: Integer);
121var
122 MousePos: TPoint;
123begin
124 inherited;
125 if MoveActive then begin
126 MousePos := Mouse.CursorPos;
127 SetBounds(MoveFormPos.X + MousePos.X - MoveMousePos.X,
128 MoveFormPos.Y + MousePos.Y - MoveMousePos.Y, Width, Height);
129 end;
130end;
131
132procedure TDrawDlg.MouseUp(Button: TMouseButton; Shift: TShiftState; X,
133 Y: Integer);
134begin
135 MoveActive := False;
136 inherited;
137end;
138
139procedure TDrawDlg.MouseLeave;
140begin
141 MoveActive := False;
142 inherited;
143end;
144
145procedure TDrawDlg.KeyDown(var Key: Word; Shift: TShiftState);
146begin
147 if Key = VK_ESCAPE then Close;
148 inherited;
149end;
150
151procedure TDrawDlg.VisibleChangedHandler(Sender: TObject);
152begin
153 // LCL hides all StayOnTop forms during ShowModal.
154 // Fix this to keep them visible.
155 if (TFormStateType.fsModal in FormState) and Visible then
156 Application.RestoreStayOnTop(True);
157
158 MoveActive := False;
159
160{$IFDEF LCLGTK2}
161 // GTK2 bug workaround https://bugs.freepascal.org/view.php?id=35720
162 {$IFDEF DPI}
163 if Visible then LastMouse.WinControl := Self.NativeForm;
164 {$ELSE}
165 if Visible then LastMouse.WinControl := Self;
166 {$ENDIF}
167{$ENDIF}
168end;
169
170procedure TDrawDlg.DoDeactivate(Sender: TObject);
171begin
172 MoveActive := False;
173end;
174
175procedure TDrawDlg.InitButtons;
176var
177 cix: Integer;
178 // ButtonDownSound, ButtonUpSound: string;
179begin
180 // ButtonDownSound := Sounds.Lookup('BUTTON_DOWN');
181 // ButtonUpSound := Sounds.Lookup('BUTTON_UP');
182 for cix := 0 to ComponentCount - 1 do
183 if Components[cix] is TButtonBase then
184 begin
185 TButtonBase(Components[cix]).Graphic := HGrSystem.Data;
186 // if ButtonDownSound <> '*' then
187 // DownSound := GetSoundsDir + DirectorySeparator + ButtonDownSound + '.wav';
188 // if ButtonUpSound <> '*' then
189 // UpSound := GetSoundsDir + DirectorySeparator + ButtonUpSound + '.wav';
190 if Components[cix] is TButtonA then
191 TButtonA(Components[cix]).Font := UniFont[ftButton];
192 if Components[cix] is TButtonB then
193 TButtonB(Components[cix]).Mask := HGrSystem.Mask;
194 end;
195end;
196
197procedure TDrawDlg.SmartInvalidate;
198var
199 I: Integer;
200 R0, R1: HRgn;
201begin
202 R0 := CreateRectRgn(0, 0, Width, Height);
203 for I := 0 to ControlCount - 1 do
204 if not (Controls[I] is TArea) and Controls[I].Visible then begin
205 with Controls[I].BoundsRect do
206 R1 := CreateRectRgn(Left, Top, Right, Bottom);
207 CombineRgn(R0, R0, R1, RGN_DIFF);
208 DeleteObject(R1);
209 end;
210 InvalidateRgn(Handle, R0, False);
211 DeleteObject(R0);
212end;
213
214procedure TDrawDlg.CenterToScreen;
215begin
216 BoundsRect := Bounds(
217 Screen.PrimaryMonitor.Left + (Screen.PrimaryMonitor.Width - Width) div 2,
218 Screen.PrimaryMonitor.Top + (Screen.PrimaryMonitor.Height - Height) div 2,
219 Width, Height);
220end;
221
222procedure TDrawDlg.CenterToScreen(AWidth, AHeight: Integer);
223begin
224 BoundsRect := Bounds(
225 Screen.PrimaryMonitor.Left + (Screen.PrimaryMonitor.Width - AWidth) div 2,
226 Screen.PrimaryMonitor.Top + (Screen.PrimaryMonitor.Height - AHeight) div 2,
227 Width, Height);
228end;
229
230{ TBaseMessgDlg }
231
232procedure TBaseMessgDlg.FormCreate(Sender: TObject);
233begin
234 Left := Screen.PrimaryMonitor.Left + (Screen.PrimaryMonitor.Width - Width) div 2;
235 Canvas.Font.Assign(UniFont[ftNormal]);
236 Canvas.Brush.Style := TBrushStyle.bsClear;
237 MessgText := '';
238 TopSpace := 0;
239 TitleHeight := Screen.PrimaryMonitor.Height;
240 if csDesigning in ComponentState then Exit;
241 InitButtons;
242end;
243
244procedure TBaseMessgDlg.FormPaint(Sender: TObject);
245var
246 I, cix: Integer;
247begin
248 if csDesigning in ComponentState then Exit;
249 PaintBackground(Canvas, 3 + Border, 3 + Border, Width - (6 + 2 * Border),
250 Height - (6 + 2 * Border), Width, Height);
251 for I := 0 to Border do
252 Frame(Canvas, I, I, Width - 1 - I, Height - 1 - I, $000000, $000000);
253 Frame(Canvas, Border + 1, Border + 1, Width - (2 + Border),
254 Height - (2 + Border), MainTexture.ColorBevelLight,
255 MainTexture.ColorBevelShade);
256 Frame(Canvas, 2 + Border, 2 + Border, Width - (3 + Border),
257 Height - (3 + Border), MainTexture.ColorBevelLight,
258 MainTexture.ColorBevelShade);
259 SplitText(False);
260
261 for cix := 0 to ControlCount - 1 do
262 if (Controls[cix].Visible) and (Controls[cix] is TButtonBase) then
263 BtnFrame(Canvas, Controls[cix].BoundsRect, MainTexture);
264end;
265
266procedure TBaseMessgDlg.SplitText(Preview: Boolean);
267var
268 Start, Stop, OrdinaryStop, LinesCount: Integer;
269 S: string;
270begin
271 Start := 1;
272 LinesCount := 0;
273 while Start < Length(MessgText) do
274 begin
275 Stop := Start;
276 while (Stop < Length(MessgText)) and (MessgText[Stop] <> '\') and
277 (BiColorTextWidth(Canvas, Copy(MessgText, Start, Stop - Start + 1)) <
278 Width - 56) do
279 Inc(Stop);
280 if Stop <> Length(MessgText) then
281 begin
282 OrdinaryStop := Stop;
283 repeat
284 Dec(OrdinaryStop)
285 until (MessgText[OrdinaryStop + 1] = ' ') or
286 (MessgText[OrdinaryStop + 1] = '\');
287 if (OrdinaryStop + 1 - Start) * 2 >= Stop - Start then
288 Stop := OrdinaryStop;
289 end;
290 if not Preview then
291 begin
292 S := Copy(MessgText, Start, Stop - Start + 1);
293 LoweredTextOut(Canvas, -1, MainTexture,
294 (Width - BiColorTextWidth(Canvas, S)) div 2,
295 19 + Border + TopSpace + LinesCount * MessageLineSpacing, S);
296 end;
297 Start := Stop + 2;
298 Inc(LinesCount);
299 end;
300 if Preview then
301 Lines := LinesCount;
302end;
303
304procedure TBaseMessgDlg.CorrectHeight;
305var
306 I: Integer;
307 NewHeight: Integer;
308 NewTop: Integer;
309begin
310 NewHeight := 72 + Border + TopSpace + Lines * MessageLineSpacing;
311 NewTop := Screen.PrimaryMonitor.Top + (Screen.PrimaryMonitor.Height - NewHeight) div 2;
312 BoundsRect := Bounds(Left, NewTop, Width, NewHeight);
313 for I := 0 to ControlCount - 1 do
314 Controls[I].Top := NewHeight - (34 + Border);
315end;
316
317end.
318
319
Note: See TracBrowser for help on using the repository browser.