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

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