Quantcast
Channel: 午後わてんのブログ
Viewing all articles
Browse latest Browse all 420

マウスクリックでCanvasに直線を描画、Line、Path、WPFとC#

$
0
0

System.Windows.Shapes.Line
マウスクリックで直線(Line)を描画
3年前にWindowsFormとVBだったのをWPFとC#で試してみた

イメージ 1
クリックしたところを始点(X1,Y1)にして、カーソル位置を終点(X2,Y2)にしている


デザイン画面
イメージ 2

C#のコード

using System.Windows;
using System.Windows.Input;

namespace _20180605_クリックで直線ShapeLine
{
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
 
MyCanvas.MouseLeftButtonDown += MyCanvas_MouseLeftButtonDown;
MyCanvas.MouseMove += MyCanvas_MouseMove;
}

private void MyCanvas_MouseMove(object sender, MouseEventArgs e)
{
Point p = e.GetPosition(MyCanvas);
MyLine.X2 = p.X;
MyLine.Y2 = p.Y; 
}

private void MyCanvas_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
Point p = e.GetPosition(MyCanvas);
MyLine.X1 = p.X;
MyLine.Y1 = p.Y;
}
}
}





イメージ 3
Lineが残るようにしてみただけ

デザイン画面
イメージ 4


C#のコード

using System.Windows;
using System.Windows.Input;

namespace _20180605_クリックで直線ShapeLine2
{
public partial class MainWindow : Window
{
bool IsDraw;

public MainWindow()
{
InitializeComponent();
MyCanvas.MouseLeftButtonDown += MyCanvas_MouseLeftButtonDown;
MyCanvas.MouseMove += MyCanvas_MouseMove;
}

private void MyCanvas_MouseMove(object sender, MouseEventArgs e)
{
if (IsDraw == true)
{
Point p = e.GetPosition(MyCanvas);
MyLine.X2 = p.X;
MyLine.Y2 = p.Y;
}
}

private void MyCanvas_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
Point p = e.GetPosition(MyCanvas);

if (IsDraw == true)
{
IsDraw = false;
MyLine.X2 = p.X;
MyLine.Y2 = p.Y;
}
else
{
IsDraw = true;
MyLine.X1 = p.X;
MyLine.Y1 = p.Y;
}
}
}
}



System.Windows.Shapes.Path
Pathを使ってクリックした場所を直線で繋いで描画
イメージ 5
Lineは1本の直線の図形なので複数の直線は繋げられないようだったので
Pathを使ってみた


イメージ 6


C#コード、書き直す前

using System.Windows;
using System.Windows.Input;
using System.Windows.Media;

namespace _20180605_クリックで直線PathGeometry
{

public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
MyCanvas.MouseMove += MyCanvas_MouseMove;
MyCanvas.MouseLeftButtonDown += MyCanvas_MouseLeftButtonDown;
MyCanvas.MouseRightButtonDown += MyCanvas_MouseRightButtonDown;
}

private void MyCanvas_MouseRightButtonDown(object sender, MouseButtonEventArgs e)
{
iPath.Data = null;//PathDataの初期化
}

private void MyCanvas_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
Point p = e.GetPosition(MyCanvas);
if (iPath.Data == null)
{
MyPathStartPoint(p);//最初のクリック時
}
else
{
//クリックした座標をLineSegmentとして追加する
var pg = (PathGeometry)iPath.Data;
PathFigure pf = pg.Figures[0];
pf.Segments.Add(new LineSegment(p, true));
}
}

//マウス移動時は最後にクリックした点から伸びる線を描画する
private void MyCanvas_MouseMove(object sender, MouseEventArgs e)
{
if (iPath.Data != null)
{
Point p = e.GetPosition(MyCanvas);//マウスカーソル位置

var pg = (PathGeometry)iPath.Data;
PathSegmentCollection psc = pg.Figures[0].Segments;
PathSegment pathSegment = psc[psc.Count - 1];//終端
//SetValueで終端座標を指定(マウスカーソルの位置)
pathSegment.SetValue(LineSegment.PointProperty, p);
}
}
//最初のクリック時にPathのDataになるPathGeometryを作成
//開始点と次点を指定する
private void MyPathStartPoint(Point p)
{
PathFigure pathFigure = new PathFigure();
pathFigure.StartPoint = p;//開始点
//次点をLineSegmentで作成してSegmentsに追加
pathFigure.Segments.Add(new LineSegment(p, true));
PathFigureCollection pathFigureCollection = new PathFigureCollection();
pathFigureCollection.Add(pathFigure);
PathGeometry pathGeometry = new PathGeometry();
pathGeometry.Figures = pathFigureCollection;
//
iPath.Data = pathGeometry;
}
}
}


