MathgeomGLS
928 строк · 24.9 Кб
1unit OverlayImage;
2(* Base Component for Graphing
3TOverlayImage based on Renate Schaaf's code
4Specialty: Has methods for temporary flickerless speedy overlayed drawings
5like zoom rectangles or even sprites.
6Use the usual canvas routines with the prefix Overlay, like OverlayEllipse,
7OverlayRectangle, etc.
8Exceptions:
9The analog of Moveto/Lineto is as a command OverlayLine.
10The analog of Canvas.Draw(x,y,MyGraphic) is OvelayDraw(DestRect,MyGraphic).
11After finished with the overlayed (possibly compound) drawing,
12call ShowOverlay. The next overlayed drawing
13will start from scratch *)
14
15interface
16
17uses
18Winapi.Windows,
19Winapi.Messages,
20System.Types,
21System.UITypes,
22System.SysUtils,
23System.Classes,
24Vcl.Graphics,
25Vcl.Controls,
26Vcl.Forms,
27Vcl.Dialogs,
28Vcl.Clipbrd;
29
30type
31TOverlayImage = class(TGraphicControl)
32private
33fBitmap: TBitmap; //Bitmap for the persistant Drawing
34fDrawWidth, fDrawHeight: Integer;
35fScreenBitmap: TBitmap; //Bitmap that gets blasted to screen
36fLockCount: Integer;
37fDrawing: Boolean;
38fTempDrawing: Boolean;
39fOverlayed: Boolean;
40fClipRect: TRect; //ClipRect for fBitmap
41fTempRect: TRect; //fTempRect is fClipRect translated to screen
42//coordinates
43fClipRgn: HRgn; //corresponding region
44fOldRgn, fNewRgn: HRgn; //regions to optimize overlaid drawing
45fxoff, fyoff: Integer;
46(* scaling data, bmp to screen, rsp. device
47regions have to be given in device coordinates.
48if the control is not located at top=left=0 in
49the parent, those will be offset from the control coordinates *)
50fOrgFontChanged,
51fOrgPenChanged,
52fOrgBrushChanged,
53fOrgPaint,
54fOnMouseLeave,
55fOnMouseEnter: TNotifyEvent;
56fOnTempPaint: TNotifyEvent; //Something that should always be added
57procedure fBitmapChanged(Sender: TObject);
58procedure fFontChanged(Sender: TObject);
59procedure fPenChanged(Sender: TObject);
60procedure fBrushChanged(Sender: TObject);
61function GetCanvas: TCanvas;
62function GetTempCanvas: TCanvas;
63function GetMetafileCanvas: TCanvas;
64function GetFont: TFont;
65function GetPen: TPen;
66function GetBrush: TBrush;
67function GetTempFont: TFont;
68function GetTempBrush: TBrush;
69function GetTempPen: TPen;
70procedure SetFont(Value: TFont);
71procedure SetPen(Value: TPen);
72procedure SetBrush(Value: TBrush);
73procedure SetTempFont(Value: TFont);
74procedure SetTempBrush(Value: TBrush);
75procedure SetTempPen(Value: TPen);
76procedure GetOffSet;
77procedure fTempCanvasChanging;
78protected
79fMetaFileCanvas: TMetaFileCanvas;
80fMetaFile: TMetaFile;
81procedure Paint; override;
82procedure Notification(AComponent: TComponent; Operation: TOperation); override;
83procedure CMMouseLeave(var msg: TMessage); message CM_MouseLeave;
84procedure CMMouseEnter(var msg: TMessage); message CM_MouseEnter;
85procedure WMWindowPosChanged(var msg: TMessage); message WM_WINDOWPOSCHANGED;
86procedure SizeChanged; virtual;
87procedure Loaded; override;
88(* Canvas for overlaid drawings like
89zoom rectangles, or helper shapes which aren't part of
90the actual drawings. Now protected, because it can't be
91used properly without some specific precautions *)
92property OverlayCanvas: TCanvas read GetTempCanvas;
93public
94constructor Create(AOwner: TComponent); override;
95destructor Destroy; override;
96{ Define a new rectangular clip region. The previous region
97is discarded.}
98procedure NewClipRegion(Value: TRect);
99{ Add a rectangle to the current clip region }
100procedure AddClipRegion(Value: TRect);
101{ Subtract a rectangular region from the current clip region }
102procedure SubtractClipRegion(Value: TRect);
103{Intersect the current clip region with the region given by Value}
104procedure IntersectClipRegion(Value: TRect);
105{ Call when the component is inside a scrollbox to adjust to scroll. Since
106the usual scrollbox has no OnScroll event, there is a derived one
107(<See class=TScrollEventBox>) in this same unit }
108procedure AdjustToScroll;
109{ Drawing surrounded by LockUpdate and UnlockUpdate is not
110updated to the screen immediately. Nested calls are OK,
111Screen will be updated on the last UnlockUpdate. This speeds up
112compound drawing}
113procedure LockUpdate;
114{ Drawing surrounded by LockUpdate and UnlockUpdate is not
115updated to the screen immediately. Nested calls are OK,
116Screen will be updated on the last UnlockUpdate. This speeds up
117compound drawing}
118procedure UnlockUpdate;
119{ A call to ShowOverlay puts the current drawing on the
120Overlaycanvas to screen. The next Overlaycanvas call, or a call of
121<See method=HideOverlay> clears the canvas }
122procedure ShowOverlay;
123{ Clears the overlayed canvas. Call, if no overlayed drawing is needed anymore,
124as this speeds up normal drawing }
125procedure HideOverlay;
126{ Clears the Canvas, sets background to AColor }
127procedure Clear(Acanvas: TCanvas; AColor: TColor); // overload; virtual;
128{ Saves any drawing on the <See property=MetafileCanvas> to file }
129procedure SaveMetafile(const filename: string);
130{ Releases memory for metafile support }
131procedure EraseMetafile;
132{ For speed optimized drawings on the overlayed canvas use this
133analogon of the TCanvas method }
134procedure OverlayCopyRect(dest: TRect; Canvas: TCanvas; Source: TRect);
135{ For speed optimized drawings on the overlayed canvas use this
136analogon of the TCanvas method }
137procedure OverlayDraw(dest: TRect; Graphic: TGraphic);
138{ For speed optimized drawings on the overlayed canvas use this
139analogon of the TCanvas method }
140procedure OverlayFillRect(const Rect: TRect);
141{ For speed optimized drawings on the overlayed canvas use this
142analogon of the TCanvas method }
143procedure OverlayFrameRect(const Rect: TRect);
144{ For speed optimized drawings on the overlayed canvas use this
145analogon of the TCanvas method }
146procedure OverlayLine(x1, y1, x2, y2: Integer);
147{ For speed optimized drawings on the overlayed canvas use this
148analogon of the TCanvas method }
149procedure OverlayPolygon(Points: array of TPoint);
150{ For speed optimized drawings on the overlayed canvas use this
151analogon of the TCanvas method }
152procedure OverlayPolyline(Points: array of TPoint);
153{ For speed optimized drawings on the overlayed canvas use this
154analogon of the TCanvas method }
155procedure OverlayEllipse(x1, y1, x2, y2: Integer);
156{ For speed optimized drawings on the overlayed canvas use this
157analogon of the TCanvas method }
158procedure OverlayRectangle(x1, y1, x2, y2: Integer);
159{ For speed optimized drawings on the overlayed canvas use this
160analogon of the TCanvas method }
161procedure OverlayRoundRect(x1, y1, x2, y2, X3, Y3: Integer);
162{ For speed optimized drawings on the overlayed canvas use this
163analogon of the TCanvas method }
164procedure OverlayTextOut(x, y: Integer; const s: string);
165{ Actually the canvas of the offscreen fbitmap }
166property Canvas: TCanvas read GetCanvas;
167{ In case you'd like to draw a metafile, just use this property.
168It will be created, if needed }
169property MetafileCanvas: TCanvas read GetMetafileCanvas;
170{ The metafile generated by drawing on <See property=MetafileCanvas> }
171property Metafile: TMetaFile read fMetaFile;
172{ This Bitmap which holds the current main (not overlayed) drawing }
173property Bitmap: TBitmap read fBitmap;
174property OverlayBrush: TBrush read GetTempBrush write SetTempBrush;
175property OverlayPen: TPen read GetTempPen write SetTempPen;
176property OverlayFont: TFont read GetTempFont write SetTempFont;
177published
178property Align;
179{ Pen, brush and font properties for the main drawing. To set the corresponding
180for the overlayed canvas use OverlayPen. For the Metafile canvas use MetafileCanvas.Pen,
181as usual }
182property Pen: TPen read GetPen write SetPen;
183{ Pen, brush and font properties for the main drawing. To set the corresponding
184for the overlayed canvas use OverlayBrush. For the Metafile canvas use MetafileCanvas.Brush,
185as usual }
186property Brush: TBrush read GetBrush write SetBrush;
187{ Pen, brush and font properties for the main drawing. To set the corresponding
188for the overlayed canvas use OverlayFont. For the Metafile canvas use MetafileCanvas.Font,
189as usual }
190property Font: TFont read GetFont write SetFont;
191{ Events}
192property OnMouseDown;
193property OnMouseUp;
194property OnMouseMove;
195property OnResize;
196{ If you want to see a persistent drawing on the overlayed canvas, use this
197event for the drawing commands }
198property OnOverlayPaint: TNotifyEvent read fOnTempPaint write fOnTempPaint;
199{ Event which fires if the mouse leaves the control. Note: There must be space
200between the control and the boundary of the parent for this to work }
201property OnMouseLeave: TNotifyEvent read fOnMouseLeave write fOnMouseLeave;
202{ Event which fires if the mouse enters the control }
203property OnMouseEnter: TNotifyEvent read fOnMouseEnter write fOnMouseEnter;
204end;
205
206(* Had to create an extra scrollbox, which fires scrollevents, because
207when the TOverlayImage is scrolled, the offsets for the device regions
208have to be recomputed. See procedure TOverlayImage.AdjustToScroll *)
209TScrollEventBox = class(TScrollbox)
210private
211fOnScroll: TNotifyEvent;
212procedure WMHScroll(var Message: TWMHScroll); message WM_HSCROLL;
213procedure WMVScroll(var Message: TWMVScroll); message WM_VSCROLL;
214published
215{ Event fires on vertical or horizontal scroll }
216property OnScroll: TNotifyEvent read fOnScroll write fOnScroll;
217end;
218
219procedure Register;
220
221//==============================================================
222implementation
223//==============================================================
224
225constructor TOverlayImage.Create;
226begin
227inherited;
228if not (csDesigning in ComponentState) then
229ControlStyle := ControlStyle + [csOpaque];
230{avoids flicker}
231fDrawWidth := 0;
232fDrawHeight := 0;
233fScreenBitmap := TBitmap.Create;
234fBitmap := TBitmap.Create;
235fOrgPenChanged := fBitmap.Canvas.Pen.OnChange;
236fOrgFontChanged := fBitmap.Canvas.Font.OnChange;
237fOrgBrushChanged := fBitmap.Canvas.Brush.OnChange;
238fBitmap.OnChange := fBitmapChanged;
239fLockCount := 0;
240fOrgPaint := nil;
241fMetaFileCanvas := nil;
242fMetaFile := nil;
243fClipRgn := 0;
244fOldRgn := 0;
245fNewRgn := 0;
246if csDesigning in ComponentState then
247begin
248Width := 50;
249Height := 50;
250end;
251fClipRect := Rect(0, 0, Width, Height);
252fTempRect := Rect(0, 0, Width, Height);
253fTempDrawing := False;
254end;
255
256destructor TOverlayImage.Destroy;
257begin
258if fBitmap <> nil then fBitmap.Free;
259if fBitmap <> nil then fScreenBitmap.Free;
260if fMetaFileCanvas <> nil then fMetaFileCanvas.Free;
261if fMetaFile <> nil then fMetaFile.Free;
262if fClipRgn <> 0 then DeleteObject(fClipRgn);
263if fOldRgn <> 0 then DeleteObject(fOldRgn);
264if fNewRgn <> 0 then DeleteObject(fNewRgn);
265inherited;
266end;
267
268procedure TOverlayImage.Paint;
269begin
270// inherited;
271if (csDesigning in ComponentState) then
272inherited Canvas.FrameRect(Rect(0, 0, Width, Height))
273else
274begin
275if not fDrawing then
276begin
277fDrawing := True;
278try
279if assigned(fOnTempPaint) then
280begin
281BitBlt(fScreenBitmap.Canvas.Handle, 0, 0, fDrawWidth, fDrawHeight,
282fBitmap.Canvas.Handle, 0, 0, SRCCopy);
283fTempDrawing := True;
284fOnTempPaint(self);
285fTempDrawing := False;
286BitBlt(inherited Canvas.Handle, 0, 0, fDrawWidth, fDrawHeight,
287fScreenBitmap.Canvas.Handle,
2880, 0, SRCCopy);
289end
290else
291if fOverlayed then
292BitBlt(inherited Canvas.Handle, 0, 0, fDrawWidth, fDrawHeight,
293fScreenBitmap.Canvas.Handle,
2940, 0, SRCCopy)
295else
296BitBlt(inherited Canvas.Handle, 0, 0, fDrawWidth, fDrawHeight,
297fBitmap.Canvas.Handle, 0, 0, SRCCopy);
298finally
299fDrawing := False;
300end;
301end;
302end;
303end;
304
305function TOverlayImage.GetCanvas;
306begin
307SelectClipRgn(fBitmap.Canvas.Handle, fClipRgn);
308Result := fBitmap.Canvas;
309end;
310
311
312function TOverlayImage.GetTempCanvas;
313begin
314SelectClipRgn(fScreenBitmap.Canvas.Handle, fNewRgn);
315Result := fScreenBitmap.Canvas;
316end;
317
318procedure TOverlayImage.fTempCanvasChanging;
319begin
320if not fTempDrawing then
321begin
322fTempDrawing := True;
323SelectClipRgn(fScreenBitmap.Canvas.Handle, fOldRgn);
324BitBlt(fScreenBitmap.Canvas.Handle, 0, 0, fDrawWidth, fDrawHeight,
325fBitmap.Canvas.Handle,
3260, 0, SRCCopy);
327fOverlayed := False;
328end;
329end;
330
331procedure TOverlayImage.fBitmapChanged;
332begin
333if not fDrawing then
334begin
335if fOldRgn <> 0 then
336begin
337DeleteObject(fOldRgn);
338fOldRgn := 0;
339end;
340fOverlayed := False;
341invalidate;
342end
343else update;
344{On each bitmap change the picture is invalidated, unless it's
345just being painted already and unless LockUpdate has been called}
346end;
347
348procedure TOverlayImage.fFontChanged(Sender: TObject);
349begin
350fOrgFontChanged(Sender);
351if fMetaFileCanvas <> nil then
352fMetaFileCanvas.Font.assign(fBitmap.Canvas.Font);
353end;
354
355procedure TOverlayImage.fPenChanged(Sender: TObject);
356begin
357fOrgPenChanged(Sender);
358if fMetaFileCanvas <> nil then
359fMetaFileCanvas.Pen.assign(fBitmap.Canvas.Pen);
360end;
361
362procedure TOverlayImage.fBrushChanged(Sender: TObject);
363begin
364fOrgBrushChanged(Sender);
365if fMetaFileCanvas <> nil then
366fMetaFileCanvas.Brush.assign(fBitmap.Canvas.Brush);
367end;
368
369
370function TOverlayImage.GetMetafileCanvas: TCanvas;
371begin
372if fMetaFileCanvas = nil then
373begin
374fMetaFile := TMetaFile.Create;
375fMetaFile.enhanced := True;
376fMetaFile.Height := fBitmap.Height;
377fMetaFile.Width := fBitmap.Width;
378fMetaFileCanvas := TMetaFileCanvas.Create(fMetaFile, 0);
379with fBitmap.Canvas do
380begin
381Font.OnChange := fFontChanged;
382Brush.OnChange := fBrushChanged;
383Pen.OnChange := fPenChanged;
384end;
385fFontChanged(nil); fPenChanged(nil); fBrushChanged(nil);
386end;
387SelectClipRgn(fMetaFileCanvas.Handle, fClipRgn);
388Result := fMetaFileCanvas;
389end;
390
391procedure TOverlayImage.SaveMetafile(const filename: string);
392begin
393if fMetaFileCanvas <> nil then
394begin
395fMetaFileCanvas.Free;
396fMetaFile.SaveToFile(filename);
397fMetaFileCanvas := TMetaFileCanvas.Create(fMetaFile, 0);
398fMetaFileCanvas.draw(0, 0, Metafile);
399end;
400end;
401
402function TOverlayImage.GetFont: TFont;
403begin
404Result := fBitmap.Canvas.Font;
405end;
406
407function TOverlayImage.GetPen: TPen;
408begin
409Result := fBitmap.Canvas.Pen;
410end;
411
412function TOverlayImage.GetBrush: TBrush;
413begin
414Result := fBitmap.Canvas.Brush;
415end;
416
417procedure TOverlayImage.SetFont(Value: TFont);
418begin
419fBitmap.Canvas.Font.assign(Value);
420end;
421
422procedure TOverlayImage.SetPen(Value: TPen);
423begin
424fBitmap.Canvas.Pen.assign(Value);
425end;
426
427procedure TOverlayImage.SetBrush(Value: TBrush);
428begin
429fBitmap.Canvas.Brush.assign(Value);
430end;
431
432procedure TOverlayImage.NewClipRegion(Value: TRect);
433begin
434if fClipRgn <> 0 then DeleteObject(fClipRgn);
435fClipRgn := 0;
436fClipRgn := CreateRectRgnIndirect(Value);
437end;
438
439procedure TOverlayImage.AddClipRegion(Value: TRect);
440var
441rgn: HRgn;
442begin
443rgn := CreateRectRgnIndirect(Value);
444CombineRgn(fClipRgn, fClipRgn, rgn, RGN_OR);
445DeleteObject(rgn);
446end;
447
448procedure TOverlayImage.SubtractClipRegion(Value: TRect);
449var
450rgn: HRgn;
451begin
452rgn := CreateRectRgnIndirect(Value);
453CombineRgn(fClipRgn, fClipRgn, rgn, RGN_DIFF);
454DeleteObject(rgn);
455end;
456
457procedure TOverlayImage.IntersectClipRegion(Value: TRect);
458var
459rgn: HRgn;
460begin
461rgn := CreateRectRgnIndirect(Value);
462CombineRgn(fClipRgn, fClipRgn, rgn, RGN_And);
463DeleteObject(rgn);
464end;
465
466//------------------------------------------------------------------------
467
468procedure TOverlayImage.WMWindowPosChanged;
469begin
470inherited;
471if not (csDesigning in ComponentState) then if assigned(Parent) then
472begin
473if (Width <> fDrawWidth) or (Height <> fDrawHeight) then
474begin
475fDrawWidth := Width;
476fDrawHeight := Height;
477SizeChanged;
478if fOldRgn <> 0 then
479DeleteObject(fOldRgn);
480fOldRgn := 0;
481fTempDrawing := False;
482fOverlayed := False;
483end;
484GetOffSet; //// ????
485end;
486end;
487
488procedure TOverlayImage.SizeChanged;
489begin
490fScreenBitmap.Width := 0;
491fScreenBitmap.Width := fDrawWidth;
492fScreenBitmap.Height := fDrawHeight;
493// fBitmap.Width:=0;
494fBitmap.Width := fDrawWidth;
495fBitmap.Height := fDrawHeight;
496if fMetaFile <> nil then
497begin
498fMetaFileCanvas.Free;
499fMetaFile.Width := Width;
500fMetaFile.Height := Height;
501fMetaFileCanvas := TMetaFileCanvas.Create(fMetaFile, 0);
502fMetaFileCanvas.draw(0, 0, fMetaFile);
503end;
504end;
505
506procedure TOverlayImage.Loaded;
507begin
508inherited;
509fDrawWidth := Width;
510fDrawHeight := Height;
511Clear(Canvas, Brush.Color);
512end;
513
514procedure TOverlayImage.GetOffSet;
515var
516p, q: TPoint;
517begin
518if assigned(Parent) then
519begin
520with Parent do
521p := ClienttoScreen(Point(0, 0));
522q := ClienttoScreen(Point(0, 0));
523fxoff := q.x - p.x;
524fyoff := q.y - p.y;
525end;
526end;
527
528
529
530procedure TOverlayImage.CMMouseLeave;
531begin
532inherited;
533if assigned(fOnMouseLeave) then
534fOnMouseLeave(self);
535{use to get rid of stray drawing on the TempCanvas}
536end;
537
538procedure TOverlayImage.CMMouseEnter;
539begin
540inherited;
541if assigned(fOnMouseEnter) then
542fOnMouseEnter(self);
543end;
544
545
546procedure TOverlayImage.ShowOverlay;
547var
548DC: HDC;
549begin
550fTempDrawing := True;
551DC := inherited Canvas.Handle;
552if assigned(fOnTempPaint) then fOnTempPaint(self);
553if fOldRgn <> 0 then
554begin
555if fNewRgn <> 0 then
556begin
557CombineRgn(fOldRgn, fOldRgn, fNewRgn, RGN_OR);
558OffsetRgn(fOldRgn, fxoff, fyoff);
559SelectClipRgn(DC, fOldRgn);
560end
561else
562SelectClipRgn(DC, 0);
563DeleteObject(fOldRgn);
564end
565else
566SelectClipRgn(DC, 0);
567BitBlt(DC, 0, 0, fDrawWidth, fDrawHeight,
568fScreenBitmap.Canvas.Handle,
5690, 0, SRCCopy);
570fOldRgn := fNewRgn;
571fNewRgn := 0;
572fTempDrawing := False;
573fOverlayed := True;
574end;
575
576procedure TOverlayImage.LockUpdate;
577begin
578fBitmap.OnChange := nil;
579{Don't update bitmap to screen}
580inc(fLockCount);
581end;
582
583procedure TOverlayImage.UnlockUpdate;
584begin
585dec(fLockCount);
586if fLockCount <= 0 then
587begin
588fLockCount := 0;
589{safety}
590fBitmap.OnChange := fBitmapChanged;
591fBitmapChanged(nil);
592end;
593end;
594
595
596
597procedure TOverlayImage.Clear(Acanvas: TCanvas; AColor: TColor);
598begin
599Acanvas.Brush.Color := AColor;
600Acanvas.FillRect(Rect(0, 0, Width, Height));
601end;
602
603procedure TOverlayImage.EraseMetafile;
604begin
605if fMetaFileCanvas <> nil then
606fMetaFileCanvas.Free;
607if fMetaFile <> nil then
608fMetaFile.Free;
609fMetaFileCanvas := nil;
610fMetaFile := nil;
611with fBitmap.Canvas do
612begin
613Font.OnChange := fOrgFontChanged;
614Brush.OnChange := fOrgBrushChanged;
615Pen.OnChange := fOrgPenChanged;
616end;
617end;
618
619procedure TScrollEventBox.WMHScroll(var Message: TWMHScroll);
620begin
621inherited;
622if assigned(fOnScroll) then fOnScroll(self);
623end;
624
625procedure TScrollEventBox.WMVScroll(var Message: TWMVScroll);
626begin
627inherited;
628if assigned(fOnScroll) then fOnScroll(self);
629end;
630
631
632
633
634procedure TOverlayImage.AdjustToScroll;
635begin
636GetOffSet;
637end;
638
639
640procedure TOverlayImage.OverlayCopyRect(dest: TRect; Canvas: TCanvas;
641Source: TRect);
642var
643rgn: HRgn;
644begin
645rgn := CreateRectRgnIndirect(dest);
646if fNewRgn <> 0 then
647begin
648CombineRgn(fNewRgn, fNewRgn, rgn, RGN_OR);
649DeleteObject(rgn);
650end
651else
652if not fTempDrawing then
653fNewRgn := rgn;
654fTempCanvasChanging;
655OverlayCanvas.CopyRect(dest, Canvas, Source);
656end;
657
658procedure TOverlayImage.OverlayDraw(dest: TRect; Graphic: TGraphic);
659var
660rgn: HRgn;
661begin
662rgn := CreateRectRgnIndirect(dest);
663if fNewRgn <> 0 then
664begin
665CombineRgn(fNewRgn, fNewRgn, rgn, RGN_OR);
666DeleteObject(rgn);
667end
668else
669if not fTempDrawing then
670fNewRgn := rgn
671else
672DeleteObject(rgn);
673fTempCanvasChanging;
674OverlayCanvas.draw(dest.Left, dest.Top, Graphic);
675end;
676
677procedure TOverlayImage.OverlayEllipse(x1, y1, x2, y2: Integer);
678var
679rgn: HRgn;
680begin
681rgn := CreateEllipticRgnIndirect(Rect(x1 - 1, y1 - 1, x2 + 2, y2 + 2));
682if fNewRgn <> 0 then
683begin
684CombineRgn(fNewRgn, fNewRgn, rgn, RGN_OR);
685DeleteObject(rgn);
686end
687else
688if not fTempDrawing then
689fNewRgn := rgn
690else
691DeleteObject(rgn);
692fTempCanvasChanging;
693OverlayCanvas.Ellipse(x1, y1, x2, y2);
694end;
695
696procedure TOverlayImage.OverlayFillRect(const Rect: TRect);
697var
698rgn: HRgn;
699begin
700rgn := CreateRectRgnIndirect(Rect);
701if fNewRgn <> 0 then
702begin
703CombineRgn(fNewRgn, fNewRgn, rgn, RGN_OR);
704DeleteObject(rgn);
705end
706else
707if not fTempDrawing then
708fNewRgn := rgn
709else
710DeleteObject(rgn);
711fTempCanvasChanging;
712OverlayCanvas.FillRect(Rect);
713end;
714
715procedure TOverlayImage.OverlayFrameRect(const Rect: TRect);
716var
717rgn: HRgn;
718begin
719rgn := CreateRectRgnIndirect(Rect);
720if fNewRgn <> 0 then
721begin
722CombineRgn(fNewRgn, fNewRgn, rgn, RGN_OR);
723DeleteObject(rgn);
724end
725else
726if not fTempDrawing then
727fNewRgn := rgn
728else
729DeleteObject(rgn);
730fTempCanvasChanging;
731OverlayCanvas.FrameRect(Rect);
732end;
733
734procedure TOverlayImage.OverlayLine(x1, y1, x2, y2: Integer);
735var
736rgn: HRgn;
737xmin, ymin, xmax, ymax: Integer;
738points: array[0..2] of TPoint;
739begin
740if x1 < x2 then
741begin
742xmin := x1;
743xmax := x2;
744end
745else
746begin
747xmin := x2;
748xmax := x1;
749end;
750if y1 < y2 then
751begin
752ymin := y1;
753ymax := y2;
754end
755else
756begin
757ymin := y2;
758ymax := y1;
759end;
760rgn := CreateRectRgnIndirect(Rect(xmin - 1, ymin - 1, xmax + 1, ymax + 1));
761if fNewRgn <> 0 then
762begin
763CombineRgn(fNewRgn, fNewRgn, rgn, RGN_OR);
764DeleteObject(rgn);
765end
766else
767if not fTempDrawing then
768fNewRgn := rgn
769else
770DeleteObject(rgn);
771fTempCanvasChanging;
772Points[0]:=Point(x1,y1);
773Points[1]:=Point(x2,y2);
774Points[2]:=Points[0];
775OverlayCanvas.Polyline(Points);
776end;
777
778procedure TOverlayImage.OverlayPolygon(Points: array of TPoint);
779var
780rgn: HRgn;
781begin
782rgn := CreatePolygonRgn(Points, High(Points) + 1, WINDING);
783if fNewRgn <> 0 then
784begin
785CombineRgn(fNewRgn, fNewRgn, rgn, RGN_OR);
786DeleteObject(rgn);
787end
788else
789if not fTempDrawing then
790fNewRgn := rgn
791else
792DeleteObject(rgn);
793fTempCanvasChanging;
794OverlayCanvas.Polygon(Points);
795end;
796
797procedure TOverlayImage.OverlayPolyline(Points: array of TPoint);
798var
799rgn: HRgn;
800begin
801rgn := CreatePolygonRgn(Points, High(Points) + 1, WINDING);
802if fNewRgn <> 0 then
803begin
804CombineRgn(fNewRgn, fNewRgn, rgn, RGN_OR);
805DeleteObject(rgn);
806end
807else
808if not fTempDrawing then
809fNewRgn := rgn
810else
811DeleteObject(rgn);
812fTempCanvasChanging;
813OverlayCanvas.Polyline(Points);
814end;
815
816procedure TOverlayImage.OverlayRectangle(x1, y1, x2, y2: Integer);
817var
818rgn: HRgn;
819begin
820rgn := CreateRectRgn(x1, y1, x2, y2);
821if fNewRgn <> 0 then
822begin
823CombineRgn(fNewRgn, fNewRgn, rgn, RGN_OR);
824DeleteObject(rgn);
825end
826else
827if not fTempDrawing then
828fNewRgn := rgn
829else
830DeleteObject(rgn);
831fTempCanvasChanging;
832OverlayCanvas.Rectangle(x1, y1, x2, y2);
833end;
834
835procedure TOverlayImage.OverlayRoundRect(x1, y1, x2, y2, X3, Y3: Integer);
836var
837rgn: HRgn;
838begin
839rgn := CreateRoundRectRgn(x1, y1, x2 + 3, y2 + 3, X3, Y3);
840if fNewRgn <> 0 then
841begin
842CombineRgn(fNewRgn, fNewRgn, rgn, RGN_OR);
843DeleteObject(rgn);
844end
845else
846if not fTempDrawing then
847fNewRgn := rgn
848else
849DeleteObject(rgn);
850fTempCanvasChanging;
851OverlayCanvas.RoundRect(x1, y1, x2, y2, X3, Y3);
852end;
853
854procedure TOverlayImage.Notification;
855begin
856//doesn't do any good tho
857inherited;
858if csDesigning in ComponentState then
859repaint;
860end;
861
862procedure TOverlayImage.HideOverlay;
863begin
864fOverlayed := False;
865invalidate;
866end;
867
868procedure TOverlayImage.OverlayTextOut(x, y: Integer; const s: string);
869var
870rgn: HRgn;
871w, h: Integer;
872begin
873with OverlayCanvas do
874begin
875w := TextWIdth(s);
876h := TextHeight(s);
877end;
878rgn := CreateRectRgn(x, y, x + w, y + h);
879if fNewRgn <> 0 then
880begin
881CombineRgn(fNewRgn, fNewRgn, rgn, RGN_OR);
882DeleteObject(rgn);
883end
884else
885if not fTempDrawing then
886fNewRgn := rgn
887else
888DeleteObject(rgn);
889OverlayCanvas.TextOut(x, y, s);
890end;
891
892function TOverlayImage.GetTempBrush: TBrush;
893begin
894Result := fScreenBitmap.Canvas.Brush;
895end;
896
897function TOverlayImage.GetTempFont: TFont;
898begin
899Result := fScreenBitmap.Canvas.Font;
900end;
901
902function TOverlayImage.GetTempPen: TPen;
903begin
904Result := fScreenBitmap.Canvas.Pen;
905end;
906
907procedure TOverlayImage.SetTempBrush(Value: TBrush);
908begin
909fScreenBitmap.Canvas.Brush.assign(Value);
910end;
911
912procedure TOverlayImage.SetTempFont(Value: TFont);
913begin
914fScreenBitmap.Canvas.Font.assign(Value);
915end;
916
917procedure TOverlayImage.SetTempPen(Value: TPen);
918begin
919fScreenBitmap.Canvas.Pen.assign(Value);
920end;
921
922procedure Register;
923begin
924RegisterComponents('MathStuff', [TOverlayImage, TScrollEventBox]);
925end;
926
927
928end.
929
930