• WPF杂难解 RichTextBox粘贴图片地址处理,并保存的问题


    引:

    这个系列将会记录工作中遇到的一些疑难问题,并贴出自己的解决方案。因为本人水平仍在入门级别徘徊,如有更好方案,望高手指点。

    问题来源:

    公司在做的项目中,需要用到文本编辑器,实现粘贴文本、图片等功能,类似网页中的FCKEditor。处理图片时,我们需要缩略显示图片,并把图片发送到服务器。

    问题在这里,我们以xaml读取RichTextBox的内容时,发现其图片标签的地址极其怪异,如下:

    <FlowDocument PagePadding="5,0,5,0" AllowDrop="True" NumberSubstitution.CultureSource="User" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
        <BlockUIContainer TextAlignment="Justify">
            <Image Width="553" Height="415">
                <Image.Source>
                    <BitmapImage BaseUri="pack://payload:,,wpf1,/Xaml/Document.xaml" UriSource="./Image1.bmp" CacheOption="OnLoad" />
                </Image.Source>
            </Image>
        </BlockUIContainer>

    </FlowDocument> 

     其中有BaseUri="pack://payload:,,wpf1,/Xaml/Document.xaml" UriSource="./Image1.bmp"猜测图片是被保存在某个临时文件夹中 ,但是无法定位。

    解决思路一:

     既然图片是粘贴进来的,我们应该能在RichTextBox的粘贴命令时即对图片进行处理。于是使用了WPF的ClipBoard,把图片保存到本地后,再插入RichTextBox中。大致代码如下:

    private void PaseHandlers(object sender, ExecutedRoutedEventArgs args) 

    {
        if (Clipboard.ContainsData(DataFormats.Bitmap))
        {
            BitmapSource bitmap = Clipboard.GetImage();
            System.Drawing.Bitmap b = BitmapToBitmap(bitmap, ".bmp");
            string path = Constants.SYSTEM.TEMP_DATA_PATH + Guid.NewGuid().ToString() + ".bmp";
            b.Save(path, System.Drawing.Imaging.ImageFormat.Jpeg);
            b.Dispose();
            //添加到控件中
            InsertImage(path, path, this.Document);
            args.Handled = true;
            return;
        }
    }

     但这个方案的问题在于,如果我以图文混排方式粘贴的话,文本就会丢失。

    有人会说,那你用Clipboard.GetText(); 拿文本嘛。我当然试了,但是这样会把图片和文本分开,即图片和文字的位置关系没办法处理。

    解决思路二:

    刚刚开始考虑这个问题时想到过RTF,又惮于RTF格式的复杂。 

     但是RTF给RichTextBox赋值显示又是好的,所以想到一个取巧的办法,先在内存中实例化一个RichTextBox,将ClipBord内的RTF格式数据赋给它,再对它的Document进行解析。

     //取出剪切板内数据 

    IDataObject iData = Clipboard.GetDataObject();

    //内存内实例化一个RichTextBox
    System.Windows.Controls.RichTextBox rtb = new System.Windows.Controls.RichTextBox();
    //rtf格式
    if (iData.GetDataPresent(DataFormats.Rtf))
    {
        var rtf = iData.GetData(DataFormats.Rtf);
        //将rtf载入内存内的RichTextBox
        TextRange textRange = new TextRange(rtb.Document.ContentStart, rtb.Document.ContentEnd);
        using (MemoryStream rtfMemoryStream = new MemoryStream())
        {
            using (StreamWriter rtfStreamWriter = new StreamWriter(rtfMemoryStream))
            {
                rtfStreamWriter.Write(rtf);
                rtfStreamWriter.Flush();
                rtfMemoryStream.Seek(0, SeekOrigin.Begin);
                //Load the MemoryStream into TextRange ranging from start to end of RichTextBox.
                textRange.Load(rtfMemoryStream, DataFormats.Rtf);
            }
        }
    }

    这样就又可以利用 System.Windows.Markup.XamlWriter.Save();将其保存为xaml处理。起码可以分析它的节点了。

     这里我们又回到了问题来源时列出的文件格式,在对图片处理时用到了一个转换:

    BitmapImage bitmap = new BitmapImage();
    bitmap.BeginInit();
    bitmap.BaseUri = new Uri(bmpNode.Attributes["BaseUri"].Value);
    bitmap.UriSource = new Uri(bmpNode.Attributes["UriSource"].Value, UriKind.Relative);
    bitmap.EndInit();
    BitmapSource bsrc = (BitmapSource)bitmap;
    PngBitmapEncoder png = new PngBitmapEncoder();
    png.Frames.Add(BitmapFrame.Create(bsrc));
    imgName = Constants.SYSTEM.TEMP_DATA_PATH + "\\" + bmpNode.Attributes["UriSource"].Value.Replace("./""");
    if (File.Exists(imgName))
    {
        File.Delete(imgName);
    }
    using (Stream stream = File.Create(imgName))
    {
        png.Save(stream);
    }

    这样图片即是可控的,很方便地对它进行处理。

    但是这个方法处理来,性能损耗很大,希望高手能给出更好的解决方案。 

  • 相关阅读:
    web开发中禁止因为网速慢导致重复提交数据
    margin四个元素的顺序
    js阻止提交表单(post)
    js中DOM集合的动态特性
    js正则表达式中=s.g表示什么意思
    js去掉字符串前后空格的五种方法
    电脑结构和CPU、内存、硬盘三者之间的关系
    mysql——查询练习
    python基础知识14——I/O阻塞非阻塞,同步异步
    Redis主从数据库的安装及主从配置
  • 原文地址:https://www.cnblogs.com/shen6041/p/2385888.html
Copyright © 2020-2023  润新知