前提・実現したいこと
色々なサイトを確認し、利用させて頂いてます。
たくさんあるのですが、手詰まり状態で困っています。
3日調べましたが、いい方法は見つかりませんでした。
・Rectangle移動後の座標、Canvasの左上を基準としたTop,Leftの値
⇒Canvas.GetLeft、Canvas.GetTopでは取得できませんでした。
RenderTransformの値だからだと思います。
MouseUpの時に現在位置を取得し設定して、RenderTransformを消したいです。
できたら、以下の内容もアドバイスがあれば伺いたいです。
・Rectangelの端をクリックし、ドラッグ移動でRectangleを拡大したい
⇒今のドラッグ移動のコードを一部追加したりすれば
Rectangleを左上座標固定して拡大することは出来そうだと思っています。
カーソルアイコンでの判定をしようと思っており、
これについてはまだ色々検証中です。
該当のソースコード
xaml
1 <Canvas Name="MyCanvas"> 2 <Rectangle x:Name="Rectan" Width="100" Height="100" Fill="Transparent" StrokeThickness="3" Stroke="Red"></Rectangle> 3 </Canvas>
C#
1 2 public PicView() 3 { 4 InitializeComponent(); 5 this.Top = 0;//ウィンドウ自体を移動 6 this.Left = 0;//ウィンドウ自体を移動 7 RectangleEvent(); 8 } 9 10 public void RectangleEvent() { 11 //色や線の太さなどは、後々動的に変更させる 12 Rectan.MouseLeftButtonDown += Rect_MouseLeftButtonDown; 13 Rectan.MouseEnter += Rect_MouseEnter; 14 Rectan.MouseLeave += Rect_Leave; 15 Rectan.MouseLeftButtonUp += Rect_MouseLeftButtonUp; 16 Rectan.MouseMove += Rect_MouseMove; 17 } 18 19 // マウス押下中フラグ 20 private bool _isMouseDown; 21 // マウスの移動が開始されたときの座標 22 private Point _startPoint; 23 // マウスの現在位置座標 24 private Point _currentPoint; 25 26 void Rect_MouseLeftButtonDown(object sender, MouseButtonEventArgs e) 27 { 28 // フラグを"マウス押下中"にする 29 _isMouseDown = true; 30 31 Mouse.OverrideCursor = Cursors.SizeAll; 32 Console.WriteLine("Cursors.Arrow!"); 33 _startPoint = e.GetPosition(MyCanvas); 34 Console.WriteLine(e.GetPosition(sender as Rectangle)); 35 // イベントを処理済みとする(当イベントがこの先伝搬されるのを止めるため) 36 e.Handled = true; 37 } 38 39 // マウス左ボタン解放イベントのハンドラ 40 private void Rect_MouseLeftButtonUp(object sender, MouseButtonEventArgs e) 41 { 42 // マウス押下中フラグを落とす 43 _isMouseDown = false; 44 e.Handled = true; 45 } 46 private void Rect_MouseEnter(object sender, System.Windows.Input.MouseEventArgs e) 47 { 48 (sender as Rectangle).Fill = new SolidColorBrush(Colors.Yellow); 49 Mouse.OverrideCursor = Cursors.SizeNWSE;//拡大アイコン 50 Console.WriteLine("マウスIN:" + e.GetPosition(sender as Rectangle)); 51 52 } 53 54 // マウス移動イベントのイベントハンドラ 55 private void Rect_MouseMove(object sender, MouseEventArgs e) 56 { 57 58 var rec = sender as Rectangle; 59 // マウス押下中でなければドラッグ操作ではないのでメソッドを抜ける 60 if (!_isMouseDown) 61 { 62 return; 63 } 64 65 //if (Mouse.OverrideCursor ==Cursors.SizeNWSE) { 66 //} 67 68 // マウスの現在位置座標を取得(MyCanvasからの相対位置) 69 _currentPoint = e.GetPosition(MyCanvas); 70 71 //移動開始点と現在位置の差から、MouseMoveイベント1回分の移動量を算出 72 double offsetX = _currentPoint.X - _startPoint.X; 73 double offsetY = _currentPoint.Y - _startPoint.Y; 74 75 // 動かす対象の図形からMatrixオブジェクトを取得 76 // このMatrixオブジェクトを用いて図形を描画上移動させる 77 Matrix matrix = ((MatrixTransform)(sender as Rectangle).RenderTransform).Matrix; 78 // TranslateメソッドにX方向とY方向の移動量を渡し、移動後の状態を計算 79 matrix.Translate(offsetX, offsetY); 80 // 移動後の状態を計算したMatrixオブジェクトを描画に反映する 81 (sender as Rectangle).RenderTransform = new MatrixTransform(matrix); 82 83 // 移動開始点を現在位置で更新する 84 // (今回の現在位置が次回のMouseMoveイベントハンドラで使われる移動開始点となる) 85 _startPoint = _currentPoint; 86 e.Handled = true; 87 } 88 private void Rect_Leave(object sender, System.Windows.Input.MouseEventArgs e) 89 { 90 (sender as Rectangle).Fill = Brushes.Transparent;//透明化 91 92 Mouse.OverrideCursor = Cursors.Arrow;//通常アイコン 93 94 _isMouseDown = false; 95 e.Handled = true; 96 } 97
試したこと
C#
1 Canvas.GetLeft(this.Rectan); 2 Canvas.GetTop(this.Rectan);
上記では、初期値が表示されるだけでした。
RenderTransformでRectangleを移動しているからだと思います。
MouseUpの時に現在位置を取得し設定し直して、
RenderTransformを消したいです。
試したこと 6/22 10:28
色々と検証を重ね、
いい方法とは思えませんが、
RectangleCreateにて、Rectangleを削除し作り直すようにしました。
(Eventのものは削除しました。
C#
1RectangleCreate(){ 2 var type = typeof(Brushes); 3 Rectangle Rectan = new Rectangle();//Rectangle新規作成 4 Rectan.Name = "Rectan";//Rectanという名前にする 5 Rectan.Width = Width; 6 Rectan.Height = Height; 7 Canvas.SetTop(Rectan,Y); 8 Canvas.SetLeft(Rectan,X); 9 Rectan.Fill = Brushes.Transparent;//サンプルとして透明固定 10 Rectan.Stroke = Brushes.Red;//サンプルとして赤固定 11 Rectan.StrokeThickness = 2;//サンプルとして2固定 12 Rectan.MouseLeftButtonDown += Rect_MouseLeftButtonDown; 13 Rectan.MouseEnter += Rect_MouseEnter; 14 Rectan.MouseLeave += Rect_Leave; 15 Rectan.MouseLeftButtonUp += Rect_MouseLeftButtonUp; 16 Rectan.MouseMove += Rect_MouseMove; 17 MyCanvas.Children.Add(Rectan); 18}
また、以下のようにしたら、正しい位置に表示されるようになった気がします。
正しいかどうかは不明ですが、見た感じ問題ないような気がします。
X = Canvas.GetLeft(TEST) + TEST.RenderTransform.Value.OffsetX; //OffsetX Y = Canvas.GetTop(TEST) + TEST.RenderTransform.Value.OffsetY;//OffsetY Width = X + TEST.RenderSize.Width;//幅 Height = Y + TEST.RenderSize.Height;//高さ
今2点気になっていることがあります。
・Rectangleを消したいが、名前で指定出来ない
「Rectan」を削除し、作成し直すという手を使おうとしてますが
NameでRectangleを検索できずNullになってしまうため、
Rectangleを動かせば動かすほど出来てしまいます。
var NG1=FindName("Rectan");
var NG2 = this.FindName("Rectan") as Rectangle;
Rectangle NG3 = (Rectangle)this.MyCanvas.FindName("Rectan");
・マウス左クリックを外していないのに、勝手にRectangleから外れる
マウスの動きが速かったり、Rectangleが小さいと
クリックしたままでも勝手にドラッグ判定から外れてしまいます。
・そもそも、移動機能は必要なのか…
WPF Canvasにマウスで図形を描画する方法
https://hyperts.net/wpf-drawcanvas-mouse/
Imageの上に、ユーザーがドラッグで四角形を描く。
そして、その四角形の場所、サイズなどを保存したいと思っていました。
描いた四角形の移動や拡縮は、四角形を描いた後の話であり
先に上記サイトのCanvasにRectangleを描く方を実施しようと思います。
そのRectangleを移動および拡縮できるように検討したいと思います。
とりあえず、TN8001様に教えて頂いた「ラバーバンド」というものを
調べてみようと思います。
補足情報(FW/ツールのバージョンなど)
VisualStudio 2019
.NET 4.5(だったはず)
WPF C# (※ WinFormではない)
あなたの回答
tips
プレビュー