Hi .I have the follow class:
TElectricBlock = class(TCustomDiagramBlock)
private
FTextAlign: TBlockTextAlign;
{$IFDEF GDIPLUS}
FPath: TGPGraphicsPath;
{$ENDIF}
procedure SetTextAlign(const Value: TBlockTextAlign);
procedure CreateLinkPoints;
protected
{$IFDEF GDIPLUS}
property DrawPath: TGPGraphicsPath read FPath;
{$ENDIF}
public
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
{$IFDEF GDIPLUS}
procedure GetBlockPath(APath: TGPGraphicsPath); override;
{$ENDIF}
published
property TextAlign: TBlockTextAlign read FTextAlign write SetTextAlign;
property Angle;
property Brush;
property SelBrush;
property Color;
property SelColor;
property Pen;
property Strings;
property Alignment;
property VertAlign;
property ClipText;
property WordWrap;
property TextCells;
property Restrictions;
property Font;
property DiagramFont;
property MinWidth;
property MinHeight;
property Shadow;
property ShowHint;
property Hint;
property ParentShowHint;
property Gradient;
property Bitmap;
property BitmapMode;
property BitmapTransparent;
property MetaFile;
property Picture;
property PictureMode;
property Transparent;
property Cursor;
property StringData;
property Visible;
property Layer;
property Transparency;
end;
constructor TElectricBlock.Create(AOwn
er: TComponent);
begin
inherited;
{$IFDEF GDIPLUS}
FPath := TGPGraphicsPath.Create;
{$ENDIF}
Shape := bsNoShape;
{OriginalRect has the easiest rect to draw, but width and height have
the best default size of the block}
Drawer.OriginalRect := Rect(0, 0, 80, 40);
{$IFDEF GDIPLUS}
GPDrawer.SourceRect := RectX(0, 0, 80, 40);
{$ENDIF}
{Call TextAlign (not FTextAlign) to update textcell. Call after changing OriginalRect}
TextAlign := taRightBottom;
UpdateBlockHandles; {Call UpdateBlockHandles after changing OriginalRect}
CreateLinkPoints;
MinWidth := 20;
MinHeight := 20;
Width := 60;
Height := 20;
RotateFont := False;
ClipText := False;
end;
procedure TElectricBlock.CreateLinkP
oints;
begin
{Create points at left and right of block, vertically centered. Points are
relative to Drawer.OriginalRect
Also defined the orientation of lines linked to the point}
with Drawer.OriginalRect do
begin
LinkPoints.Add(Left, (Bottom - Top) div 2, aoLeft);
LinkPoints.Add(Right, (Bottom - Top) div 2, aoRight)
end;
end;
destructor TElectricBlock.Destroy;
begin
{$IFDEF GDIPLUS}
FPath.Free;
{$ENDIF}
inherited;
end;
{$IFDEF GDIPLUS}
procedure TElectricBlock.GetBlockPat
h(APath: TGPGraphicsPath);
begin
{Set the block path as a rectangle because we need to set that area as
the selectable area. We will paint the control in the DrawBlock method}
APath.AddRectangle(RectGP(
GPDrawer.S
ourceRect)
);
end;
{$ENDIF}
procedure TElectricBlock.SetTextAlig
n(const Value: TBlockTextAlign);
begin
if FTextAlign <> Value then
begin
FTextAlign := Value;
With Drawer.OriginalRect do
Case FTextAlign of
taLeftTop:
DefaultTextCell.SetBounds(
0, -(Bottom - Top), Right - Left, Bottom - Top);
taRightBottom:
DefaultTextCell.SetBounds(
0, Bottom - Top, Right - Left, Bottom - Top);
end;
Redraw;
end;
end;
In another unit i have such code:
type
IMyInterface = Interface(IInterface)
['{11BBD2CA-04BC-45AE-8CA2
-378CCFCB2
21F}']
procedure Dotest;
end;
type
TNPNTransistor = class(TElectricBlock,IMyIn
terface)
protected
procedure DrawBlock(Canvas: TCanvas; ARect: TRect); override;
public
constructor Create(AOwner: TComponent);
procedure Dotest;
end;
constructor TNPNTransistor.Create(AOwn
er: TComponent);
begin
inherited;
Drawer.OriginalRect := Rect(0, 0, 80, 80);
{$IFDEF GDIPLUS}
GPDrawer.SourceRect := RectX(0, 0, 80, 80);
{$ENDIF}
UpdateBlockHandles; {Call UpdateBlockHandles after changing OriginalRect}
Width := 40;
Height := 40;
with Drawer.OriginalRect do
begin
LinkPoints.Clear;
LinkPoints.Add(Right, Bottom , aoNone);
LinkPoints.Add(Left, (Bottom - Top) div 2, aoNone);
LinkPoints.Add(Right, Top , aoNone);
end;
end;
procedure TNPNTransistor.DrawBlock(C
anvas: TCanvas; ARect: TRect);
var w ,h,x : integer;
begin
w := 20;
h := 10;
{$IFDEF GDIPLUS}
With DrawPath do
begin
Reset;
StartFigure;
AddArc(0,0,w,h,45,270);
CloseFigure;
end;
GPDrawer.GPCanvas.Pen.Tran
sparency := Self.Transparency;
GPDrawer.GPCanvas.Pen.Assi
gn(Self.Pe
n);
GPDrawer.TransformPath(Dra
wPath);
GPDrawer.GPCanvas.DrawPath
(DrawPath)
;
{$ENDIF}
end;
procedure TNPNTransistor.Dotest;
begin
with Drawer.OriginalRect do
begin
LinkPoints.Add(Right, Bottom , aoNone);
LinkPoints.Add(Left, (Bottom - Top) div 8, aoNone);
LinkPoints.Add(Right/2, Top , aoNone);
LinkPoints.Add(Right/2, Top/3 , aoNone);
end;
{$IFDEF GDIPLUS}
With Self.DrawPath do
begin
StartFigure;
AddArc(0,0,10,40,45,270);
CloseFigure;
end;
GPDrawer.GPCanvas.Pen.Tran
sparency := Self.Transparency;
GPDrawer.GPCanvas.Pen.Assi
gn(Self.Pe
n);
GPDrawer.TransformPath(Dra
wPath);
GPDrawer.GPCanvas.DrawPath
(DrawPath)
; <--------------(*)
{$ENDIF}
end;
In main form I create an object of TNPNTransistor.
The DrawBlock is called automatically.
Everything works nice and i get my shape painted in
the diagram, a component that holds all the blocks.
procedure TTMSForm1.DrawClick(Sender
: TObject);
var npn: TNPNTransistor;
begin
npn := TNPNTransistor.Create(Owne
r);
npn.Diagram := floor;
end;
A doubleclik on the shape just created should excute the Dotest method:
procedure TTMSForm1.floorDControlDbl
Click(Send
er: TObject; ADControl: TDiagramControl);
Var ImyInterf2 : IMyInterface2 ;
ImyInterf : IMyInterface ;
begin
(ADControl as TNPNTransistor).DoTest;
end;
It works for the first part of the DoTest procedure. I get an Access Violation because
of this line:
GPDrawer.GPCanvas.DrawPath
(DrawPath)
; <--------------(*)
I am not able to find out the reason. Any help?
Thx