lazarus/components/cairocanvas/cairographics.pas
2013-10-09 17:53:02 +00:00

266 lines
6.1 KiB
ObjectPascal

unit CairoGraphics;
{$mode objfpc}{$H+}
interface
uses
Types, CairoCanvas, Cairo, LCLType, LCLIntf, LMessages,
Classes, Controls, ExtCtrls, Graphics;
type
{ TCairoGraphicControl }
TCairoGraphicControl = class(TControl)
private
FCanvas: TCanvas;
FOnPaint: TNotifyEvent;
procedure WMPaint(var Message: TLMPaint); message LM_PAINT;
protected
//class procedure WSRegisterClass; override;
procedure FontChanged(Sender: TObject); override;
procedure Paint; virtual;
procedure DoOnChangeBounds; override;
procedure DoOnParentHandleDestruction; override;
property OnPaint: TNotifyEvent read FOnPaint write FOnPaint;
function GetDCHandle: HDC;
procedure ReleaseDCHandle(DC: HDC);
public
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
property Canvas: TCanvas read FCanvas;
end;
{ TCairoPaintBox }
TCairoPaintBox = class(TCairoGraphicControl)
protected
//class procedure WSRegisterClass; override;
procedure Paint; override;
class function GetControlClassDefaultSize: TSize; override;
public
constructor Create(AOwner: TComponent); override;
property Canvas;
published
property Align;
property Anchors;
property BorderSpacing;
property Color;
property Constraints;
property DragCursor;
property DragMode;
property Enabled;
property Font;
property Hint;
property ParentColor;
property ParentFont;
property ParentShowHint;
property PopupMenu;
property ShowHint;
property Visible;
property OnChangeBounds;
property OnClick;
property OnDblClick;
property OnDragDrop;
property OnDragOver;
property OnEndDrag;
property OnMouseDown;
property OnMouseMove;
property OnMouseUp;
property OnMouseEnter;
property OnMouseLeave;
property OnMouseWheel;
property OnMouseWheelDown;
property OnMouseWheelUp;
property OnPaint;
property OnResize;
property OnStartDrag;
end;
{ TCairoControlCanvas }
TCairoControlCanvas = class(TCairoPrinterCanvas)
private
procedure SetControl(const AValue: TCairoGraphicControl);
protected
sf: Pcairo_surface_t;
FControl: TCairoGraphicControl;
FDeviceContext: HDC;
procedure DestroyCairoHandle; override;
public
procedure CreateHandle; override;
procedure FreeHandle; override;
property Control: TCairoGraphicControl read FControl write SetControl;
destructor Destroy; override;
end;
TCairoControlCanvasClass = class of TCairoControlCanvas;
var
CairoGraphicControlCanvasClass: TCairoControlCanvasClass = nil;
implementation
uses
SysUtils;
{ TCairoGraphicControl }
procedure TCairoGraphicControl.WMPaint(var Message: TLMPaint);
begin
if Message.DC <> 0 then
begin
Canvas.Lock;
try
Canvas.Handle := Message.DC;
try
Paint;
finally
Canvas.Handle := 0;
end;
finally
Canvas.Unlock;
end;
end;
end;
{class procedure TCairoGraphicControl.WSRegisterClass;
begin
inherited WSRegisterClass;
end;}
procedure TCairoGraphicControl.FontChanged(Sender: TObject);
begin
Canvas.Font:=Font;
inherited FontChanged(Sender);
end;
procedure TCairoGraphicControl.Paint;
begin
if Assigned(FOnPaint) then FOnPaint(Self);
end;
procedure TCairoGraphicControl.DoOnChangeBounds;
begin
inherited DoOnChangeBounds;
// reset canvas handle in next access
if Canvas.HandleAllocated then
TCairoControlCanvas(Canvas).FreeHandle;
end;
procedure TCairoGraphicControl.DoOnParentHandleDestruction;
begin
inherited DoOnParentHandleDestruction;
if Canvas.HandleAllocated then
TCairoControlCanvas(Canvas).FreeHandle;
end;
function TCairoGraphicControl.GetDCHandle: HDC;
begin
Result := GetDC(Parent.Handle);
MoveWindowOrgEx(Result, Left, Top);
IntersectClipRect(Result, 0, 0, Width, Height);
end;
procedure TCairoGraphicControl.ReleaseDCHandle(DC: HDC);
begin
ReleaseDC(Parent.Handle, DC);
end;
constructor TCairoGraphicControl.Create(AOwner: TComponent);
begin
FCanvas := CairoGraphicControlCanvasClass.Create;
TCairoControlCanvas(FCanvas).FControl := Self;
inherited Create(AOwner);
end;
destructor TCairoGraphicControl.Destroy;
begin
FreeAndNil(FCanvas);
inherited Destroy;
end;
{ TCairoControlCanvas }
procedure TCairoControlCanvas.SetControl(const AValue: TCairoGraphicControl);
begin
if FControl <> AValue then begin
FreeHandle;
FControl := AValue;
end;
end;
procedure TCairoControlCanvas.DestroyCairoHandle;
begin
cairo_surface_destroy(sf);
sf := nil;
inherited DestroyCairoHandle;
end;
procedure TCairoControlCanvas.CreateHandle;
begin
inherited CreateHandle;
if FDeviceContext = 0 then //Store it locally, what was Geted must be Released
FDeviceContext := FControl.GetDCHandle;
SetHandle(FDeviceContext);
SurfaceXDPI := GetDeviceCaps(FDeviceContext, LOGPIXELSX);
SurfaceYDPI := GetDeviceCaps(FDeviceContext, LOGPIXELSY);
XDPI := SurfaceXDPI;
YDPI := SurfaceXDPI;
end;
procedure TCairoControlCanvas.FreeHandle;
begin
if FDeviceContext <> 0 then begin
FControl.ReleaseDCHandle(FDeviceContext);
FDeviceContext := 0;
end;
inherited FreeHandle;
end;
destructor TCairoControlCanvas.Destroy;
begin
FreeHandle;
inherited Destroy;
end;
{ TCairoPaintBox }
procedure TCairoPaintBox.Paint;
begin
if csDesigning in ComponentState then begin
Canvas.Brush.Color := Color;
with Canvas do
begin
Pen.Style := psDash;
Pen.Color:=clBlack;
Brush.Style := bsClear;
Rectangle(0, 0, Self.Width - 1, Self.Height - 1);
Line(0,0,Self.Width-1,Self.Height-1);
Line(Self.Width-1,0,0,Self.Height-1);
end;
exit;
end;
if Assigned(OnPaint) then begin
Canvas.Font := Font;
Canvas.Brush.Color := Color;
inherited Paint;
end;
end;
class function TCairoPaintBox.GetControlClassDefaultSize: TSize;
begin
Result.Cx:=105;
Result.Cy:=105;
end;
constructor TCairoPaintBox.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
ControlStyle := ControlStyle + [csReplicatable];
SetInitialBounds(0,0,GetControlClassDefaultSize.Cx,GetControlClassDefaultSize.Cx);
end;
end.