您的位置:首页 > 其它

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

2012-03-08 21:53 176 查看
引:

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

问题来源:

公司在做的项目中,需要用到文本编辑器,实现粘贴文本、图片等功能,类似网页中的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);

}

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

但是这个方法处理来,性能损耗很大,希望高手能给出更好的解决方案。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: