source: trunk/Packages/CevoComponents/DrawDlg.pas

Last change on this file was 554, checked in by chronos, 2 days ago
  • Added: TButtonG class as a button class component referencing TGraphicSet item.
  • Modified: Code cleanup.
File size: 9.1 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 TitleHeight: Integer;
24 // defines area to grip the window for moving (from top)
25 procedure InitButtons;
26 procedure OnEraseBkgnd(var Msg: TMessage); message WM_ERASEBKGND;
27 procedure OnHitTest(var Msg: TMessage); message WM_NCHITTEST;
28 procedure MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
29 override;
30 procedure MouseMove(Shift: TShiftState; X, Y: Integer); override;
31 procedure MouseUp(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); override;
32 procedure MouseLeave; override;
33 procedure KeyDown(var Key: Word; Shift: TShiftState); override;
34 public
35 constructor Create(AOwner: TComponent); override;
36 destructor Destroy; override;
37 procedure SmartInvalidate; virtual;
38 end;
39
40 { TBaseMessgDlg }
41
42 TBaseMessgDlg = class(TDrawDlg)
43 procedure FormCreate(Sender: TObject);
44 procedure FormPaint(Sender: TObject);
45 protected
46 Lines: Integer;
47 TopSpace: Integer;
48 procedure SplitText(Preview: Boolean);
49 procedure CorrectHeight;
50 public
51 MessgText: string;
52 end;
53
54const
55 Border = 3;
56 MessageLineSpacing = 20;
57
58procedure Register;
59
60
61implementation
62
63procedure Register;
64begin
65 RegisterNoIcon([TDrawDlg]);
66 RegisterNoIcon([TBaseMessgDlg]);
67end;
68
69{ TDrawDlg }
70
71constructor TDrawDlg.Create(AOwner: TComponent);
72begin
73 inherited;
74 Color := clBlack;
75 TitleHeight := 0;
76 MoveActive := False;
77 AddHandlerOnVisibleChanged(VisibleChangedHandler);
78 {$IFDEF UNIX}
79 OnDeactivate := DoDeactivate;
80 {$ENDIF}
81end;
82
83destructor TDrawDlg.Destroy;
84begin
85 RemoveHandlerOnVisibleChanged(VisibleChangedHandler);
86 inherited;
87end;
88
89procedure TDrawDlg.OnEraseBkgnd(var Msg: TMessage);
90begin
91 // Full area should be covered by Paint method
92end;
93
94procedure TDrawDlg.OnHitTest(var Msg: TMessage);
95var
96 I: integer;
97 ControlBounds: TRect;
98 Pos: TPoint;
99begin
100 if BorderStyle <> TBorderStyle.bsNone then
101 inherited
102 else
103 begin
104 Pos := Point(ScaleFromNative(Integer(Msg.LParam and $ffff)),
105 ScaleFromNative(Integer((Msg.LParam shr 16) and $ffff)));
106 if Pos.Y >= Top + TitleHeight then
107 Msg.Result := HTCLIENT
108 else
109 begin
110 for I := 0 to ControlCount - 1 do
111 if Controls[I].Visible then
112 begin
113 ControlBounds := Controls[I].BoundsRect;
114 if (Pos.X >= Left + ControlBounds.Left) and
115 (Pos.X < Left + ControlBounds.Right) and
116 (Pos.Y >= Top + ControlBounds.Top) and
117 (Pos.Y < Top + ControlBounds.Bottom) then
118 begin
119 Msg.result := HTCLIENT;
120 Exit;
121 end;
122 end;
123 Msg.Result := HTCAPTION;
124 end;
125 end;
126end;
127
128procedure TDrawDlg.MouseDown(Button: TMouseButton; Shift: TShiftState; X,
129 Y: Integer);
130var
131 MousePos1: TPoint;
132 MousePos2: TPoint;
133{$IFDEF UNIX}
134 NewFormPos: TPoint;
135{$ENDIF}
136begin
137 MousePos1 := Mouse.CursorPos;
138 inherited;
139 MousePos2 := Mouse.CursorPos;
140 {$IFDEF UNIX}
141 // Only if client is not doing own mouse move handling
142 if not Assigned(OnMouseDown) or not Assigned(OnMouseMove) or not Assigned(OnMouseUp) then begin
143 // HitTest is not supported under Linux GTK2 so use form inside move mechanizm
144 NewFormPos := ScreenToClient(Mouse.CursorPos);
145 if (NewFormPos.X >= 0) and (NewFormPos.X < Width) and
146 (NewFormPos.Y >= 0) and (NewFormPos.Y < Height) and
147 (NewFormPos.Y < TitleHeight) then begin
148 MoveMousePos := ClientToScreen(Point(X, Y));
149 MoveFormPos := Point(Left, Top);
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 // LCL hides all StayOnTop forms during ShowModal.
194 // Fix this to keep them visible.
195 if (TFormStateType.fsModal in FormState) and Visible then
196 Application.RestoreStayOnTop(True);
197
198 MoveActive := False;
199
200{$IFDEF LCLGTK2}
201 // GTK2 bug workaround https://bugs.freepascal.org/view.php?id=35720
202 {$IFDEF DPI}
203 if Visible then LastMouse.WinControl := Self.NativeForm;
204 {$ELSE}
205 if Visible then LastMouse.WinControl := Self;
206 {$ENDIF}
207{$ENDIF}
208end;
209
210procedure TDrawDlg.DoDeactivate(Sender: TObject);
211begin
212 MoveActive := False;
213end;
214
215procedure TDrawDlg.InitButtons;
216var
217 cix: Integer;
218 // ButtonDownSound, ButtonUpSound: string;
219begin
220 // ButtonDownSound := Sounds.Lookup('BUTTON_DOWN');
221 // ButtonUpSound := Sounds.Lookup('BUTTON_UP');
222 for cix := 0 to ComponentCount - 1 do
223 if Components[cix] is TButtonBase then
224 begin
225 TButtonBase(Components[cix]).Graphic := HGrSystem.Data;
226 // if ButtonDownSound <> '*' then
227 // DownSound := GetSoundsDir + DirectorySeparator + ButtonDownSound + '.wav';
228 // if ButtonUpSound <> '*' then
229 // UpSound := GetSoundsDir + DirectorySeparator + ButtonUpSound + '.wav';
230 if Components[cix] is TButtonA then
231 TButtonA(Components[cix]).Font := UniFont[ftButton];
232 if Components[cix] is TButtonB then
233 TButtonB(Components[cix]).Mask := HGrSystem.Mask;
234 end;
235end;
236
237procedure TDrawDlg.SmartInvalidate;
238var
239 i: Integer;
240 r0, r1: HRgn;
241begin
242 r0 := CreateRectRgn(0, 0, Width, Height);
243 for i := 0 to ControlCount - 1 do
244 if not (Controls[i] is TArea) and Controls[i].Visible then
245 begin
246 with Controls[i].BoundsRect do
247 r1 := CreateRectRgn(Left, Top, Right, Bottom);
248 CombineRgn(r0, r0, r1, RGN_DIFF);
249 DeleteObject(r1);
250 end;
251 InvalidateRgn(Handle, r0, False);
252 DeleteObject(r0);
253end;
254
255{ TBaseMessgDlg }
256
257procedure TBaseMessgDlg.FormCreate(Sender: TObject);
258begin
259 Left := (Screen.Width - Width) div 2;
260 Canvas.Font.Assign(UniFont[ftNormal]);
261 Canvas.Brush.Style := TBrushStyle.bsClear;
262 MessgText := '';
263 TopSpace := 0;
264 TitleHeight := Screen.Height;
265 if csDesigning in ComponentState then Exit;
266 InitButtons;
267end;
268
269procedure TBaseMessgDlg.FormPaint(Sender: TObject);
270var
271 I, cix: Integer;
272begin
273 if csDesigning in ComponentState then Exit;
274 PaintBackground(Self, 3 + Border, 3 + Border, Width - (6 + 2 * Border),
275 Height - (6 + 2 * Border));
276 for I := 0 to Border do
277 Frame(Canvas, I, I, Width - 1 - I, Height - 1 - I,
278 $000000, $000000);
279 Frame(Canvas, Border + 1, Border + 1, Width - (2 + Border),
280 Height - (2 + Border), MainTexture.ColorBevelLight,
281 MainTexture.ColorBevelShade);
282 Frame(Canvas, 2 + Border, 2 + Border, Width - (3 + Border),
283 Height - (3 + Border), MainTexture.ColorBevelLight,
284 MainTexture.ColorBevelShade);
285 SplitText(False);
286
287 for cix := 0 to ControlCount - 1 do
288 if (Controls[cix].Visible) and (Controls[cix] is TButtonBase) then
289 BtnFrame(Canvas, Controls[cix].BoundsRect, MainTexture);
290end;
291
292procedure TBaseMessgDlg.SplitText(Preview: Boolean);
293var
294 Start, Stop, OrdinaryStop, LinesCount: Integer;
295 S: string;
296begin
297 Start := 1;
298 LinesCount := 0;
299 while Start < Length(MessgText) do
300 begin
301 Stop := Start;
302 while (Stop < Length(MessgText)) and (MessgText[Stop] <> '\') and
303 (BiColorTextWidth(Canvas, Copy(MessgText, Start, Stop - Start + 1)) <
304 Width - 56) do
305 Inc(Stop);
306 if Stop <> Length(MessgText) then
307 begin
308 OrdinaryStop := Stop;
309 repeat
310 Dec(OrdinaryStop)
311 until (MessgText[OrdinaryStop + 1] = ' ') or
312 (MessgText[OrdinaryStop + 1] = '\');
313 if (OrdinaryStop + 1 - Start) * 2 >= Stop - Start then
314 Stop := OrdinaryStop;
315 end;
316 if not Preview then
317 begin
318 S := Copy(MessgText, Start, Stop - Start + 1);
319 LoweredTextOut(Canvas, -1, MainTexture,
320 (Width - BiColorTextWidth(Canvas, S)) div 2,
321 19 + Border + TopSpace + LinesCount * MessageLineSpacing, S);
322 end;
323 Start := Stop + 2;
324 Inc(LinesCount);
325 end;
326 if Preview then
327 Lines := LinesCount;
328end;
329
330procedure TBaseMessgDlg.CorrectHeight;
331var
332 I: Integer;
333begin
334 Height := 72 + Border + TopSpace + Lines * MessageLineSpacing;
335 Top := (Screen.Height - Height) div 2;
336 for i := 0 to ControlCount - 1 do
337 Controls[i].Top := Height - (34 + Border);
338end;
339
340end.
341
342
Note: See TracBrowser for help on using the repository browser.