Go Premium for a chance to win a PS4. Enter to Win

x
?
Solved

Arrow Tool  for drawing on canvas - more points available

Posted on 2002-03-13
7
Medium Priority
?
267 Views
Last Modified: 2010-04-05
I want to be able to create an arrow tool like the one in MS Word drawing toolbar - that is full head arrow (always filled) with either 1 or 2 heads. Possibility of dotted or dashed  shaft is an optional extra.

It also needs to be able to stretch like a line would on the canvas, determined by where the user places the mouse on the canvas.

any solutions greatly appreciated.

More points available for fullness of answer.


Vanessa

0
Comment
Question by:Vanessa
7 Comments
 
LVL 9

Expert Comment

by:ginsonic
ID: 6863626
listening
0
 
LVL 34

Expert Comment

by:Slick812
ID: 6863633
I can not guess what you want? An Arrow Tool? Here is some code to make an arrow shape on a Canvas.


var
ArPoints: array[0..7] of TPoint;

begin
Canvas.Brush.Color := clRed;
Canvas.Pen.Color := clRed;
{these points draw an Arrow with Polygon( )}
  ArPoints[0].x := 2;
  ArPoints[0].y := 8;
    ArPoints[1].x := 14;
    ArPoints[1].y := 2;
  ArPoints[2].x := 14;
  ArPoints[2].y := 6;
    ArPoints[3].x := 20;
    ArPoints[3].y := 6;
  ArPoints[4].x := 20;
  ArPoints[4].y := 10;
    ArPoints[5].x := 14;
    ArPoints[5].y := 10;
  ArPoints[6].x := 14;
  ArPoints[6].y := 14;
    ArPoints[7].x := 2;
    ArPoints[7].y := 8;
Canvas.Polygon(ArPoints);
end;

I do not understand "It also needs to be able to stretch like a line would on the canvas" Do lines streach? What is your goal? what are you trying to let the user do with your program, draw an arrow, make a line between 2 points that the user clicks?
0
 
LVL 6

Expert Comment

by:zebada
ID: 6863810
Sample "rubberband" arrow drawing program can be downloaded from
http://www.blacky.co.nz/free/arrow.zip
It can easily be modified to do what you want.
If you want me to modify it let me know.

There are other sample programs as well:
http://www.blacky.co.nz/free
Most of these were developed in response to questions asked on EE.

Regards
Paul
0
Concerto Cloud for Software Providers & ISVs

Can Concerto Cloud Services help you focus on evolving your application offerings, while delivering the best cloud experience to your customers? From DevOps to revenue models and customer support, the answer is yes!

Learn how Concerto can help you.

 

Author Comment

by:Vanessa
ID: 6866196
Fuller explanation follows

The user has to click on a button then drag from pointA to pointB and on mouse up an arrow appears.  The head on the arrow is at pointB.  There can be multiple arrows on the canvas at anytime. Ideally they should be able to select whether they want a solid line arrow, a dotted or dashed arrow of varying thicknesses.  

I am using a paintbox for the canvas, which then coverts to a bitmap and the picture is saved in the database.


Your assistence slick182 and zebada have been astounding.  Thanks for the fullness of your explanations.

Vanessa
0
 
LVL 34

Expert Comment

by:Slick812
ID: 6873472
Have you tried to combine the code I listed for
Canvas.Polygon(ArPoints);
and the code in zebada's arrow zip? that should be enough to get you started. Do you have some code you tried for this?
0
 
LVL 34

Expert Comment

by:Slick812
ID: 6878782
Had time this weekend, so I did an arrow draw, I did it with a 7 point array for Polygon, but you could use a 4 point array and just draw a wide line for the arrow tail

private
    { Private declarations }
    DoArrow, ReArrow, Start1: Boolean;
    StartArrow, ALPt: TPoint;
    ArrowPoints: Array[0..7] of TPoint;

procedure TForm1.Button_DrawArrowClick(Sender: TObject);
begin
Start1 := True;
end;


