引:
這個系列將會記錄工作中遇到的一些疑難問題,並貼出自己的解決方案。因為本人水平仍在入門級別徘徊,如有更好方案,望高手指點。
問題來源:
公司在做的項目中,需要用到文本編輯器,實現粘貼文本、圖片等功能,類似網頁中的FCKEditor。處理圖片時,我們需要縮略顯示圖片,並把圖片發送到服務器。
問題在這里,我們以xaml讀取RichTextBox的內容時,發現其圖片標簽的地址極其怪異,如下:
<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中。大致代碼如下:
{
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);
}
這樣圖片即是可控的,很方便地對它進行處理。
但是這個方法處理來,性能損耗很大,希望高手能給出更好的解決方案。