source: tags/1.3.1/Packages/CevoComponents/DrawDlg.pas

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