procedure TForm1.PaintBox5MouseDown(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
begin
if Start1 then
  begin
  DoArrow := True;
  Start1 := False;
  PaintBox5.Canvas.Brush.Style := bsClear;
  PaintBox5.Canvas.Pen.Color := clBlack;
  PaintBox5.Canvas.Pen.Style := psSolid;
  PaintBox5.Canvas.Pen.Mode := pmNot;
  PaintBox5.Canvas.Pen.Width := 1;

  StartArrow.x := X;
  StartArrow.y := Y;
  ALPt.x := X;
  ALPt.y := Y;
  end;
end;

procedure TForm1.PaintBox5MouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer);
var
Angle, Rad1: Extended;
HalfHWidth, HalfTWidth, AheadLength: Integer;
begin
if DoArrow then
  begin
  if (abs(StartArrow.x - X) < 14) and
  (abs(StartArrow.y - Y) < 14) and
  not ReArrow then Exit;
  {since this arrow head is 17 pixels long then don't start drawing
  until the cursor moves 14 pixels}
  if ReArrow then
    begin
    {erase the arrow}
    PaintBox5.Canvas.Polygon(ArrowPoints);
    PaintBox5.Canvas.MoveTo(StartArrow.x,StartArrow.y);
    PaintBox5.Canvas.LineTo(ALPt.x, ALPt.y);
    end;
  Angle := 180 * (1 + ArcTan2(Y-StartArrow.y, X-StartArrow.x) / Pi);
  {I use a trig function to get the angle from the rise and run (Y-StartArrow.y, X-StartArrow.x)
  ArcTan2( )  returns a Radian value from the rise (Cos-Y) and run (Sin-X) values
  I convert it to Angle mesurement, because it's easier than radians for me to use}
  PaintBox5.Canvas.MoveTo(StartArrow.x,StartArrow.y);
  AheadLength := 17;
  {set the length of the arrow head here by changing AheadLength}
  Rad1 := DegToRad(Angle+180);
  {reverse the angle and move 17 pixels back toward StartPoint for the length of the arrow head}
  ALPt.x := Round(X-Cos(Rad1)*AheadLength);
  ALPt.y := Round(Y-Sin(Rad1)*AheadLength);
  PaintBox5.Canvas.LineTo(ALPt.x, ALPt.y);
  ArrowPoints[0].x := X;
  ArrowPoints[0].y := Y;
  {build your point array, start with the current cursor Position}
  Rad1 := DegToRad(Angle+90);
  {now rotate your angle 90 degrees}
  HalfHWidth := 7;
  HalfTWidth := 2;
  {set your half Head and Tail Width}
  ArrowPoints[1].x := Round(ALPt.x-(Cos(Rad1)*HalfHWidth));
  {the Cos( ) gives you the X factor to mutiply your X mesurements
   and Sin( ) gives you the Y}
  ArrowPoints[1].y := Round(ALPt.y-(Sin(Rad1)*HalfHWidth));
  {you have rotated the angle 90 so move the point out 7
  pixels from ALPt point for arrow head width}
  ArrowPoints[2].x := Round(ALPt.x-(Cos(Rad1)*HalfTWidth));
  ArrowPoints[2].y := Round(ALPt.y-(Sin(Rad1)*HalfTWidth));
  {move the point out 2 pixels for the arrow tail width}
  ArrowPoints[3].x := Round(StartArrow.x-(Cos(Rad1)*HalfTWidth));
  ArrowPoints[3].y := Round(StartArrow.y-(Sin(Rad1)*HalfTWidth));
  {now do the start point}
  Rad1 := DegToRad(Angle-90);
  {rotate angle 90 other way}
  ArrowPoints[4].x := Round(StartArrow.x-(Cos(Rad1)*HalfTWidth));
  ArrowPoints[4].y := Round(StartArrow.y-(Sin(Rad1)*HalfTWidth));

  ArrowPoints[5].x := Round(ALPt.x-(Cos(Rad1)*HalfTWidth));
  ArrowPoints[5].y := Round(ALPt.y-(Sin(Rad1)*HalfTWidth));

  ArrowPoints[6].x := Round(ALPt.x-(Cos(Rad1)*HalfHWidth));
  ArrowPoints[6].y := Round(ALPt.y-(Sin(Rad1)*HalfHWidth));
  {because all the Radian values are Rounded, small HalfTWidth like
    2 pixels may not be consistant}

  ArrowPoints[7] := ArrowPoints[0];
  {close the polygon}

  PaintBox5.Canvas.Polygon(ArrowPoints);
  ReArrow := True;
  end;
end;

procedure TForm1.PaintBox5MouseUp(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
begin
if DoArrow and ReArrow then
  begin
  PaintBox5.Canvas.Brush.Style := bsSolid;
  PaintBox5.Canvas.Brush.Color := clAqua;
  PaintBox5.Canvas.Pen.Color := clBlue;
  PaintBox5.Canvas.Pen.Style := psSolid;
  PaintBox5.Canvas.Pen.Mode := pmCopy;
  PaintBox5.Canvas.Polygon(ArrowPoints);
  {PB5Bmp.Canvas.Polygon(ArrowPoints);}

  {below are some alternate ways to draw the arrow tail}
  {PaintBox5.Canvas.Pen.Width := 3;
  PaintBox5.Canvas.MoveTo(StartArrow.x,StartArrow.y);
  PaintBox5.Canvas.LineTo(ALPt.x,ALPt.y);
  PaintBox5.Canvas.Pen.Width := 1;
  PaintBox5.Canvas.Pen.Color := clWhite;
  PaintBox5.Canvas.MoveTo(StartArrow.x,StartArrow.y);
  PaintBox5.Canvas.LineTo(ALPt.x,ALPt.y);}
  end;
ReArrow := False;
DoArrow := False;
end;

- - - - - - - - - - - - - - - -
if you're going to do a graphics program, you might practice using the drawng methods available for TCanvas
0
 
LVL 34

Accepted Solution

by:
Slick812 earned 400 total points
ID: 6879070
you might look at this About web site for delphi graphics

http://delphi.about.com/cs/kbgreffect/index.htm
0

Featured Post

Technology Partners: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

The uses clause is one of those things that just tends to grow and grow. Most of the time this is in the main form, as it's from this form that all others are called. If you have a big application (including many forms), the uses clause in the in…
Introduction Raise your hands if you were as upset with FireMonkey as I was when I discovered that there was no TListview.  I use TListView in almost all of my applications I've written, and I was not going to compromise by resorting to TStringGrid…
This video shows how to quickly and easily deploy an email signature for all users in Office 365 and prevent it from being added to replies and forwards. (the resulting signature is applied on the server level in Exchange Online) The email signat…
Please read the paragraph below before following the instructions in the video — there are important caveats in the paragraph that I did not mention in the video. If your PaperPort 12 or PaperPort 14 is failing to start, or crashing, or hanging, …

916 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question