Solved

Clickable line

Posted on 2001-06-27
7
220 Views
Last Modified: 2010-05-18
Hi,

Is there anyone out there who know if it's possible to draw a line on the "canvas" and have it reacting on mouseclick.

Example of the setup is I have five buttons on the form and connect them with lines.
I then want to be able to click on the line and get information on for instance the X and Y points of the endpoints.

If it's possible i also want to assign a "name" to this line to be able to sort wich line is selected if I have for instance 15 lines in a star pattern.

Hoping for this as I have tried myself and failed..
0
Comment
Question by:samone
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
7 Comments
 
LVL 27

Expert Comment

by:kretzschmar
ID: 6230866
? maybe
use tshape(s)
0
 
LVL 9

Accepted Solution

by:
ITugay earned 200 total points
ID: 6230925
Hi samone,

here is sample unit. It generates 10 random lines. All lines drawn in OnPaint method.
Moving the mouse (OnMouseMove) over the one of line you can see how cursor changed to crHandPoint.
Clickin on line (OnMouseDown) you can change it's "Selected" property.

Be sure you include "Contnrs" unit in your uses clause.

Enjoy :-)

------
Igor.


unit Unit1;

interface

uses
  Windows, Classes, Graphics, Controls, Forms,
  Contnrs;

type

  TLine = class(TObject)
    A: TPoint;
    B: TPoint;
    Selected: Boolean;
  end;

  TForm1 = class(TForm)
    procedure FormPaint(Sender: TObject);
    procedure FormMouseMove(Sender: TObject; Shift: TShiftState; X,
      Y: Integer);
    procedure FormCreate(Sender: TObject);
    procedure FormMouseDown(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
  private
  public
    Lines: TObjectList;
  end;

var
  Form1: TForm1;

implementation

{$R *.DFM}

// check that point P lie on line with coordinates X1.Y1 - X2.Y2
// Delta - possible distance from the line's point
function PointOnLine(X1,Y1, X2,Y2: Integer; P: TPoint; Delta: Integer): Boolean;
var
  Step: Real;
  R: TRect;
  N: Integer;
  Z: Real;
begin
  Result := False;
  if (Abs(X2-X1) > Abs(Y2-Y1)) and (X2-X1 <> 0) then
  begin
    Step := (Y2- Y1)/abs((X2 - X1));
    if X2 > X1 then N := 1 else N := -1;
    Z := Y1;

    while X1 <> X2 do
    begin
      SetRect(R, X1, Round(Z), X1, Round(Z));
      InflateRect(R, Delta, Delta);
      if PtInRect(R, P) then
      begin
        Result := True;
        Break;
      end;
      Z := Z + Step;
      X1 := X1 + N;
    end;
  end
  else
  if Y2 - Y1 <> 0 then
  begin
    Step := (X2 - X1)/abs((Y2 - Y1));
    if Y2 > Y1 then N := 1 else N := -1;
    Z := X1;

    while Y1 <> Y2 do
    begin
      SetRect(R, Round(Z), Y1, Round(Z), Y1);
      InflateRect(R, Delta, Delta);
      if PtInRect(R, P) then
      begin
        Result := True;
        Break;
      end;
      Z := Z + Step;
      Y1 := Y1 + N;
    end;
  end;
end;

procedure TForm1.FormCreate(Sender: TObject);
var
  I: Integer;
  L: TLine;
begin
  Randomize;
  Lines := TObjectList.Create(true);
  // create 10 random lines
  for I := 1 to 10 do
  begin
    L := TLine.Create;
    L.A.X := Random(Width);
    L.B.X := Random(Width);
    L.A.Y := Random(Height);
    L.B.Y := Random(Height);
    Lines.Add(L);
  end;
end;

procedure TForm1.FormPaint(Sender: TObject);
var
  I: Integer;
  L: TLine;
begin
  // draw generated lines
  with Form1.Canvas do
  for I := 0 to Lines.Count - 1 do
  begin
    L := TLine(Lines[I]);
    if L.Selected then
      Pen.Color := clRed
    else
      Pen.Color := clBlack;

    MoveTo(L.A.X, L.A.Y);
    LineTo(L.B.X, L.B.Y);
  end;
end;

procedure TForm1.FormMouseMove(Sender: TObject; Shift: TShiftState; X,
  Y: Integer);
var
  P: TPoint;
  I: Integer;
  L: TLine;
begin
  P.X := X;
  P.Y := Y;
  Cursor := crDefault;
  // detect when mouse over the one of line
  for I := 0 to Lines.Count - 1 do
  begin
    L := TLine(Lines[I]);
    if PointOnLine(L.A.X, L.A.Y, L.B.X, L.B.Y, P, 3) then
      Cursor := crHandPoint;
  end;
end;

procedure TForm1.FormMouseDown(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
var
  P: TPoint;
  I: Integer;
  L: TLine;
begin
  P.X := X;
  P.Y := Y;
  // select deselect line when mouse clicked on it
  for I := 0 to Lines.Count - 1 do
  begin
    L := TLine(Lines[I]);
    if PointOnLine(L.A.X, L.A.Y, L.B.X, L.B.Y, P, 3) then
    begin
      L.Selected := not L.Selected;
      Invalidate;
    end;
  end;
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
  Lines.Free;
end;

end.
0
 
LVL 27

Expert Comment

by:kretzschmar
ID: 6230950
nice igor ;-)
0
Industry Leaders: 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!

 
LVL 9

Expert Comment

by:ITugay
ID: 6230953
just compilation from another samples :-)
0
 
