我正在开发一个可以使用鼠标或手写笔通过触摸屏进行输入的应用程序。发现这<InkCanvas>
对我来说非常有用,但 Windows Store 应用程序项目不识别/支持<InkCanvas>
标签。
有没有遇到过类似的需求和场景。任何建议。
当然,其中之一是,但它不如灵活<InkCanvas>
我正在开发一个可以使用鼠标或手写笔通过触摸屏进行输入的应用程序。发现这<InkCanvas>
对我来说非常有用,但 Windows Store 应用程序项目不识别/支持<InkCanvas>
标签。
有没有遇到过类似的需求和场景。任何建议。
当然,其中之一是,但它不如灵活<InkCanvas>
Use this control in xaml like: <ctrl:InkCanvas x:Name="inkCanvas" />
不要忘记引用“ctrl”,例如:xmlns:ctrl="using:MyAppNamespace"
using System;
using System.Collections.Generic;
using Windows.Devices.Input;
using Windows.Foundation;
using Windows.UI;
using Windows.UI.Input;
using Windows.UI.Input.Inking;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Input;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Shapes;
using System.Linq;
using System.Threading.Tasks;
using Windows.Storage;
using Windows.Storage.Streams;
using Windows.UI.Xaml.Media.Imaging;
using System.Runtime.InteropServices.WindowsRuntime;
namespace MyAppNamespace
{
public class InkCanvas : Canvas
{
InkManager m_InkManager = new Windows.UI.Input.Inking.InkManager();
private uint m_PenId;
private uint _touchID;
private Point _previousContactPt;
private Point currentContactPt;
private double x1;
private double y1;
private double x2;
private double y2;
private Color m_CurrentDrawingColor = Colors.Black;
private double m_CurrentDrawingSize = 4;
public List<InkStroke> Strokes { get { return m_InkManager.GetStrokes().ToList(); } }
public InkCanvas()
{
m_InkManager.Mode = Windows.UI.Input.Inking.InkManipulationMode.Inking;
SetDefaults(m_CurrentDrawingSize, m_CurrentDrawingColor);
this.PointerPressed += new PointerEventHandler(OnCanvasPointerPressed);
this.PointerMoved += new PointerEventHandler(OnCanvasPointerMoved);
this.PointerReleased += new PointerEventHandler(OnCanvasPointerReleased);
this.PointerExited += new PointerEventHandler(OnCanvasPointerReleased);
}
public void Clear()
{
this.Children.Clear();
var strokes = m_InkManager.GetStrokes();
for (int i = 0; i < strokes.Count; i++)
strokes[i].Selected = true;
m_InkManager.DeleteSelected();
}
public async Task<byte[]> GetBytes()
{
var bytes = new byte[0];
if (Strokes.Count > 0)
{
var tempFile = await ApplicationData.Current.LocalFolder.CreateFileAsync(Guid.NewGuid().ToString() + ".jpg");
var writeStream = await tempFile.OpenAsync(FileAccessMode.ReadWrite);
await m_InkManager.SaveAsync(writeStream);
await writeStream.FlushAsync();
var reader = new DataReader(writeStream.GetInputStreamAt(0));
bytes = new byte[writeStream.Size];
await reader.LoadAsync((uint)writeStream.Size);
reader.ReadBytes(bytes);
reader.DetachStream();
await tempFile.DeleteAsync();
}
return bytes;
}
public async Task<BitmapImage> GetBitmapImage()
{
var bitmapImage = new BitmapImage();
var bytes = await GetBytes();
if (bytes.Length > 0)
{
using (var stream = new InMemoryRandomAccessStream())
{
// For AsBuffer manually add [ using System.Runtime.InteropServices.WindowsRuntime ];
await stream.WriteAsync(bytes.AsBuffer());
stream.Seek(0);
bitmapImage.SetSource(stream);
}
}
return bitmapImage;
}
#region Pointer Event Handlers
public void OnCanvasPointerReleased(object sender, PointerRoutedEventArgs e)
{
if (e.Pointer.PointerId == m_PenId)
{
Windows.UI.Input.PointerPoint pt = e.GetCurrentPoint(this);
// Pass the pointer information to the InkManager.
m_InkManager.ProcessPointerUp(pt);
}
else if (e.Pointer.PointerId == _touchID)
{
// Process touch input
}
_touchID = 0;
m_PenId = 0;
e.Handled = true;
}
private void OnCanvasPointerMoved(object sender, PointerRoutedEventArgs e)
{
if (e.Pointer.PointerId == m_PenId)
{
PointerPoint pt = e.GetCurrentPoint(this);
// Render a red line on the canvas as the pointer moves.
// Distance() is an application-defined function that tests
// whether the pointer has moved far enough to justify
// drawing a new line.
currentContactPt = pt.Position;
x1 = _previousContactPt.X;
y1 = _previousContactPt.Y;
x2 = currentContactPt.X;
y2 = currentContactPt.Y;
var color = m_CurrentDrawingColor;
var size = m_CurrentDrawingSize;
if (Distance(x1, y1, x2, y2) > 2.0)
{
Line line = new Line()
{
X1 = x1,
Y1 = y1,
X2 = x2,
Y2 = y2,
StrokeThickness = size,
Stroke = new SolidColorBrush(color)
};
_previousContactPt = currentContactPt;
// Draw the line on the canvas by adding the Line object as
// a child of the Canvas object.
this.Children.Add(line);
}
// Pass the pointer information to the InkManager.
m_InkManager.ProcessPointerUpdate(pt);
}
else if (e.Pointer.PointerId == _touchID)
{
// Process touch input
}
}
private double Distance(double x1, double y1, double x2, double y2)
{
double d = 0;
d = Math.Sqrt(Math.Pow((x2 - x1), 2) + Math.Pow((y2 - y1), 2));
return d;
}
public void OnCanvasPointerPressed(object sender, PointerRoutedEventArgs e)
{
// Get information about the pointer location.
PointerPoint pt = e.GetCurrentPoint(this);
_previousContactPt = pt.Position;
// Accept input only from a pen or mouse with the left button pressed.
PointerDeviceType pointerDevType = e.Pointer.PointerDeviceType;
if (pointerDevType == PointerDeviceType.Pen ||
pointerDevType == PointerDeviceType.Mouse &&
pt.Properties.IsLeftButtonPressed)
{
// Pass the pointer information to the InkManager.
m_InkManager.ProcessPointerDown(pt);
m_PenId = pt.PointerId;
e.Handled = true;
}
else if (pointerDevType == PointerDeviceType.Touch)
{
// Process touch input
}
}
#endregion
#region Mode Functions
// Change the color and width in the default (used for new strokes) to the values
// currently set in the current context.
private void SetDefaults(double strokeSize, Color color)
{
var newDrawingAttributes = new InkDrawingAttributes();
newDrawingAttributes.Size = new Size(strokeSize, strokeSize);
newDrawingAttributes.Color = color;
newDrawingAttributes.FitToCurve = true;
m_InkManager.SetDefaultDrawingAttributes(newDrawingAttributes);
this.Background = new SolidColorBrush(Colors.White);
}
#endregion
}
}
您使用InkManager
WinRT 中的类而不是 WPF 的InkCanvas
. 我认为您可能需要使用自己的Canvas
控件和一些Shapes
(Polyline
?)并自己处理 Pointer~ 事件,但我自己没有做过,所以我不能肯定地说。