这种应用现在已经比较常见了,比如论坛回贴中的手写功能 ,IM聊天中的个性化手写文字,个性签名等,在Silverlight中要实现该功能其实非常简单,只要一个InkPresenter控件即可
使用要点:
1.要合理设置裁剪区,否则手写时可能笔划会写到你不希望出现的地方.
2.处理好MouseLeftButtonDown,MouseMove,LostMouseCapture这三个事件.
演示代码:
前端Xaml部分:
by 菩提树下的杨过 http://yjmyzz.cnblogs.com/
<UserControl x:Class="InkPresenterTest.Page"
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"
mc:Ignorable="d" Background="Black"
>
<RowDefinition Height="25"></RowDefinition>
<RowDefinition Height="30"></RowDefinition>
<RowDefinition></RowDefinition>
<RowDefinition Height="30"></RowDefinition>
<RowDefinition Height="150"></RowDefinition>
</Grid.RowDefinitions>
<TextBlock Text="笔划颜色:" VerticalAlignment="Center"></TextBlock>
<ComboBox x:Name="cboColor" Width="65" VerticalAlignment="Center">
<ComboBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<Rectangle Fill="{Binding Color}" ToolTipService.ToolTip="{Binding Name}" Width="10" Height="10"/>
<TextBlock Text="{Binding Name}" Margin="2,0,0,0" Foreground="{Binding Color}"></TextBlock>
</StackPanel>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
<TextBlock Text="笔划外框颜色:" VerticalAlignment="Center" Margin="10,0,0,0"></TextBlock>
<ComboBox x:Name="cboOutlineColor" Width="65" VerticalAlignment="Center">
<ComboBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<Rectangle Fill="{Binding Color}" ToolTipService.ToolTip="{Binding Name}" Width="10" Height="10"/>
<TextBlock Text="{Binding Name}" Margin="2,0,0,0" Foreground="{Binding Color}"></TextBlock>
</StackPanel>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
<TextBlock Text="笔划宽度:" Margin="10,0,0,0" VerticalAlignment="Center"></TextBlock>
<ComboBox x:Name="cboWidth" Width="60" VerticalAlignment="Center" Height="20">
<ComboBox.ItemTemplate>
<DataTemplate>
<Rectangle Fill="Black" Width="40" Height="{Binding Size}"/>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
<TextBlock Text="笔划高度:" Margin="10,0,0,0" VerticalAlignment="Center"></TextBlock>
<ComboBox x:Name="cboHeight" Width="60" VerticalAlignment="Center" Height="20">
<ComboBox.ItemTemplate>
<DataTemplate>
<Rectangle Fill="Black" Width="40" Height="{Binding Size}"/>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
<TextBlock Text="透明度:" Margin="10,0,0,0" VerticalAlignment="Center"></TextBlock>
<ComboBox x:Name="cboOpactiy" Width="60" VerticalAlignment="Center" SelectionChanged="cboOpactiy_SelectionChanged">
<ComboBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Value}" Opacity="{Binding Value}" ></TextBlock>
</StackPanel>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
</StackPanel>
<Rectangle x:Name="rectBg" Grid.Row="2" Width="650" Height="370" Fill="#FFECD85C" Margin="0" StrokeThickness="0"></Rectangle>
<Image Source="image/background.png" Stretch="UniformToFill" x:Name="imgBg"></Image>
<InkPresenter x:Name="ink" Height="370" Width="650" Grid.Row="2"
Background="Transparent" Opacity="1"
MouseLeftButtonDown="OnMouseLeftButtonDown"
MouseMove="OnMouseMove"
LostMouseCapture="OnLostMouseCapture" Margin="0"
>
<InkPresenter.Clip>
<RectangleGeometry Rect="0,0,650,370"></RectangleGeometry>
</InkPresenter.Clip>
<TextBlock Text="by 菩提树下的杨过" MouseLeftButtonDown="TextBlock_MouseLeftButtonDown" Cursor="Hand" Canvas.Left="5" Canvas.Top="5" Foreground="LightGray"></TextBlock>
</Canvas>
<Button x:Name="btnToogleBg" HorizontalAlignment="Center" Width="80" Content="隐藏背景图" VerticalAlignment="Center" Click="btnToogleBg_Click"/>
<Button x:Name="btnToogleBgRect" HorizontalAlignment="Center" Width="80" Content="隐藏背景色" VerticalAlignment="Center" Click="btnToogleBgRect_Click" Margin="10,0,0,0"/>
<Button x:Name="btnSave" HorizontalAlignment="Center" Width="80" Content="保存图片" VerticalAlignment="Center" Margin="10,0,0,0" Click="btnSave_Click"/>
<Button x:Name="btnSaveLocal" HorizontalAlignment="Center" Width="90" Content="保存图片到本地" VerticalAlignment="Center" Margin="10,0,0,0" Click="btnSaveLocal_Click" />
<Button x:Name="btnClear" HorizontalAlignment="Center" Width="80" Content="清空画版" VerticalAlignment="Center" Margin="10,0,0,0" Click="btnClear_Click"/>
<Button x:Name="btnClearSave" HorizontalAlignment="Center" Width="80" Content="清空保存区" VerticalAlignment="Center" Margin="10,0,0,0" Click="btnClearSave_Click"/>
</StackPanel>
<StackPanel x:Name="thumbs" Orientation="Horizontal"/>
</ScrollViewer>
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"
mc:Ignorable="d" Background="Black"
>
<Grid Background="#FF0BB5A3" Width="650" Height="615">
<Grid.RowDefinitions>
<RowDefinition Height="25"></RowDefinition>
<RowDefinition Height="30"></RowDefinition>
<RowDefinition></RowDefinition>
<RowDefinition Height="30"></RowDefinition>
<RowDefinition Height="150"></RowDefinition>
</Grid.RowDefinitions>
<TextBlock x:Name="txtTitle" Text="InkPresenter 演 示" FontWeight="Bold" Grid.Row="0" HorizontalAlignment="Center" Height="20" VerticalAlignment="Center" Foreground="White" />
<StackPanel x:Name="spToolBar" Grid.Row="1" Orientation="Horizontal" HorizontalAlignment="Center" Height="25" VerticalAlignment="Center">
<TextBlock Text="笔划颜色:" VerticalAlignment="Center"></TextBlock>
<ComboBox x:Name="cboColor" Width="65" VerticalAlignment="Center">
<ComboBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<Rectangle Fill="{Binding Color}" ToolTipService.ToolTip="{Binding Name}" Width="10" Height="10"/>
<TextBlock Text="{Binding Name}" Margin="2,0,0,0" Foreground="{Binding Color}"></TextBlock>
</StackPanel>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
<TextBlock Text="笔划外框颜色:" VerticalAlignment="Center" Margin="10,0,0,0"></TextBlock>
<ComboBox x:Name="cboOutlineColor" Width="65" VerticalAlignment="Center">
<ComboBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<Rectangle Fill="{Binding Color}" ToolTipService.ToolTip="{Binding Name}" Width="10" Height="10"/>
<TextBlock Text="{Binding Name}" Margin="2,0,0,0" Foreground="{Binding Color}"></TextBlock>
</StackPanel>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
<TextBlock Text="笔划宽度:" Margin="10,0,0,0" VerticalAlignment="Center"></TextBlock>
<ComboBox x:Name="cboWidth" Width="60" VerticalAlignment="Center" Height="20">
<ComboBox.ItemTemplate>
<DataTemplate>
<Rectangle Fill="Black" Width="40" Height="{Binding Size}"/>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
<TextBlock Text="笔划高度:" Margin="10,0,0,0" VerticalAlignment="Center"></TextBlock>
<ComboBox x:Name="cboHeight" Width="60" VerticalAlignment="Center" Height="20">
<ComboBox.ItemTemplate>
<DataTemplate>
<Rectangle Fill="Black" Width="40" Height="{Binding Size}"/>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
<TextBlock Text="透明度:" Margin="10,0,0,0" VerticalAlignment="Center"></TextBlock>
<ComboBox x:Name="cboOpactiy" Width="60" VerticalAlignment="Center" SelectionChanged="cboOpactiy_SelectionChanged">
<ComboBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Value}" Opacity="{Binding Value}" ></TextBlock>
</StackPanel>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
</StackPanel>
<Canvas x:Name="inkC" Grid.Row="2" Height="370">
<Rectangle x:Name="rectBg" Grid.Row="2" Width="650" Height="370" Fill="#FFECD85C" Margin="0" StrokeThickness="0"></Rectangle>
<Image Source="image/background.png" Stretch="UniformToFill" x:Name="imgBg"></Image>
<InkPresenter x:Name="ink" Height="370" Width="650" Grid.Row="2"
Background="Transparent" Opacity="1"
MouseLeftButtonDown="OnMouseLeftButtonDown"
MouseMove="OnMouseMove"
LostMouseCapture="OnLostMouseCapture" Margin="0"
>
<InkPresenter.Clip>
<RectangleGeometry Rect="0,0,650,370"></RectangleGeometry>
</InkPresenter.Clip>
</InkPresenter>
<TextBlock Text="by 菩提树下的杨过" MouseLeftButtonDown="TextBlock_MouseLeftButtonDown" Cursor="Hand" Canvas.Left="5" Canvas.Top="5" Foreground="LightGray"></TextBlock>
</Canvas>
<StackPanel x:Name="spBtn" Grid.Row="3" Height="30" Margin="0" Orientation="Horizontal" VerticalAlignment="Center" HorizontalAlignment="Center">
<Button x:Name="btnToogleBg" HorizontalAlignment="Center" Width="80" Content="隐藏背景图" VerticalAlignment="Center" Click="btnToogleBg_Click"/>
<Button x:Name="btnToogleBgRect" HorizontalAlignment="Center" Width="80" Content="隐藏背景色" VerticalAlignment="Center" Click="btnToogleBgRect_Click" Margin="10,0,0,0"/>
<Button x:Name="btnSave" HorizontalAlignment="Center" Width="80" Content="保存图片" VerticalAlignment="Center" Margin="10,0,0,0" Click="btnSave_Click"/>
<Button x:Name="btnSaveLocal" HorizontalAlignment="Center" Width="90" Content="保存图片到本地" VerticalAlignment="Center" Margin="10,0,0,0" Click="btnSaveLocal_Click" />
<Button x:Name="btnClear" HorizontalAlignment="Center" Width="80" Content="清空画版" VerticalAlignment="Center" Margin="10,0,0,0" Click="btnClear_Click"/>
<Button x:Name="btnClearSave" HorizontalAlignment="Center" Width="80" Content="清空保存区" VerticalAlignment="Center" Margin="10,0,0,0" Click="btnClearSave_Click"/>
</StackPanel>
<ScrollViewer x:Name="ScreenshotViewer" Margin="0" Grid.Row="4" Background="#FFFFFF99" HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Hidden">
<StackPanel x:Name="thumbs" Orientation="Horizontal"/>
</ScrollViewer>
</Grid> </UserControl>
后端代码:
by 菩提树下的杨过 http://yjmyzz.cnblogs.com/
using System.Windows;
using System.Windows.Controls;
using System.Collections.Generic;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Shapes;
using System.Windows.Browser;
using System.Windows.Media.Imaging;
using System.IO;
using FluxJpeg.Core; namespace InkPresenterTest
{
public partial class Page : UserControl
{
Stroke _drawStroke;
List<SizeData> lstSizeData;
List<OpacityData> lstOpacityData;
{
InitializeComponent();
lstFillColor = new List<FillColor>() {
new FillColor(){ Color = new SolidColorBrush(Colors.Black), Name="黑色"},
new FillColor(){ Color = new SolidColorBrush(Colors.Red), Name="红色"},
new FillColor(){ Color = new SolidColorBrush(Colors.Blue), Name="蓝色"},
new FillColor(){ Color = new SolidColorBrush(Colors.Green),Name="绿色"},
new FillColor(){ Color = new SolidColorBrush(Colors.Magenta), Name="洋红"},
new FillColor(){ Color = new SolidColorBrush(Colors.Orange), Name="橙色"},
};
{
new SizeData(){ Size=1.0},
new SizeData(){ Size=3.0},
new SizeData(){ Size=5.0},
new SizeData(){ Size=7.0},
new SizeData(){ Size=9.0},
new SizeData(){ Size=11.0},
new SizeData(){ Size=13.0},
new SizeData(){ Size=15.0}
};
new OpacityData(){ Value=0.1},
new OpacityData(){ Value=0.2},
new OpacityData(){ Value=0.3},
new OpacityData(){ Value=0.4},
new OpacityData(){ Value=0.5},
new OpacityData(){ Value=0.6},
new OpacityData(){ Value=0.7},
new OpacityData(){ Value=0.8},
new OpacityData(){ Value=0.9},
new OpacityData(){ Value=1.0}
};
}
{
this.cboColor.ItemsSource = lstFillColor;
this.cboColor.SelectedIndex = 0;
this.cboOutlineColor.SelectedIndex = 0;
this.cboWidth.SelectedIndex = 0;
this.cboHeight.SelectedIndex = 0;
this.cboOpactiy.SelectedIndex = 5;
}
{
ink.CaptureMouse();
StylusPointCollection MyStylusPointCollection = new StylusPointCollection();
MyStylusPointCollection.Add(e.StylusDevice.GetStylusPoints(ink));
_drawStroke = new Stroke(MyStylusPointCollection);
_drawStroke.DrawingAttributes.Color = (cboColor.SelectedItem as FillColor).Color.Color;
_drawStroke.DrawingAttributes.OutlineColor = (this.cboOutlineColor.SelectedItem as FillColor).Color.Color;
_drawStroke.DrawingAttributes.Width = (this.cboWidth.SelectedItem as SizeData).Size;
_drawStroke.DrawingAttributes.Height = (this.cboHeight.SelectedItem as SizeData).Size;
//_drawStroke.SetValue(OpacityProperty, (this.cboOpactiy.SelectedItem as OpacityData).Value);
ink.Strokes.Add(_drawStroke);
ink.Opacity = (cboOpactiy.SelectedItem as OpacityData).Value;
}
{
if (_drawStroke != null)
{
_drawStroke.StylusPoints.Add(e.StylusDevice.GetStylusPoints(ink));
}
}
{
_drawStroke = null;
}
{
ink.Strokes.Clear();
}
{
if (_isLoaded)
{
ink.Opacity = (cboOpactiy.SelectedItem as OpacityData).Value;
}
}
{
Button btn = (sender as Button);
if (btn.Content.ToString() == "隐藏背景图")
{
imgBg.Visibility = Visibility.Collapsed;
btn.Content = "显示背景图";
}
else
{
imgBg.Visibility = Visibility.Visible;
btn.Content = "隐藏背景图";
}
}
{
Button btn = (sender as Button);
if (btn.Content.ToString() == "隐藏背景色")
{
this.rectBg.Visibility = Visibility.Collapsed;
btn.Content = "显示背景色";
}
else
{
rectBg.Visibility = Visibility.Visible;
btn.Content = "隐藏背景色";
}
}
{
HtmlPage.Window.Navigate(new System.Uri("http://yjmyzz.cnblogs.com/"), "_blank");
}
{
// 创建一个WriteableBitmap并且把需要呈现位图的元素赋值给WriteableBitmap
WriteableBitmap wb = new WriteableBitmap(inkC, null);
System.Windows.Controls.Image image = new System.Windows.Controls.Image();
image.Height = 120;
image.Margin = new Thickness(5);
image.Source = wb;
using System.Windows.Controls;
using System.Collections.Generic;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Shapes;
using System.Windows.Browser;
using System.Windows.Media.Imaging;
using System.IO;
using FluxJpeg.Core; namespace InkPresenterTest
{
public partial class Page : UserControl
{
Stroke _drawStroke;
List
<FillColor> lstFillColor;List<SizeData> lstSizeData;
List<OpacityData> lstOpacityData;
bool _isLoaded = false;
public Page()
{
InitializeComponent();
//初始化数据
lstFillColor = new List<FillColor>() {
new FillColor(){ Color = new SolidColorBrush(Colors.Black), Name="黑色"},
new FillColor(){ Color = new SolidColorBrush(Colors.Red), Name="红色"},
new FillColor(){ Color = new SolidColorBrush(Colors.Blue), Name="蓝色"},
new FillColor(){ Color = new SolidColorBrush(Colors.Green),Name="绿色"},
new FillColor(){ Color = new SolidColorBrush(Colors.Magenta), Name="洋红"},
new FillColor(){ Color = new SolidColorBrush(Colors.Orange), Name="橙色"},
};
lstSizeData
= new List<SizeData>(){
new SizeData(){ Size=1.0},
new SizeData(){ Size=3.0},
new SizeData(){ Size=5.0},
new SizeData(){ Size=7.0},
new SizeData(){ Size=9.0},
new SizeData(){ Size=11.0},
new SizeData(){ Size=13.0},
new SizeData(){ Size=15.0}
};
lstOpacityData
= new List<OpacityData>(){new OpacityData(){ Value=0.1},
new OpacityData(){ Value=0.2},
new OpacityData(){ Value=0.3},
new OpacityData(){ Value=0.4},
new OpacityData(){ Value=0.5},
new OpacityData(){ Value=0.6},
new OpacityData(){ Value=0.7},
new OpacityData(){ Value=0.8},
new OpacityData(){ Value=0.9},
new OpacityData(){ Value=1.0}
};
this.Loaded += new RoutedEventHandler(Page_Loaded);
}
void Page_Loaded(object sender, RoutedEventArgs e)
{
this.cboColor.ItemsSource = lstFillColor;
this.cboColor.SelectedIndex = 0;
this.cboOutlineColor.ItemsSource = lstFillColor;
this.cboOutlineColor.SelectedIndex = 0;
this.cboWidth.ItemsSource = lstSizeData;
this.cboWidth.SelectedIndex = 0;
this.cboHeight.ItemsSource = lstSizeData;
this.cboHeight.SelectedIndex = 0;
this.cboOpactiy.ItemsSource = lstOpacityData;
this.cboOpactiy.SelectedIndex = 5;
_isLoaded
= true;}
private void OnMouseLeftButtonDown(object sender, MouseEventArgs e)
{
ink.CaptureMouse();
StylusPointCollection MyStylusPointCollection = new StylusPointCollection();
MyStylusPointCollection.Add(e.StylusDevice.GetStylusPoints(ink));
_drawStroke = new Stroke(MyStylusPointCollection);
_drawStroke.DrawingAttributes.Color = (cboColor.SelectedItem as FillColor).Color.Color;
_drawStroke.DrawingAttributes.OutlineColor = (this.cboOutlineColor.SelectedItem as FillColor).Color.Color;
_drawStroke.DrawingAttributes.Width = (this.cboWidth.SelectedItem as SizeData).Size;
_drawStroke.DrawingAttributes.Height = (this.cboHeight.SelectedItem as SizeData).Size;
//_drawStroke.SetValue(OpacityProperty, (this.cboOpactiy.SelectedItem as OpacityData).Value);
ink.Strokes.Add(_drawStroke);
ink.Opacity = (cboOpactiy.SelectedItem as OpacityData).Value;
}
private void OnMouseMove(object sender, MouseEventArgs e)
{
if (_drawStroke != null)
{
_drawStroke.StylusPoints.Add(e.StylusDevice.GetStylusPoints(ink));
}
}
private void OnLostMouseCapture(object sender, MouseEventArgs e)
{
_drawStroke = null;
}
private void btnClear_Click(object sender, System.Windows.RoutedEventArgs e)
{
ink.Strokes.Clear();
}
private void cboOpactiy_SelectionChanged(object sender, System.Windows.Controls.SelectionChangedEventArgs e)
{
if (_isLoaded)
{
ink.Opacity = (cboOpactiy.SelectedItem as OpacityData).Value;
}
}
private void btnToogleBg_Click(object sender, RoutedEventArgs e)
{
Button btn = (sender as Button);
if (btn.Content.ToString() == "隐藏背景图")
{
imgBg.Visibility = Visibility.Collapsed;
btn.Content = "显示背景图";
}
else
{
imgBg.Visibility = Visibility.Visible;
btn.Content = "隐藏背景图";
}
}
private void btnToogleBgRect_Click(object sender, RoutedEventArgs e)
{
Button btn = (sender as Button);
if (btn.Content.ToString() == "隐藏背景色")
{
this.rectBg.Visibility = Visibility.Collapsed;
btn.Content = "显示背景色";
}
else
{
rectBg.Visibility = Visibility.Visible;
btn.Content = "隐藏背景色";
}
}
private void TextBlock_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
HtmlPage.Window.Navigate(new System.Uri("http://yjmyzz.cnblogs.com/"), "_blank");
}
private void btnSave_Click(object sender, RoutedEventArgs e)
{
// 创建一个WriteableBitmap并且把需要呈现位图的元素赋值给WriteableBitmap
WriteableBitmap wb = new WriteableBitmap(inkC, null);
// 创建一个Image元素来承载位图
System.Windows.Controls.Image image = new System.Windows.Controls.Image();
image.Height = 120;
image.Margin = new Thickness(5);
image.Source = wb;