canvasに書いた線をドラッグ&ドロップさせるには?


シンハ  2001-10-31 02:04:33  No: 260  IP: [192.*.*.*]

canvasでLinetoやPolyline等で書いた線をドラッグ&ドロップさせるにはどうすればよいでしょうか?

delphi始めて一ヶ月の初心者です。出来れば簡単な答えをお願いします。

編集    削除
にしの  2001-10-31 03:45:00  No: 261  IP: [192.*.*.*]

無理です。
描いたものは、単なる線ですから。
紙に書かれた線を移動するのと同じです。
やるとしたら、マウスのイベントを駆使してください。

すぐには例を出せませんが、簡単に説明すると
1.OnMouseDownイベントで、(X,Y)が線の上かどうかを判別。上ならば、「マウスが線上で押された」フラグをたてる(線のどこで押されたかも記録)。
2.OnMouseMoveイベントで、「マウスが線上で押された」フラグがたっていれば、線を移動する(線のどこで押されたかによって、その差分を移動させた後、描画し直す)。
3.OnMouseUpイベントで、フラグをクリア。

です。
このほかにも、対象エリア外でマウスを放した場合なども考慮しないといけないでしょう。

編集    削除
シンハ  2001-10-31 05:25:00  No: 262  IP: [192.*.*.*]

にしのさん、早速の解答ありがとうございます。
やっぱり無理ですか・・・。

では具体的に、どういう風に線を書いたらいいと思いますか?
書いた線というのは、書いた後更に、編集(伸ばしたり、縮めたり、折れ曲る)ができないとダメなんです。

まったく見当がつかないので、お願いします。

編集    削除
にしの  2001-10-31 19:49:17  No: 263  IP: [192.*.*.*]

そのアプリケーションの仕様がわからないと、コメントしにくいのですが、線をドラッグするのでなく、点をドラッグするのなら結構簡単です。

パネルを4つ用意します。大きさは、5x5くらいでよいです。
このうち2つ(Panel1,Panel2とします)の、BevelInner,BevelOuterをbvNoneに、ColorをclBlackに、CursorをcrSizeAllにします。
残りの2つ(Panel3,Panel4とします)の、BevelInner,BevelOuterをbvNoneに、ColorをclBlack(これは何でもよいですが)に、VisibleをFalseにします。

フォーム(Form1とします)のprivate宣言に、
b1, b2: boolean; // マウスがおされている
px1, py1: integer; // パネル1が押されたときの差分
px2, py2: integer; // パネル2が押されたときの差分
を宣言します。

あとは、Panel1,Panel2のMouseDown,MouseMove,MouseUpイベントと、FormPaintイベントを用意すればOKです。

こんな感じです。
あとはいろいろ試してみてください。
やり方はたくさんあります。
ちなみに、このままだと、マウスダウン状態でAlt+TABすると、他のアプリケーションがアクティブになりますが、マウスアップ処理が動かないため変な動作になります。

procedure TForm1.FormPaint(Sender: TObject);
var
  pt1, pt2: TPoint;
begin
  if b1 then
  begin
    pt1.x := Panel3.Left;
    pt1.y := Panel3.Top;
  end
  else
  begin
    pt1.x := Panel1.Left;
    pt1.y := Panel1.Top;
  end;
  if b2 then
  begin
    pt2.x := Panel4.Left;
    pt2.y := Panel4.Top;
  end
  else
  begin
    pt2.x := Panel2.Left;
    pt2.y := Panel2.Top;
  end;
  Canvas.MoveTo(pt1.x + 2, pt1.y + 2);
  Canvas.LineTo(pt2.x + 2, pt2.y + 2);
end;

procedure TForm1.Panel1MouseDown(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
begin
  px1 := X;
  py1 := Y;
  Panel3.Left := Panel1.Left;
  Panel3.Top  := Panel1.Top;
  Panel3.Visible := True;
  b1 := true;
end;

procedure TForm1.Panel1MouseMove(Sender: TObject; Shift: TShiftState; X,
  Y: Integer);
begin
  if not b1 then Exit;
  Panel3.Left := Panel1.Left + X - px1;
  Panel3.Top  := Panel1.Top  + Y - py1;
  Refresh;
end;

procedure TForm1.Panel1MouseUp(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
begin
  if b1 then
  begin
    Panel1.Left := Panel3.Left;
    Panel1.Top  := Panel3.Top;
    Panel3.Visible := False;
  end;
  b1 := false;
end;

procedure TForm1.Panel2MouseDown(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
begin
  px2 := X;
  py2 := Y;
  Panel4.Left := Panel2.Left;
  Panel4.Top  := Panel2.Top;
  Panel4.Visible := True;
  b2 := true;
end;

procedure TForm1.Panel2MouseMove(Sender: TObject; Shift: TShiftState; X,
  Y: Integer);
begin
  if not b2 then Exit;
  Panel4.Left := Panel2.Left + X - px2;
  Panel4.Top  := Panel2.Top  + Y - py2;
  Refresh;
end;

procedure TForm1.Panel2MouseUp(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
begin
  if b2 then
  begin
    Panel2.Left := Panel4.Left;
    Panel2.Top  := Panel4.Top;
    Panel4.Visible := False;
  end;
  b2 := false;
end;

編集    削除