{----------------------------------------------------------------------------- The contents of this file are subject to the Mozilla Public License Version 1.1 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.mozilla.org/MPL/MPL-1.1.html Software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either expressed or implied. See the License for the specific language governing rights and limitations under the License. The Original Code is: JvZoom.PAS, released on 2001-02-28. 2002-12-08 : added crosshair options and OnContentsChanged event (Antoine Potten) The Initial Developer of the Original Code is Sébastien Buysse [sbuysse att buypin dott com] Portions created by Sébastien Buysse are Copyright (C) 2001 Sébastien Buysse. All Rights Reserved. Contributor(s): Michael Beck [mbeck att bigfoot dott com], Antoine Potten [jvcl att antp dott be] You may retrieve the latest version of this file at the Project JEDI's JVCL home page, located at http://jvcl.sourceforge.net Known Issues: -----------------------------------------------------------------------------} // $Id: JvZoom.pas 10613 2006-05-19 19:21:43Z jfudickar $ unit JvZoom; {$I jvcl.inc} interface uses {$IFDEF UNITVERSIONING} JclUnitVersioning, {$ENDIF UNITVERSIONING} SysUtils, Classes, Windows, Messages, Graphics, Controls, Forms, ExtCtrls, JvComponent; type TJvZoom = class(TJvCustomControl) private FTimer: TTimer; FActive: Boolean; FZoomLevel: Integer; FDelay: Cardinal; FLastPoint: TPoint; FCrossHair: Boolean; FCrosshairColor: TColor; FCrosshairSize: Integer; FOnContentsChanged: TNotifyEvent; FCacheOnDeactivate: Boolean; FCacheBitmap: TBitmap; FCrossHairPicture: TPicture; procedure SetActive(const Value: Boolean); procedure SetDelay(const Value: Cardinal); procedure SetZoomLevel(const Value: Integer); procedure SetCacheOnDeactivate(const Value: Boolean); procedure SetCrossHairPicture(const Value: TPicture); function GetZoomPercentage: Integer; procedure SetZoomPercentage(const Value: Integer); procedure PaintMe(Sender: TObject); procedure SetCrossHair(const Value: Boolean); protected procedure Resize; override; procedure Paint; override; procedure PaintZoom; procedure Loaded; override; procedure Cache; procedure FlushCache; procedure DoContentsChanged; public constructor Create(AOwner: TComponent); override; destructor Destroy; override; procedure ForceUpdate; procedure ZoomInAt(X, Y: Integer); published property Anchors; property Align; property Constraints; property Color; property Enabled; property Visible; property Active: Boolean read FActive write SetActive default True; property ZoomLevel: Integer read FZoomLevel write SetZoomLevel default 100; property ZoomPercentage: Integer read GetZoomPercentage write SetZoomPercentage stored False; property Delay: Cardinal read FDelay write SetDelay default 100; property Crosshair: Boolean read FCrossHair write SetCrossHair default False; property CrossHairPicture: TPicture read FCrossHairPicture write SetCrossHairPicture; property CrosshairColor: TColor read FCrosshairColor write FCrosshairColor default clBlack; property CrosshairSize: Integer read FCrosshairSize write FCrosshairSize default 20; property CacheOnDeactivate: Boolean read FCacheOnDeactivate write SetCacheOnDeactivate default True; property OnContentsChanged: TNotifyEvent read FOnContentsChanged write FOnContentsChanged; property OnMouseDown; property OnClick; property OnDblClick; property OnMouseUp; property OnResize; property OnKeyPress; property OnKeyDown; property OnKeyUp; property OnMouseWheel; property OnMouseWheelUp; property OnMouseWheelDown; end; {$IFDEF UNITVERSIONING} const UnitVersioning: TUnitVersionInfo = ( RCSfile: '$URL: https://jvcl.svn.sourceforge.net/svnroot/jvcl/tags/JVCL3_32/run/JvZoom.pas $'; Revision: '$Revision: 10613 $'; Date: '$Date: 2006-05-19 21:21:43 +0200 (ven., 19 mai 2006) $'; LogPath: 'JVCL\run' ); {$ENDIF UNITVERSIONING} implementation uses {$IFDEF VisualCLX} Qt, {$ENDIF VisualCLX} JvJVCLUtils; constructor TJvZoom.Create(AOwner: TComponent); begin inherited Create(AOwner); FCrossHairPicture := TPicture.Create; FCrossHairPicture.OnChange := PaintMe; Height := 100; Width := 100; FDelay := 100; FZoomLevel := 100; FCrosshairSize := 20; FCrosshairColor := clBlack; FCacheOnDeactivate := True; FActive := True; FTimer := TTimer.Create(Self); FTimer.OnTimer := PaintMe; FTimer.Interval := 100; end; destructor TJvZoom.Destroy; begin FCacheBitmap.Free; FCacheBitmap := nil; FCrossHairPicture.OnChange := nil; FCrossHairPicture.Free; { Timer is automatically freed } inherited Destroy; end; procedure TJvZoom.Cache; begin if not Assigned(FCacheBitmap) then FCacheBitmap := TBitmap.Create; FCacheBitmap.Width := Width; FCacheBitmap.Height := Height; FCacheBitmap.Canvas.CopyRect(ClientRect, Canvas, ClientRect); end; procedure TJvZoom.FlushCache; begin FreeAndNil(FCacheBitmap); end; procedure TJvZoom.Loaded; begin inherited Loaded; FTimer.Enabled := FActive; end; procedure TJvZoom.Paint; begin if Active then PaintZoom else begin if Assigned(FCacheBitmap) then Canvas.Draw(0, 0, FCacheBitmap) else begin Canvas.Brush.Color := Color; Canvas.FillRect(Rect(0, 0, Width, Height)); end; end; if csDesigning in ComponentState then with Canvas do begin Pen.Style := psDash; Pen.Color := clBlack; Brush.Style := bsClear; Rectangle(0, 0, Width, Height); end; end; procedure TJvZoom.PaintMe(Sender: TObject); {$IFDEF VisualCLX} var P: TPoint; {$ENDIF VisualCLX} begin {$IFDEF VCL} { Reading Canvas.Handle will implicitly set the canvas handle to the control's device context Calling PaintWindow will lock the canvas and call Paint } PaintWindow(Canvas.Handle); {$ENDIF VCL} {$IFDEF VisualCLX} if Enabled then GetCursorPos(P); //Only draw if on a different position if (P.X <> FLastPoint.X) or (P.Y <> FLastPoint.Y) then Invalidate; end; {$ENDIF VisualCLX} end; procedure TJvZoom.PaintZoom; var P: TPoint; X, Y, Dx, Dy: Integer; SourceRect: TRect; {$IFDEF VCL} DesktopCanvas: TJvDesktopCanvas; {$ENDIF VCL} {$IFDEF VisualCLX} Bmp: TBitmap; {$ENDIF VisualCLX} begin if Enabled then begin GetCursorPos(P); //Only draw if on a different position if (P.X = FLastPoint.X) and (P.Y = FLastPoint.Y) then Exit; end else P := FLastPoint; //Analyse the point FLastPoint := P; //Create the area to Copy X := (Width div 2) * FZoomLevel div 100; Y := (Height div 2) * FZoomLevel div 100; Dx := 0; Dy := 0; if P.X < X then begin Dx := (P.X - X - 1) * 100 div FZoomLevel; P.X := X; end else if P.X + X > Screen.Width then begin Dx := (X - (Screen.Width - P.X) + 1) * 100 div FZoomLevel; P.X := Screen.Width - X; end; if P.Y < Y then begin Dy := (P.Y - Y - 1) * 100 div FZoomLevel; P.Y := Y; end else if P.Y + Y > Screen.Height then begin Dy := (Y - (Screen.Height - P.Y) + 1) * 100 div FZoomLevel; P.Y := Screen.Height - Y; end; SourceRect.Left := P.X - X; SourceRect.Top := P.Y - Y; SourceRect.Right := P.X + X; SourceRect.Bottom := P.Y + Y; {$IFDEF VCL} //Draw the area around the mouse DesktopCanvas := TJvDesktopCanvas.Create; Canvas.CopyRect(Rect(0, 0, Width, Height), DesktopCanvas, SourceRect); DesktopCanvas.Free; {$ENDIF VCL} {$IFDEF VisualCLX} Bmp := TBitmap.Create; Bmp.Handle := QPixmap_create; try with SourceRect do QPixmap_grabWindow(Bmp.Handle, QWidget_winID(GetDesktopWindow), Left, Top, 2 * X, 2 * Y); CopyRect(Canvas, Rect(0, 0, Width, Height), Bmp.Canvas, Rect(0,0, Bmp.Width, Bmp.Height)); finally Bmp.Free; end; {$ENDIF VisualCLX} if FCrossHair then begin if (FCrossHairPicture.Graphic <> nil) and not FCrossHairPicture.Graphic.Empty then begin FCrossHairPicture.Graphic.Transparent := True; Canvas.Draw((Width - FCrossHairPicture.Graphic.Width) div 2 + Dx, (Height - FCrossHairPicture.Graphic.Height) div 2 + Dy,FCrossHairPicture.Graphic); end else with Canvas do begin Pen.Color := FCrosshairColor; Pen.Style := psSolid; MoveTo(Width div 2 + Dx, Height div 2 - FCrosshairSize div 2 + Dy); LineTo(Width div 2 + Dx, Height div 2 + FCrosshairSize div 2 + Dy); MoveTo(Width div 2 - FCrosshairSize div 2 + Dx, Height div 2 + Dy); LineTo(Width div 2 + FCrosshairSize div 2 + Dx, Height div 2 + Dy); end; end; if Enabled then DoContentsChanged; end; procedure TJvZoom.SetActive(const Value: Boolean); begin if FActive = Value then Exit; FActive := Value; if not (csReading in ComponentState) then FTimer.Enabled := FActive; if not FActive then begin if FCacheOnDeactivate then Cache else Invalidate; end else if not Enabled then FLastPoint := Point(MaxLongint, MaxLongint); Invalidate; end; procedure TJvZoom.SetCacheOnDeactivate(const Value: Boolean); begin if Value <> FCacheOnDeactivate then begin FCacheOnDeactivate := Value; if not Value then begin FlushCache; if not Active then Invalidate; end; end; end; procedure TJvZoom.SetDelay(const Value: Cardinal); begin FDelay := Value; FTimer.Interval := Value; end; procedure TJvZoom.SetZoomLevel(const Value: Integer); begin if (FZoomLevel <> Value) and (Value > 0) then begin FZoomLevel := Value; { Forget the old point; thus force repaint } if Enabled then FLastPoint := Point(MaxLongint, MaxLongint); Invalidate; end; end; procedure TJvZoom.SetCrossHair(const Value: Boolean); begin if FCrossHair <> Value then begin FCrossHair := Value; { Forget the old point; thus force repaint } ForceUpdate; end; end; procedure TJvZoom.Resize; begin //On resize, refresh it inherited Resize; { Forget the old point; thus force repaint } if Enabled then FLastPoint := Point(MaxLongint, MaxLongint); PaintMe(Self); end; function TJvZoom.GetZoomPercentage: Integer; begin if ZoomLevel <> 0 then Result := Trunc((100.0 / ZoomLevel) * 100.0) else Result := 0; end; procedure TJvZoom.SetZoomPercentage(const Value: Integer); begin if Value <> 0 then ZoomLevel := Trunc((100.0 / Value) * 100.0); end; procedure TJvZoom.SetCrossHairPicture(const Value: TPicture); begin FCrossHairPicture.Assign(Value); end; procedure TJvZoom.ZoomInAt(X, Y: Integer); begin if Enabled then SetCursorPos(X,Y) else begin if (FLastPoint.X <> X) or (FLastPoint.Y <> Y) then begin FLastPoint.X := X; FLastPoint.Y := Y; DoContentsChanged; end; end; Invalidate; end; procedure TJvZoom.ForceUpdate; begin if Enabled then FLastPoint := Point(MaxLongint, MaxLongint); Invalidate; end; procedure TJvZoom.DoContentsChanged; begin if Assigned(FOnContentsChanged) then FOnContentsChanged(Self); end; {$IFDEF UNITVERSIONING} initialization RegisterUnitVersion(HInstance, UnitVersioning); finalization UnregisterUnitVersion(HInstance); {$ENDIF UNITVERSIONING} end.