PathのDataプロパティにPathGeometryを指定
クリックした座標を追加していくところはPathSegmentCollectionで
Pathからたどっていくと

Path.Data
PathGeometry.Figures
PathFigureCollection
PathFigure.Segments
PathSegmentCollection
LineSegment

LineSegmentのPointプロパティにx,y座標を指定してPathSegmentCollectionに追加していく
イメージ 7
遠いなあ

イメージ 8
最初のクリック時にPathのDataになるPathGeometryを作成
今見てて思ったのがPathSegmentCollectionは特に作成していないけど、73行目でAddでいいんだなあと、ってことは79行目もFiguresにPathFigureCollectionを指定しているけど、これも直接Addで追加できるのかなと思って

イメージ 9
こうしてみたら、これでも動いた
このほうがラクだわ


左クリック時はクリックした座標を追加
イメージ 10
PathGeometryの最初([0])のFiguresのSegmentにクリック座標のLineSegmentを追加



マウス移動時は最後にクリックした点から伸びる直線を描画
イメージ 11
59行目でLineSegmentが入っているPathSegmentCollectionを取得
これが
イメージ 12
この赤字のところで
これの最後にあるLineSegmentの座標を今のマウスカーソルの座標にするので
最後のインデックスはCount-1
これでPathSegmentを取得して、60行目
62行目で座標を指定している、指定するのにSetValueとか分かりづらいのを使っている
今思ったのが、60行目でPathSegmentじゃなくてLineSegmentにキャストして取得すればいいのでは、ってことで書き直して

イメージ 13
これでOK、座標指定も普通にPointで指定できた!


右クリック時はPath.Dataの消去
イメージ 14


C#コード、書き直し後

using System.Windows;
using System.Windows.Input;
using System.Windows.Media;


namespace _20180605_クリックで直線PathGeometry
{

public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
MyCanvas.MouseMove += MyCanvas_MouseMove;
MyCanvas.MouseLeftButtonDown += MyCanvas_MouseLeftButtonDown;
MyCanvas.MouseRightButtonDown += MyCanvas_MouseRightButtonDown;
}

private void MyCanvas_MouseRightButtonDown(object sender, MouseButtonEventArgs e)
{
iPath.Data = null;//PathDataの初期化
}

private void MyCanvas_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
Point p = e.GetPosition(MyCanvas);
if (iPath.Data == null)
{
MyPathStartPoint(p);//最初のクリック時
}
else
{
//クリックした座標をLineSegmentとして追加する
var pg = (PathGeometry)iPath.Data;
PathFigure pf = pg.Figures[0];
pf.Segments.Add(new LineSegment(p, true));
}
}

//マウス移動時は最後にクリックした点から伸びる線を描画する
private void MyCanvas_MouseMove(object sender, MouseEventArgs e)
{
if (iPath.Data != null)
{
Point p = e.GetPosition(MyCanvas);//マウスカーソル位置

var pg = (PathGeometry)iPath.Data;
PathSegmentCollection psc = pg.Figures[0].Segments;
LineSegment lineSegment = (LineSegment)psc[psc.Count - 1];//終端
//終端座標を指定(マウスカーソルの位置)
lineSegment.Point = p;
}
}
//最初のクリック時にPathのDataになるPathGeometryを作成
//開始点と次点を指定する
private void MyPathStartPoint(Point p)
{
PathFigure pathFigure = new PathFigure();
pathFigure.StartPoint = p;//開始点
//次点をLineSegmentで作成してSegmentsに追加
pathFigure.Segments.Add(new LineSegment(p, true));
PathGeometry pathGeometry = new PathGeometry();
pathGeometry.Figures.Add(pathFigure);
//
iPath.Data = pathGeometry;
}
}
}


イメージ 15


コード全部


WindowsFormと比べるとWPFは直線一つなら同じ感じだけど、複数の直線を繋げた描画は少しややこしいかなあ、もっとラクな方法ないかしら


参照したところ




関連記事
2015/1/21
マウスクリックでPictureBoxに直線を描くテスト、VisualBasic2013 ( ソフトウェア ) - 午後わてんのブログ - Yahoo!ブログ
https://blogs.yahoo.co.jp/gogowaten/12634284.html




Viewing all articles
Browse latest Browse all 420

Trending Articles