View Code
using System; using System.Threading; using System.Collections.Generic; using System.IO; using System.Windows.Xps; using System.Windows.Xps.Packaging; using System.IO.Packaging; using System.Windows.Documents; using System.Windows.Documents.Serialization; using System.Windows.Media; using System.Windows; using System.Windows.Controls; // CharacterHit using System.Printing; public partial class ViewXPSDetail : System.Web.UI.Page { public int Pages { get; set; } public bool FinishConvert { get; set; } protected void Page_Load(object sender, EventArgs e) { if (!IsPostBack) { } } protected void ShowXPSBtn_Click(object sender, EventArgs e) { AddBackGroundStart(); } //xps转成jpg private bool SaveXpsPage(string xpsPath) { try { FileConvert fileConvert = new FileConvert(); fileConvert.FileFullPath = xpsPath; Thread thread = new Thread(fileConvert.SaveFileToJpg); thread.SetApartmentState(ApartmentState.STA); thread.Start(); while (!fileConvert.FinishConvert) { Thread.Sleep(100); } return true; } catch (Exception) { Pages = 0; return false; } } public void AddBackGroundStart() { Thread thread = new Thread(AddBackGround); thread.SetApartmentState(ApartmentState.STA); thread.Start(); } public void AddBackGround() { string oldFileName = Server.MapPath("Content/") + FileUpload1.FileName; string newFileName = Server.MapPath("Content/NewHighLight.xps"); if (!File.Exists(oldFileName)) return; // Open original XPS document using (XpsDocument xpsOld = new XpsDocument(oldFileName, FileAccess.ReadWrite)) { FixedDocumentSequence seqOld = xpsOld.GetFixedDocumentSequence(); // Create new XPS document Package container = Package.Open(newFileName, FileMode.Create); XpsDocumentWriter writer = XpsDocument.CreateXpsDocumentWriter(new XpsDocument(container)); // Needed for writing multiple pages SerializerWriterCollator vxpsd = writer.CreateVisualsCollator(); int pageno = 1; if (seqOld == null) return; foreach (DocumentReference r in seqOld.References) { FixedDocument d = r.GetDocument(false); // Walk through each page foreach (PageContent pc in d.Pages) { if (pc == null) continue; FixedPage fixedPage = pc.GetPageRoot(false); if (fixedPage == null) continue; double width = fixedPage.Width; double height = fixedPage.Height; Size sz = new Size(width, height); //// Convert to WPF Visual fixedPage.Measure(sz); fixedPage.Arrange(new Rect(new Point(), sz)); fixedPage.UpdateLayout(); ContainerVisual newpage = new ContainerVisual(); newpage.Children.Add(fixedPage); //// 高亮 var backgroundRect = GetBackgroundRect(fixedPage, txtKeyWord.Text.Trim()); if (backgroundRect != null && backgroundRect.Count > 0) { backgroundRect.ForEach(q => newpage.Children.Add(CreateBackGround(q.X, q.Y, q.Width, q.Height))); } ////水印 newpage.Children.Add(CreateWatermark(width, height, "Takako (" + pageno.ToString() + ")")); ////横向还是纵向 PrintTicket pt = new PrintTicket(); pt.PageMediaSize = new PageMediaSize(width, height); pt.PageOrientation = (width > height) ? PageOrientation.Landscape : PageOrientation.Portrait; vxpsd.Write(newpage, pt); pageno++; } } vxpsd.EndBatchWrite(); container.Close(); } } /// <summary> /// 创建背景色 /// alpha 的值为 0 表示透明,alpha 的值为 255 则表示不透明. /// </summary> /// <param name="x"></param> /// <param name="y"></param> /// <param name="width"></param> /// <param name="height"></param> /// <returns></returns> private Visual CreateBackGround(double x, double y, double width, double height) { DrawingVisual background = new DrawingVisual(); using (DrawingContext dc = background.RenderOpen()) { dc.DrawRectangle(new SolidColorBrush(Color.FromArgb(100, 255, 255, 0)), null, new Rect(x, y, width, height)); } return background; } /// <summary> /// 创建水印 /// </summary> /// <param name="width"></param> /// <param name="height"></param> /// <param name="message"></param> /// <returns></returns> private Visual CreateWatermark(double width, double height, string message) { DrawingVisual watermark = new DrawingVisual(); using (DrawingContext ctx = watermark.RenderOpen()) { FormattedText text = new FormattedText(message, System.Globalization.CultureInfo.CurrentCulture, FlowDirection.LeftToRight, new Typeface("Times New Roman"), 96 * 1.5, new SolidColorBrush(Color.FromScRgb(0.3f, 1f, 0f, 0f)) ); // Rotate transform, keep center { double diag = Math.Sqrt(width * width + height * height); double cX = width / 2; double cY = height / 2; double sin = height / diag; double cos = width / diag; double dx = (cX * (1.0 - cos)) + (cY * sin); double dy = (cY * (1.0 - cos)) - (cX * sin); Transform mat = new MatrixTransform(cos, sin, -sin, cos, dx, dy); ctx.PushTransform(mat); } // Centerlize double x = (width - text.Width) / 2; double y = (height - text.Height) / 2; ctx.DrawText(text, new Point(x, y)); ctx.Pop(); } return watermark; } public List<BackgroundRect> GetBackgroundRect(FixedPage page, string keyword) { List<BackgroundRect> lstBackgroundRect = new List<BackgroundRect>(); foreach (UIElement element in page.Children) { if (element is Glyphs) { lstBackgroundRect.AddRange(GetBackgroundRect((Glyphs)element, keyword)); } if (element is Canvas) { Canvas canvas = (Canvas)element; foreach (UIElement element2 in canvas.Children) { if (element2 is Glyphs) { lstBackgroundRect.AddRange(GetBackgroundRect((Glyphs)element2, keyword)); } } } } return lstBackgroundRect; } public List<BackgroundRect> GetBackgroundRect(Glyphs glyphs, string keyword) { List<BackgroundRect> lstBackgroundRect = new List<BackgroundRect>(); string value = glyphs.UnicodeString; if (value.Contains(keyword)) { GlyphRun grun = glyphs.ToGlyphRun(); //关键字所在的index List<int> indexs = new List<int>(); indexs = GetIndexs(value, keyword); //算出高度 double height = glyphs.FontRenderingEmSize * glyphs.RenderTransform.Value.M22; foreach (int index in indexs) { //算出宽度 double width = 0; for (int i = index; i < keyword.Length + index; i++) { width += grun.AdvanceWidths[i] * glyphs.RenderTransform.Value.M11; } //算出X:X = OriginX + 关键字前面字的宽度 + 偏移量 //用office 2007 Save as XPS or PDF得出的 OriginX非常准确,但用打印机确定生成OriginX 看上去需要往右偏一点,不要问我为什么,莫名其妙它就是偏左!!! double x = glyphs.OriginX * glyphs.RenderTransform.Value.M11; for (int i = 0; i < index; i++) { x += grun.AdvanceWidths[i] * glyphs.RenderTransform.Value.M11; } //算出Y double y = glyphs.OriginY * glyphs.RenderTransform.Value.M22; IChangeRect ICR = new ChangeRect3(); BackgroundRect br = ICR.GetNewRect(new BackgroundRect() { X = x, Y = y, Width = width, Height = height }); lstBackgroundRect.Add(br); } } return lstBackgroundRect; } /// <summary> /// 找出某一个节点中所有关键字的Index /// </summary> /// <param name="value"></param> /// <param name="keyword"></param> /// <returns></returns> public List<int> GetIndexs(string value, string keyword) { //空白的别搜了,浪费时间浪费内容。 if (string.IsNullOrEmpty(keyword)) return new List<int>(); List<int> lstIndex = new List<int>(); int index = value.IndexOf(keyword); if (index != -1) { lstIndex.Add(index); while (index != -1) { index = value.IndexOf(keyword, index + keyword.Length, value.Length - index - keyword.Length); if (index != -1) { lstIndex.Add(index); } } } return lstIndex; } } public class BackgroundRect { public double X { get; set; } public double Y { get; set; } public double Width { get; set; } public double Height { get; set; } } public interface IChangeRect { BackgroundRect GetNewRect(BackgroundRect oldRect); } /// <summary> /// 维持原先的不变 /// </summary> public class ChangeRect1 : IChangeRect { public BackgroundRect GetNewRect(BackgroundRect oldRect) { return oldRect; } } /// <summary> /// X轴往右偏移21.5 /// </summary> public class ChangeRect2 : IChangeRect { public BackgroundRect GetNewRect(BackgroundRect oldRect) { oldRect.X += 21.5; return oldRect; } } /// <summary> /// 用我们自己的驱动,Y轴是有偏移的,需要自定义一下!!! /// </summary> public class ChangeRect3 : IChangeRect { public BackgroundRect GetNewRect(BackgroundRect oldRect) { oldRect.X += 21.5; double size = (int)oldRect.Height; if (size > 0 && size <= 15) { oldRect.Y += 5; } else { oldRect.Y -= (size - 15) * 4 / 5; } return oldRect; } }