今回のアプリのダウンロード先
3年前にWindowsFormと
VBだったのを
WPFと
C#で試してみた
クリックしたところを始点(X1,Y1)にして、カーソル位置を終点(X2,Y2)にしている
デザイン画面
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;
}
}
}
デザイン画面
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;
}
}
}
}
Pathを使ってクリックした場所を直線で繋いで描画
Lineは1本の直線の図形なので複数の直線は繋げられないようだったので
Pathを使ってみた
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;
}
private void MyCanvas_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
Point p = e.GetPosition(MyCanvas);
if (iPath.Data == null)
{
MyPathStartPoint(p);
}
else
{
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];
pathSegment.SetValue(LineSegment.PointProperty, p);
}
}
private void MyPathStartPoint(Point p)
{
PathFigure pathFigure = new PathFigure();
pathFigure.StartPoint = p;
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に追加していく
最初のクリック時にPathのDataになるPathGeometryを作成
今見てて思ったのがPathSegmentCollectionは特に作成していないけど、73行目でAddでいいんだなあと、ってことは79行目もFiguresにPathFigureCollectionを指定しているけど、これも直接Addで追加できるのかなと思って
左クリック時はクリックした座標を追加
PathGeometryの最初([0])のFiguresのSegmentにクリック座標のLineSegmentを追加
マウス移動時は最後にクリックした点から伸びる直線を描画
59行目でLineSegmentが入っているPathSegmentCollectionを取得
これが
これの最後にあるLineSegmentの座標を今のマウスカーソルの座標にするので
最後のインデックスはCount-1
これでPathSegmentを取得して、60行目
62行目で座標を指定している、指定するのにSetValueとか分かりづらいのを使っている
今思ったのが、60行目でPathSegmentじゃなくてLineSegmentにキャストして取得すればいいのでは、ってことで書き直して
これでOK、座標指定も普通にPointで指定できた!
右クリック時はPath.Dataの消去
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;
}
private void MyCanvas_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
Point p = e.GetPosition(MyCanvas);
if (iPath.Data == null)
{
MyPathStartPoint(p);
}
else
{
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;
}
}
private void MyPathStartPoint(Point p)
{
PathFigure pathFigure = new PathFigure();
pathFigure.StartPoint = p;
pathFigure.Segments.Add(new LineSegment(p, true));
PathGeometry pathGeometry = new PathGeometry();
pathGeometry.Figures.Add(pathFigure);
iPath.Data = pathGeometry;
}
}
}
コード全部
WindowsFormと比べると
WPFは直線一つなら同じ感じだけど、複数の直線を繋げた描画は少しややこしいかなあ、もっと
ラクな方法ないかしら
2018/06/08追記
参照したところ
関連記事
2015/1/21は3年前