Monday, September 21, 2009

Mouse drawing in WPF

I was trying to build a simple control to allow mouse drawing via the WPF. I found one web site that seemed to make the process a bit more complicated than doing the same thing in Windows Forms--but I tried it anyhow, and I simply couldn't make it work. I don't remember the website, but it basically used a canvas, and attempted to draw shapes on it based on Mouse movements. I had implemented routines bound to MouseDown, MouseUp, and MouseMove events, but those events never seemed to execute.
Then I discovered the InkCanvas control--and that solved all my problems. That original code must have come from before the existance of the InkCanvas, or the programmer simply didn't know any better. After switching to use the InkCanvas code I could remove all event handling code so that I only needed the code to capture the resulting image and save it. Below is the XAML:

<

UserControl x:Class="RCO.Imaging.SignaturePad.MouseSignaturePad.SignaturePad"
xmlns=http://schemas.microsoft.com/winfx/2006/xaml/presentation
xmlns:x=http://schemas.microsoft.com/winfx/2006/xaml
HorizontalAlignment="Stretch" Width="Auto" Height="Auto" VerticalAlignment="Stretch" >

<InkCanvas Name="canvas1" Width="Auto" Height="Auto" VerticalAlignment="Stretch" HorizontalAlignment="Stretch" ></InkCanvas>

</

UserControl>

And here is the C# behind it:





using
System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace

MousePad
{
/// <summary>
/// Interaction logic for SignaturePad.xaml
/// </summary>
public partial class SignaturePad : UserControl
{
public SignaturePad()
{
InitializeComponent();
}

public static RenderTargetBitmap ToImageSource(FrameworkElement obj)
{

// Save current canvas transform
Transform transform = obj.LayoutTransform;
obj.LayoutTransform =
null;
// fix margin offset as well
Thickness margin = obj.Margin;
obj.Margin =
new Thickness(0, 0,
margIn.Right - margin.Left, margin.Bottom - margin.Top);
// Get the size of canvas
Size size = new Size(obj.ActualWidth, obj.ActualHeight);
// force control to Update
obj.Measure(size);
obj.Arrange(
new Rect(size));
RenderTargetBitmap bmp = new RenderTargetBitmap(
(
int)obj.ActualWidth, (int)obj.ActualHeight, 96, 96, PixelFormats.Pbgra32);
bmp.Render(obj);
// return values as they were before
obj.LayoutTransform = transform;
obj.Margin = margin;
return bmp;
}
public void AcceptImage()
{
using (System.IO.MemoryStream outStream = new System.IO.MemoryStream())
{
// Use png encoder for our data
PngBitmapEncoder encoder = new PngBitmapEncoder();
// push the rendered bitmap to it
encoder.Frames.Add(BitmapFrame.Create(ToImageSource(canvas1)));
// save the data to the stream
encoder.Save(outStream);
outStream.Position = 0;
// Do something with the MemoryStream here--save it to file or pass it back into system.
}

}

}

}

No comments:

Post a Comment