0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

ひとりで完走_C# is GODAdvent Calendar 2024

Day 2

Win2Dについて その2 ドラッグで描画

Last updated at Posted at 2024-12-01

はじめに

前回のWin2Dを使用してプログラムから描画する方法を解説しました。
今回はペイントソフトで欠かせないマウス操作からの図形描画について解説したいと思います。
例としてマウスドラッグで四角形を描画する方法について解説していきます。

UIコントロール

前回の追加したコントロールにマウス操作のイベントを追加していきます。
追加するのは以下のイベントです。
PointerPressed・・・マウスをコントロール内でクリックしたときに発火
PointerMoved・・・マウスをコントロール内で動かしたときに発火
PointerReleased・・・マウスクリックをコントロール内で離したときに発火
このイベントを追加することで、マウスをドラッグしたときの処理を加えることができます。

<canvas:CanvasControl
    x:Name="canvas"
    CreateResources="Canvas_CreateResources"
    Draw="Canvas_Draw"
+   PointerMoved="Canvas_PointerMoved"
+   PointerPressed="Canvas_PointerPressed"
+   PointerReleased="Canvas_PointerReleased"
    />

ドラッグ処理用クラス作成

ドラッグで描画していくための、最初の位置、現在の位置を保持するためのPointerDragクラスを作成します。

using Windows.Foundation;

public class PointerDrag
{
    //データを保持するフィールドを作る
    public Point StartLocation {  get; set; }
    public Point CurrentLocation { get; set; }

    //コンストラクタで現在のマウスの位置を与え初期化する
    public PointerDrag(Point location)
    {
        StartLocation = location;
        CurrentLocation = location;
    }
}

WinUI3ではマウスの位置がWindows.Foundation.Point構造体によって取得されるので、フィールドもPoint型を指定してます。

マウスクリックイベント

マウスをクリックしたときの処理を追加していきます。
MainWindow.xaml.csに戻り、先ほど作成したマウスの位置を保持するクラスをフィールドとして追加します。
また、マウスをドラッグしているかを示す変数も追加します。

public sealed partial class MainWindow : Window
{
    PointerDrag pointerDrag;
    bool mouseDown = false;
}

マウスクリックのイベントを作成します。

private void Canvas_PointerPressed(object sender, Microsoft.UI.Xaml.Input.PointerRoutedEventArgs e)
{
    mouseDown = true;
    pointerDrag = new PointerDrag(e.GetCurrentPoint(canvas).Position);
    canvas.Invalidate();
}

マウスが押されたことをmouseDownに保持します。
ドラッグにおいてのマウスクリックは最初に現在のマウスの場所を取得すればよいだけです。
e.GetCurrentPoint(canvas).Positionでイベントが発火したときのコントロール上のマウスの位置を取得しています。
canvas.Invalidate()はコントロールの描画処理を更新するための関数です。
canvasはコントロールにつけたx:Nameによって異なる

マウスムーブイベント

コントロール上でマウスが動いているときに発火します。

private void Canvas_PointerMoved(object sender, Microsoft.UI.Xaml.Input.PointerRoutedEventArgs e)
{
    // マウスがクリックされていないときはドラッグではないので処理を無視する
    if (mouseDown == false)
        return; 
    pointerDrag.CurrentLocation = e.GetCurrentPoint(canvas).Position;
    canvas.Invalidate();
}

CurrentLocationに現在の位置を入れます

マウスリリースイベント

マウスを離したときに発火します。

private void Canvas_PointerReleased(object sender, Microsoft.UI.Xaml.Input.PointerRoutedEventArgs e)
{
    pointerDrag.CurrentLocation = e.GetCurrentPoint(canvas).Position;
    mouseDown = false;
    canvas.Invalidate();
}

マウスムーブと同様に離した位置を現在の位置として保持します。
マウスが離されたのでmouseDownfalseにしています。

描画

その1と同様にDrawイベントで描画処理をします。
四角形のはじめと終わりの点についてはpointerDragが保持しているのでそれを使い、Rectとして代入しています。

private void Canvas_Draw(CanvasControl sender, CanvasDrawEventArgs args)
{
    var ds = args.DrawingSession;
    ds.DrawRectangle(new Rect(pointerDrag.StartLocation, pointerDrag.CurrentLocation), Color.FromArgb(255, 0, 0, 0));
}

これでコントロール上でドラッグすると四角が描けると思います。
MainWindow.xaml.csの全体は以下

public sealed partial class MainWindow : Window
{
    PointerDrag pointerDrag;
    bool mouseDown = false;

    public MainWindow()
    {
        this.InitializeComponent();
    }

    private void Canvas_PointerPressed(object sender, Microsoft.UI.Xaml.Input.PointerRoutedEventArgs e)
    {
        mouseDown = true;
        pointerDrag = new PointerDrag(e.GetCurrentPoint(canvas).Position);
        canvas.Invalidate();
    }

    private void Canvas_PointerMoved(object sender, Microsoft.UI.Xaml.Input.PointerRoutedEventArgs e)
    {
        // マウスがクリックされていないときはドラッグではないので処理を無視する
        if (mouseDown == false)
            return; 
        pointerDrag.CurrentLocation = e.GetCurrentPoint(canvas).Position;
        canvas.Invalidate();
    }
    
    private void Canvas_PointerReleased(object sender, Microsoft.UI.Xaml.Input.PointerRoutedEventArgs e)
    {
        pointerDrag.CurrentLocation = e.GetCurrentPoint(canvas).Position;
        mouseDown = false;
        canvas.Invalidate();
    }

    private void Canvas_Draw(CanvasControl sender, CanvasDrawEventArgs args)
    {
        var ds = args.DrawingSession;
        ds.DrawRectangle(new Rect(pointerDrag.StartLocation, pointerDrag.CurrentLocation), Color.FromArgb(255, 0, 0, 0));
    }
}

複数の描画についての対応

先ほどのコードは1つの描画には対応していますが、2個目を描画するとき1つ目に書いたものが消えてしまいます。
その時はListでpointerDragを保持し、マウスリリースでAddforeachで複数描画という形で書けばよいです。

+   List<PointerDrag> pointerDrags = new List<PointerDrag>();
    PointerDrag pointerDrag;
    bool mouseDown = false;

    private void Canvas_PointerReleased(object sender, Microsoft.UI.Xaml.Input.PointerRoutedEventArgs e)
    {
        pointerDrag.CurrentLocation = e.GetCurrentPoint(canvas).Position;
        mouseDown = false;
+       pointerDrags.Add(pointerDrag);
        canvas.Invalidate();
    }

    private void Canvas_Draw(CanvasControl sender, CanvasDrawEventArgs args)
    {
        var ds = args.DrawingSession;
+       foreach(var point in pointerDrags)
        {
            ds.DrawRectangle(new Rect(point.StartLocation, point.CurrentLocation), Color.FromArgb(255, 0, 0, 0));
        }
    }
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?