FreeDraw.cs
using System.Runtime.CompilerServices;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Shapes;
namespace Maywork.WPF.Helpers;
public static class FreeDraw
{
// Canvasごとの内部状態
class DrawState
{
public bool IsDrawing;
public PathFigure? Figure;
public PathGeometry? Geometry;
public Path? Path;
}
// Canvas → State
static readonly ConditionalWeakTable<Canvas, DrawState> states = new();
static DrawState GetState(Canvas canvas)
=> states.GetOrCreateValue(canvas);
// 描画モードON/OFF
public static readonly DependencyProperty DrawEnabledProperty =
DependencyProperty.RegisterAttached(
"DrawEnabled",
typeof(bool),
typeof(FreeDraw),
new PropertyMetadata(false, OnChanged));
public static void SetDrawEnabled(UIElement element, bool value)
=> element.SetValue(DrawEnabledProperty, value);
public static bool GetDrawEnabled(UIElement element)
=> (bool)element.GetValue(DrawEnabledProperty);
static void OnChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
if (d is not Canvas canvas)
return;
bool enabled = (bool)e.NewValue;
if (enabled)
{
canvas.MouseDown += MouseDown;
canvas.MouseMove += MouseMove;
canvas.MouseUp += MouseUp;
}
else
{
canvas.MouseDown -= MouseDown;
canvas.MouseMove -= MouseMove;
canvas.MouseUp -= MouseUp;
}
}
static void MouseDown(object sender, MouseButtonEventArgs e)
{
if (sender is not Canvas canvas)
return;
var state = GetState(canvas);
state.IsDrawing = true;
Point p = e.GetPosition(canvas);
state.Figure = new PathFigure
{
StartPoint = p
};
state.Geometry = new PathGeometry();
state.Geometry.Figures.Add(state.Figure);
state.Path = new Path
{
Stroke = Brushes.Black,
StrokeThickness = 2,
Data = state.Geometry
};
canvas.Children.Add(state.Path);
canvas.CaptureMouse();
}
static void MouseMove(object sender, MouseEventArgs e)
{
if (sender is not Canvas canvas)
return;
var state = GetState(canvas);
if (!state.IsDrawing || state.Figure is null)
return;
Point p = e.GetPosition(canvas);
state.Figure.Segments.Add(new LineSegment(p, true));
}
static void MouseUp(object sender, MouseButtonEventArgs e)
{
if (sender is not Canvas canvas)
return;
var state = GetState(canvas);
state.IsDrawing = false;
canvas.ReleaseMouseCapture();
}
}
/*
// 使い方
XAML
xmlns:h="clr-namespace:Maywork.WPF.Helpers"
<Canvas
Background="White"
h:FreeDraw.DrawEnabled="True"/>
*/
Download

コメント