zoukankan      html  css  js  c++  java
  • silverlight:手写板/涂鸦/墨迹/InkPresenter示例程序


    这种应用现在已经比较常见了,比如论坛回贴中的手写功能 ,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"
        
    >

        
    <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
    <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;

                
    // 将Image元素放入容器控件中
                thumbs.Children.Add(image);

                ScreenshotViewer.ScrollToHorizontalOffset(ScreenshotViewer.ExtentWidth);

            }

            
    private void btnClearSave_Click(object sender, RoutedEventArgs e)
            {
                thumbs.Children.Clear();
            }

            
    private void btnSaveLocal_Click(object sender, RoutedEventArgs e)
            {
                WriteableBitmap wb 
    = new WriteableBitmap(inkC, null);

                
    if (wb != null)
                {
                    SaveFileDialog saveDlg 
    = new SaveFileDialog();
                    saveDlg.Filter 
    = "JPEG Files (*.jpeg)|*.jpeg";
                    saveDlg.DefaultExt 
    = ".jpeg";

                    
    if (saveDlg.ShowDialog().Value)
                    {
                        
    using (Stream fs = saveDlg.OpenFile())
                        {
                            SaveToFile(wb, fs);
                            MessageBox.Show(
    string.Format("文件已经保存至“{0}”",saveDlg.SafeFileName));
                        }
                    }
                }


            }


            
    private void SaveToFile(WriteableBitmap bitmap, Stream fs)
            {
                
    int width = bitmap.PixelWidth;
                
    int height = bitmap.PixelHeight;
                
    int bands = 3;
                
    byte[][,] raster = new byte[bands][,];

                
    for (int i = 0; i < bands; i++)
                {
                    raster[i] 
    = new byte[width, height];
                }

                
    for (int row = 0; row < height; row++)
                {
                    
    for (int column = 0; column < width; column++)
                    {
                        
    int pixel = bitmap.Pixels[width * row + column];
                        raster[
    0][column, row] = (byte)(pixel >> 16);
                        raster[
    1][column, row] = (byte)(pixel >> 8);
                        raster[
    2][column, row] = (byte)pixel;
                    }

                }

                FluxJpeg.Core.ColorModel model 
    = new FluxJpeg.Core.ColorModel { colorspace = FluxJpeg.Core.ColorSpace.RGB };
                FluxJpeg.Core.Image img 
    = new FluxJpeg.Core.Image(model, raster);


                
    //Encode the Image as a JPEG
                MemoryStream stream = new MemoryStream();
                FluxJpeg.Core.Encoder.JpegEncoder encoder 
    = new FluxJpeg.Core.Encoder.JpegEncoder(img, 100, stream);
                encoder.Encode();

                
    //Back to the start
                stream.Seek(0, SeekOrigin.Begin);

                
    //Get teh Bytes and write them to the stream
                byte[] binaryData = new byte[stream.Length];
                
    long bytesRead = stream.Read(binaryData, 0, (int)stream.Length);
                fs.Write(binaryData, 
    0, binaryData.Length);
            }

        }




        
    public class FillColor
        {
            
    public SolidColorBrush Color { setget; }
            
    public string Name { setget; }
        }


        
    public class SizeData
        {
            
    public double Size { setget; }
        }


        
    public class OpacityData
        {
            
    public double Value { setget; }
        }
    }

    源代码下载地址: https://files.cnblogs.com/yjmyzz/InkPresenterTest.rar

    对Flash感兴趣的朋友,做为对比,也可以看下Flash/Flex学习笔记(14):制作涂鸦板 

    转载请注明来自菩提树下的杨过 http://www.cnblogs.com/yjmyzz/archive/2010/01/14/1647636.html

     

    注:里面用到了一个开源的组件FJCore

    作者:菩提树下的杨过
    出处:http://yjmyzz.cnblogs.com
    本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
  • 相关阅读:
    [HDOJ1800]Flying to the Mars
    [HDOJ5058]So easy
    HDU 2819 — Swap 二分匹配
    POJ1236
    Codeforces Round #267 (Div. 2) C. George and Job DP
    codeforces Round #263(div2) D. Appleman and Tree 树形dp
    HDU 4345 Permutation dp
    HDU 4349 Xiao Ming's Hope lucas定理
    HDU 4342History repeat itself 数学
    HDU 4341 分组背包
  • 原文地址:https://www.cnblogs.com/yjmyzz/p/1647636.html
Copyright © 2011-2022 走看看