LVL 17

Expert Comment

by:geobul
ID: 6231349
Hi,
Just another way:

DrawLine adds a line to a StringList with coordinates and name. Label1 shows current line name and coordinates(OnMouseMove).

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  StdCtrls;

type
  TForm1 = class(TForm)
    Label1: TLabel;
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
    procedure FormMouseMove(Sender: TObject; Shift: TShiftState; X,
      Y: Integer);
    procedure FormPaint(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;
  LineList : TStringList;

implementation

{$R *.DFM}

const
  Sensitivity = 50;

function Min(X1,X2: integer): integer;
begin
 if X1 <= X2 then result := X1
             else result := X2;
end;

function Max(X1,X2: integer): integer;
begin
 if X1 >= X2 then result := X1
             else result := X2;
end;

procedure DrawLine(X1,Y1,X2,Y2: integer; Name: string);
begin
  with Form1.Canvas do begin
    MoveTo(X1,Y1);
    LineTo(X2,Y2);
  end;
  LineList.Add(Format('%.4d',[X1])+Format('%.4d',[Y1])+Format('%.4d',[X2])+Format('%.4d',[Y2])+Name);
end;

function OverLine(X,Y: integer): integer;
var
  X1,Y1,X2,Y2: integer;
  i: integer;
begin
 result := -1;
 for i := 0 to LineList.Count - 1 do begin
  X1 := StrToInt(Copy(LineList[i],1,4));
  Y1 := StrToInt(Copy(LineList[i],5,4));
  X2 := StrToInt(Copy(LineList[i],9,4));
  Y2 := StrToInt(Copy(LineList[i],13,4));
  if (Y-Y1 <> 0) and (Y-Y1 <> 0) and (X-X2 <> 0) and (X1-X2 <> 0) then begin
   if (X >= Min(X1,X2)) and (X <= Max(X1,X2)) and (Y >= Min(Y1,Y2)) and (Y <= Max(Y1,Y2)) then begin
    if (Round(((X - X1)/(Y - Y1))*Sensitivity) = Round(((X2 - X1)/(Y2 - Y1))*Sensitivity)) or
       (Round(((Y - Y2)/(X - X2))*Sensitivity) = Round(((Y1 - Y2)/(X1 - X2))*Sensitivity)) then begin
      result := i;
      exit;
    end;
   end;
  end;
 end;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  LineList := TStringList.Create;
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
  LineList.Free;
end;

procedure TForm1.FormPaint(Sender: TObject);
begin
  DrawLine(5,200,100,5,'Line1');
  DrawLine(5,5,100,200,'Line2');
end;

procedure TForm1.FormMouseMove(Sender: TObject; Shift: TShiftState; X,
  Y: Integer);
var
 i: integer;
 s: string;
begin
 i := OverLine(X,Y);
 if i > -1 then begin
  s := LineList[i];
  Label1.Caption := Copy(s,17,Length(s) - 16) + ' ' +
    Copy(s,1,4) + ',' + Copy(s,5,4) + ',' +
    Copy(s,9,4) + ',' + Copy(s,13,4);
  end else Label1.Caption := '';
end;
end.

Regards, Geo
0
 

Expert Comment

by:manata
ID: 6232484
Hi Samone

By now you know how to draw a line on a canvas.

A method to get where you are going would be to use the MoveTo and LineTo methods of the TCanvas Class.

But prior to using this make up coordinates that you may store in an array( ICoordinates : Array[0..10] of Integer;)
this will help you keep track of the starting and ending points of the line.

On your mouse down method you may track the mouse coordinates and compare them to the points in the array.

Facts:
You draw the lines so you know ICoordinates[0] = x Mouse coordinate of the first line, etc

So knowing the order of the lines and the order of the coordinates, the index of the array can work as a tag value of any control.

Good Luck Manata
0
 

Author Comment

by:samone
ID: 6243884
Hi,

I have been sick for a few days and haven't been able too check the answers yet.

I will try to see if and how to use what you have written and I come back with more questions if I don't understand something.

//Ulf
0

Featured Post

Independent Software Vendors: 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 The parallel port is a very commonly known port, it was widely used to connect a printer to the PC, if you look at the back of your computer, for those who don't have newer computers, there will be a port with 25 pins and a small print…
Monitoring a network: why having a policy is the best policy? Michael Kulchisky, MCSE, MCSA, MCP, VTSP, VSP, CCSP outlines the enormous benefits of having a policy-based approach when monitoring medium and large networks. Software utilized in this v…
Do you want to know how to make a graph with Microsoft Access? First, create a query with the data for the chart. Then make a blank form and add a chart control. This video also shows how to change what data is displayed on the graph as well as form…

688 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