WPFで自由にRectangleを描画する
先日、WPFで特定のアプリケーションに限定してスリーンショット録画の方法をまとめました。
elsammit-beginnerblg.hatenablog.com
ですが、
・複数アプリを録画したい
・好きなエリアを指定したい
といった場合にはアプリケーションに限定するだけでは不十分です。。
そこで、自分で指定したエリアで録画するアプリケーションを実装したいと考えました!
今回は、エリアを指定するためにRectangleを描画する方法をまとめたいと思います。
■xamlの実装
今回メインウィンドウとして実装したxamlはこちらになります。
ウィンドウにBorderで枠線を作成し、その中にCanvasを差し込んでいるシンプルな構成です。
Canvasの名前は"CanvasArea"としました。
Canvas上ではトリガとしてこちらを定義しました。
・マウスの左ボタン押す :MouseLeftDwn
・マウスの左ボタン上げる:MouseLeftUp
・マウスを動かす :MouseMoving
<Window x:Class="WpfApp2.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:local="clr-namespace:WpfApp2" mc:Ignorable="d" Title="MainWindow" Height="408.739" Width="659.456"> <Grid> <Border BorderBrush="Black" BorderThickness="1" HorizontalAlignment="Left" Height="277" Margin="64,49,0,0" VerticalAlignment="Top" Width="528" Background="#00000000"> <Canvas x:Name="CanvasArea" HorizontalAlignment="Left" Height="273" Margin="0,1,0,0" VerticalAlignment="Top" Width="523" Panel.ZIndex="1" PreviewMouseLeftButtonUp="MouseLeftUp" PreviewMouseLeftButtonDown="MouseLeftDwn" PreviewMouseMove="MouseMoving" Background="White" /> </Border> </Grid> </Window>
■好きなエリアにRectangleを作成する
では早速、Canvas上にエリアを指定するためのRectangleを描画してみたいと思います。
コードはこちら。
using System; using System.Collections.Generic; using System.Windows; using System.Windows.Controls; using System.Windows.Input; using System.Windows.Media; using System.Windows.Shapes; namespace WpfApp2 { /// <summary> /// MainWindow.xaml の相互作用ロジック /// </summary> public partial class MainWindow : Window { bool isWriting = false; Point Init; private List<UIElement> RectangleList = new List<UIElement>(); UIElement RectElement = new UIElement(); public MainWindow() { InitializeComponent(); } private void MouseLeftDwn(object sender, MouseButtonEventArgs e) { Console.WriteLine("Click Mouse Dwn"); Canvas c = sender as Canvas; Init = e.GetPosition(c); c.CaptureMouse(); isWriting = true; } private void MouseLeftUp(object sender, MouseButtonEventArgs e) { if (isWriting) { Console.WriteLine("Click Mouse Up"); Canvas c = sender as Canvas; isWriting = false; c.ReleaseMouseCapture(); } } private void WriteRectangle(Point point) { CanvasArea.Children.Remove(RectElement); Rectangle rect = new Rectangle(); rect.Stroke = new SolidColorBrush(Colors.Red); rect.StrokeThickness = 1; rect.Width = Math.Abs(Init.X - point.X); rect.Height = Math.Abs(Init.Y - point.Y); if(Init.X < point.X) { Canvas.SetLeft(rect, Init.X); } else { Canvas.SetLeft(rect, point.X); } if(Init.Y < point.Y) { Canvas.SetTop(rect, Init.Y); } else { Canvas.SetTop(rect, point.Y); } CanvasArea.Children.Add(rect); RectElement = rect; } private void MouseMoving(object sender, MouseEventArgs e) { if (isWriting) { Console.WriteLine("Click Mouse Move"); Point pos = e.GetPosition(CanvasArea); WriteRectangle(pos); } } } }
マウスの左ボタン押すとMouseLeftDwnが実行されます。
MouseLeftDwnでは、
・マウスの強制キャプチャ
・マウスの位置を記憶
・マウスを押下したフラグをtrue
します。
private void MouseLeftDwn(object sender, MouseButtonEventArgs e) { Console.WriteLine("Click Mouse Dwn"); Canvas c = sender as Canvas; Init = e.GetPosition(c); c.CaptureMouse(); isWriting = true; }
マウスの左ボタン押下した状態でマウスを動かすと、
MouseMovingがコールされます。
MouseMovingではWriteRectangleがコールされ、こちらでRectangleを描画します。
private void MouseMoving(object sender, MouseEventArgs e) { if (isWriting) { Console.WriteLine("Click Mouse Move"); Point pos = e.GetPosition(CanvasArea); WriteRectangle(pos); } }
最後にマウスの左ボタンを離すと、
MouseLeftUpがコールされます。
MouseLeftUpでは、
・マウスの強制キャプチャ解除
・マウスを押下したフラグをfalse
private void MouseLeftUp(object sender, MouseButtonEventArgs e) { if (isWriting) { Console.WriteLine("Click Mouse Up"); Canvas c = sender as Canvas; isWriting = false; c.ReleaseMouseCapture(); } }
このコードを実行すると、
こちらのような結果となります。
■Rectangle描画領域をCanvasに限定する
先ほどのコードでRectangleを好きな位置に描画することが出来るのですが、
領域外にRectangleをはみ出して描画できてしまいます。
次に、Canvas領域内に限定してRectangleを留めるようなコードを実装してみます。
変更するのは、WriteRectangleのみになります。
コードはこちら。
private void WriteRectangle(Point point) { CanvasArea.Children.Remove(RectElement); Rectangle rect = new Rectangle(); rect.Stroke = new SolidColorBrush(Colors.Red); rect.StrokeThickness = 1; rect.Width = Math.Abs(Init.X - point.X); rect.Height = Math.Abs(Init.Y - point.Y); if (point.X > CanvasArea.ActualWidth) { Canvas.SetLeft(rect, Init.X); rect.Width = CanvasArea.ActualWidth - Init.X; } else if (point.X < 0) { Canvas.SetLeft(rect, 0); rect.Width = Init.X; } else if (Init.X < point.X) { Canvas.SetLeft(rect, Init.X); } else { Canvas.SetLeft(rect, point.X); } if (point.Y > CanvasArea.ActualHeight) { Canvas.SetTop(rect, Init.Y); rect.Height = CanvasArea.ActualHeight - Init.Y; } else if (point.Y < 0) { Canvas.SetTop(rect, 0); rect.Height = Init.Y; } else if (Init.Y < point.Y) { Canvas.SetTop(rect, Init.Y); } else { Canvas.SetTop(rect, point.Y); } CanvasArea.Children.Add(rect); RectElement = rect; }
実施していることですが、Canvasのエリア外に出てしまった場合にはサイズを
Canvasサイズ - 初期座標位置
とすることで、Canvasサイズ外にRectangleがはみ出さないように実装しております。
実際に動かすとこちらのようになります。
■最後に
今回はWPFで自由に位置やサイズを指定してRectangleを描画するコードをまとめました。
これをスクリーン録画とマージしてエリア指定して録画するアプリにしていきたいと思います!!