//此文件来自 SharpDevelop using System; using System.IO; using System.Printing; using System.Drawing.Printing; using System.Windows; using System.Windows.Media; using System.Windows.Documents; namespace LunarSF.SHomeWorkshop.LunarMarkdownEditor { /// <summary> /// Represents the DocumentPaginatorWrapper adding headers and footers to the document. /// </summary> public class DocumentPaginatorWrapper : DocumentPaginator { string m_Title; Margins m_Margins; Size m_PageSize; DocumentPaginator m_Paginator; Typeface m_Typeface; #region Properties /// <summary> /// Sets the header title for each document page. /// </summary> public string Title { set { m_Title = value; } } public override bool IsPageCountValid { get { return m_Paginator.IsPageCountValid; } } public override int PageCount { get { return m_Paginator.PageCount; } } public override Size PageSize { get { return m_Paginator.PageSize; } set { m_Paginator.PageSize = value; } } public override IDocumentPaginatorSource Source { get { return m_Paginator.Source; } } #endregion public DocumentPaginatorWrapper(DocumentPaginator paginator, PageSettings pageSettings, PrintTicket printTicket, FontFamily headerFooterfontFamily) { m_Margins = ConvertMarginsToPx(pageSettings.Margins); if (pageSettings.Landscape) m_PageSize = new Size((int)printTicket.PageMediaSize.Height, (int)printTicket.PageMediaSize.Width); else m_PageSize = new Size((int)printTicket.PageMediaSize.Width, (int)printTicket.PageMediaSize.Height); m_Paginator = paginator; m_Paginator.PageSize = new Size(m_PageSize.Width - m_Margins.Left - m_Margins.Right, m_PageSize.Height - m_Margins.Top - m_Margins.Bottom); m_Typeface = new Typeface(headerFooterfontFamily, FontStyles.Normal, FontWeights.Normal, FontStretches.Normal); } Rect Move(Rect rect) { if (rect.IsEmpty) { return rect; } else { return new Rect(rect.Left + m_Margins.Left, rect.Top + m_Margins.Top, rect.Width, rect.Height); } } public override DocumentPage GetPage(int pageNumber) { DocumentPage page = m_Paginator.GetPage(pageNumber); ContainerVisual newpage = new ContainerVisual(); // // Header // DrawingVisual header = new DrawingVisual(); using (DrawingContext ctx = header.RenderOpen()) { DrawPath(ctx, m_Margins.Top - 20, m_Title, TextAlignment.Left); DrawText(ctx, m_Margins.Top - 20, String.Format("{0}", DateTime.Now), TextAlignment.Right); DrawLine(ctx, m_Margins.Top - 5, 0.5); } // // Footer // DrawingVisual footer = new DrawingVisual(); using (DrawingContext ctx = footer.RenderOpen()) { DrawText(ctx, m_PageSize.Height - m_Margins.Bottom + 5, "-" + (pageNumber + 1) + "-", TextAlignment.Center); DrawLine(ctx, m_PageSize.Height - m_Margins.Bottom + 5, 0.5); } ContainerVisual pageVisual = new ContainerVisual(); pageVisual.Children.Add(page.Visual); newpage.Children.Add(header); newpage.Children.Add(pageVisual); newpage.Children.Add(footer); return new DocumentPage(newpage, m_PageSize, Move(page.BleedBox), Move(page.ContentBox)); } /// <summary> /// Draws a text at specified y-postion with specified text alignment. /// </summary> void DrawText(DrawingContext ctx, double yPos, string text, TextAlignment alignment) { if (string.IsNullOrEmpty(text)) return; if (m_Typeface == null) { m_Typeface = new Typeface("Times New Roman"); } FormattedText formattedText = new FormattedText(text, System.Globalization.CultureInfo.CurrentCulture, FlowDirection.LeftToRight, m_Typeface, 12, Brushes.Black); if (alignment == TextAlignment.Left) { formattedText.TextAlignment = TextAlignment.Left; formattedText.MaxTextWidth = m_PageSize.Width * 2 / 3; formattedText.MaxTextHeight = 16; formattedText.Trimming = TextTrimming.WordEllipsis; ctx.DrawText(formattedText, new Point(m_Margins.Left, yPos)); } else if (alignment == TextAlignment.Right) { formattedText.TextAlignment = TextAlignment.Right; ctx.DrawText(formattedText, new Point(m_PageSize.Width - m_Margins.Right, yPos)); } else if (alignment == TextAlignment.Center) { formattedText.TextAlignment = TextAlignment.Center; ctx.DrawText(formattedText, new Point(m_PageSize.Width / 2, yPos)); } } /// <summary> /// Draws a path as document title. /// </summary> void DrawPath(DrawingContext ctx, double yPos, string text, TextAlignment alignment) { if (string.IsNullOrEmpty(text)) return; if (!File.Exists(text)) { DrawText(ctx, yPos, text, alignment); return; } if (m_Typeface == null) { m_Typeface = new Typeface("Times New Roman"); } double textWidth; FormattedText formattedText = new FormattedText(text, System.Globalization.CultureInfo.CurrentCulture, FlowDirection.LeftToRight, m_Typeface, 12, Brushes.Black); textWidth = formattedText.Width; double maxTextLength = m_PageSize.Width * 2 / 3; if (textWidth < maxTextLength) { ctx.DrawText(formattedText, new Point(m_Margins.Left, yPos)); return; } // // if someone has a more clever solution // to do WordEllipsis trimming for paths, please shout // string path = Path.GetDirectoryName(text); string fileName = "\\" + Path.GetFileName(text); // get the length of the trimmed file name formattedText = new FormattedText(fileName, System.Globalization.CultureInfo.CurrentCulture, FlowDirection.LeftToRight, m_Typeface, 12, Brushes.Black); formattedText.MaxTextWidth = maxTextLength - 100; formattedText.MaxTextHeight = 16; formattedText.Trimming = TextTrimming.WordEllipsis; textWidth = formattedText.Width; // draw the path formattedText = new FormattedText(path, System.Globalization.CultureInfo.CurrentCulture, FlowDirection.LeftToRight, m_Typeface, 12, Brushes.Black); formattedText.MaxTextWidth = maxTextLength - textWidth; formattedText.MaxTextHeight = 16; formattedText.Trimming = TextTrimming.WordEllipsis; ctx.DrawText(formattedText, new Point(m_Margins.Left, yPos)); textWidth = formattedText.Width; // draw the file name formattedText = new FormattedText(fileName, System.Globalization.CultureInfo.CurrentCulture, FlowDirection.LeftToRight, m_Typeface, 12, Brushes.Black); formattedText.MaxTextWidth = maxTextLength - textWidth; formattedText.MaxTextHeight = 16; formattedText.Trimming = TextTrimming.WordEllipsis; ctx.DrawText(formattedText, new Point(m_Margins.Left + textWidth, yPos)); } /// <summary> /// Draws a line form left to right margin at specified y-postion. /// </summary> void DrawLine(DrawingContext ctx, double yPos, double thickness) { ctx.DrawLine(new Pen(new SolidColorBrush(Colors.Black), thickness), new Point(m_Margins.Left, yPos), new Point(m_PageSize.Width - m_Margins.Right, yPos)); } /// <summary> /// Converts specified Margins (hundredths of an inch) to pixel margin (px). /// </summary> Margins ConvertMarginsToPx(Margins margins) { margins.Left = ConvertToPx(margins.Left); margins.Top = ConvertToPx(margins.Top); margins.Right = ConvertToPx(margins.Right); margins.Bottom = ConvertToPx(margins.Bottom); return margins; } /// <summary> /// Converts specified inch (hundredths of an inch) to pixels (px). /// </summary> int ConvertToPx(double inch) { return (int)(inch * 0.96); } } }