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

這樣圖片即是可控的,很方便地對它進行處理。

但是這個方法處理來,性能損耗很大,希望高手能給出更好的解決方案。 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM