Beispiel #1
0
        ///<summary>Since Graphics doesn't have a line height property.
        ///Our rendering algorithm focuses on wrapping the text on the same character on each line for all printing options (screen, printer, pdf),
        ///as well as making the text exactly fix vertically within the bounds given in order to properly support sheet vertical growth behavior.
        ///Since all printing options have slightly different implementations within their drivers, the same font when used in each option is slightly
        ///different.  As a result, the printed text width will vary depending on which printing option is used.  We return a rectangle representing the
        ///actual drawn area of the output string for use in special cases such as the TreatmentPlan.Note, which has a border drawn around it always.
        ///</summary>
        public static RectangleF DrawString(Graphics g, string str, Font font, Brush brush, Rectangle bounds, HorizontalAlignment align)
        {
            if (str.Trim() == "")
            {
                return(bounds);               //Nothing to draw.
            }
            StringFormat sf = StringFormat.GenericTypographic;

            //The overload for DrawString that takes a StringFormat will cause the tabs '\t' to be ignored.
            //In order for the tabs to not get ignored, we have to tell StringFormat how many pixels each tab should be.
            //50.0f is the closest to our Fill Sheet Edit preview.
            sf.SetTabStops(0.0f, new float[1] {
                50.0f
            });
            RichTextBox             textbox       = CreateTextBoxForSheetDisplay(str, font, bounds.Width, bounds.Height, align);
            List <RichTextLineInfo> listTextLines = GetTextSheetDisplayLines(textbox);
            float deviceLineHeight = g.MeasureString(str.Replace("\r", "").Replace("\n", ""), font, int.MaxValue, sf).Height;
            float scale            = deviceLineHeight / textbox.Font.Height;//(size when printed)/(size on screen)

            font = new Font(font.FontFamily, font.Size * scale, font.Style);
            float maxLineWidth = 0;

            for (int i = 0; i < listTextLines.Count; i++)
            {
                string line = RichTextLineInfo.GetTextForLine(textbox.Text, listTextLines, i);
                if (line.Trim().Length > 0)
                {
                    float textWidth = g.MeasureString(line, font, int.MaxValue, sf).Width;
                    float x;
                    if (align == HorizontalAlignment.Left)
                    {
                        x = bounds.X + listTextLines[i].Left * scale;
                    }
                    else if (align == HorizontalAlignment.Center)
                    {
                        x = bounds.X + ((bounds.Width - (textWidth * scale)) / 2);
                    }
                    else                      //Right
                    {
                        x = bounds.X + bounds.Width - (textWidth * scale);
                    }
                    float y = bounds.Y + listTextLines[i].Top * scale;
                    g.DrawString(line, font, brush, x, y, sf);
                    maxLineWidth = Math.Max(maxLineWidth, (listTextLines[i].Left * scale) + textWidth);
                }
            }
            textbox.Font.Dispose();            //This font was dynamically created when the textbox was created.
            textbox.Dispose();
            sf.Dispose();
            font.Dispose();
            return(new RectangleF(bounds.X, bounds.Y, maxLineWidth, bounds.Height));
        }
Beispiel #2
0
        ///<summary>The PdfSharp version of Graphics.DrawString().  scaleToPix scales xObjects to pixels.
        ///Our rendering algorithm focuses on wrapping the text on the same character on each line for all printing options (screen, printer, pdf),
        ///as well as making the text exactly fix vertically within the bounds given in order to properly support sheet vertical growth behavior.
        ///Since all printing options have slightly different implementations within their drivers, the same font when used in each option is slightly
        ///different.  As a result, the printed text width will vary depending on which printing option is used.  We return a rectangle representing the
        ///actual drawn area of the output string for use in special cases such as the TreatmentPlan.Note, which has a border drawn around it always.
        ///</summary>
        public static RectangleF DrawStringX(XGraphics xg, string str, XFont xfont, XBrush xbrush, RectangleF bounds, HorizontalAlignment align)
        {
            if (str.Trim() == "")
            {
                return(bounds);               //Nothing to draw.
            }
            XStringFormat sf = XStringFormats.Default;
            //There are two coordinate systems here: pixels (used by us) and points (used by PdfSharp).
            //MeasureString and ALL related measurement functions must use pixels.
            //DrawString is the ONLY function that uses points.
            //pixels:
            FontStyle fontstyle = FontStyle.Regular;

            if (xfont.Style == XFontStyle.Bold)
            {
                fontstyle = FontStyle.Bold;
            }
            //pixels: (except Size is em-size)
            Font                    font             = new Font(xfont.Name, (float)xfont.Size, fontstyle);
            RichTextBox             textbox          = CreateTextBoxForSheetDisplay(str, font, (int)Math.Ceiling(bounds.Width), (int)Math.Ceiling(bounds.Height), align);
            List <RichTextLineInfo> listTextLines    = GetTextSheetDisplayLines(textbox);
            float                   deviceLineHeight = PointsToPixels((float)xg.MeasureString(str.Replace("\r", "").Replace("\n", ""), xfont, sf).Height);
            float                   scale            = deviceLineHeight / textbox.Font.Height;//(size when printed)/(size on screen)

            font.Dispose();
            xfont = new XFont(xfont.Name, xfont.Size * scale, xfont.Style);
            double maxLineWidth = 0;

            for (int i = 0; i < listTextLines.Count; i++)
            {
                string line = RichTextLineInfo.GetTextForLine(textbox.Text, listTextLines, i);
                if (line.Trim().Length > 0)
                {
                    float x = PixelsToPoints(bounds.X + listTextLines[i].Left * scale);
                    //The +11 was arrived at via trial an error. Without this, the first line of each page after the first is halfway on the previous page.
                    float y = PixelsToPoints(bounds.Y + listTextLines[i].Bottom * scale);
                    //There is currently a problem with printing the tab character '\t' when using XStringFormat.
                    //C#'s StringFormat has a method called SetTabStops() which can be used to get the tabs to be drawn (see regular printing above).
                    //We're doing nothing for now because the current complaint is only for printing, not PDF creation.
                    //A workaround is to not use tabs and to instead use separate static text fields that are spaced out as desired.
                    xg.DrawString(line, xfont, xbrush, x, y, sf);
                    maxLineWidth = Math.Max(maxLineWidth, PixelsToPoints(listTextLines[i].Left * scale) + xg.MeasureString(line, xfont, sf).Width);
                }
            }
            textbox.Font.Dispose();            //This font was dynamically created when the textbox was created.
            textbox.Dispose();
            //sf.Dispose();//Does not exist for PDF.
            //xfont.Dispose();//Does not exist for PDF fonts.
            return(new RectangleF(bounds.X, bounds.Y, PointsToPixels((float)maxLineWidth), bounds.Height));
        }
Beispiel #3
0
        ///<summary>If lineIndex is past the last line, then the information of the last line will be returned. </summary>
        public static RichTextLineInfo GetOneTextLine(RichTextBox textbox, int lineIndex)
        {
            if (lineIndex < 0 || GetTextLineCount(textbox) == 0)
            {
                return(new RichTextLineInfo());
            }
            RichTextLineInfo lineInfo = new RichTextLineInfo();

            //GetFirstCharIndexFromLine() returns -1 if lineIndex is past the last line.
            lineInfo.FirstCharIndex = textbox.GetFirstCharIndexFromLine(lineIndex); //-1 if lineIndex >= count of lines in rtb.
            if (lineInfo.FirstCharIndex == -1)                                      //Return the last line's information.
            {
                lineIndex = GetTextLineCount(textbox) - 1;
                lineInfo.FirstCharIndex = textbox.GetFirstCharIndexFromLine(lineIndex);              //First character of last line.
            }
            Point posThisLine = textbox.GetPositionFromCharIndex(lineInfo.FirstCharIndex);
            Point posNextLine;

            if (lineIndex != GetTextLineCount(textbox) - 1)                                                       //This is not the last line.
            {
                posNextLine = textbox.GetPositionFromCharIndex(textbox.GetFirstCharIndexFromLine(lineIndex + 1)); //Top of next line=bottom of this line.
            }
            else                                                                                                  //Only do this "phony last line" logic when we are looking at the actual last line.  Trying to copy all the content/formatting of an
                                                                                                                  //entire RichTextBox causes all kinds of printing/Pdf/alignment/spacing issues in Sheets and Forms.
            {
                using (RichTextBox rtb = new RichTextBox()) {
                    //Copy values to new RichTextBox because we might modify text below.
                    rtb.Rtf = textbox.Rtf;
                    //Setting the rtb.Font property in this RichTextBox causes an Out of Memory Exception when the Treatment Finder report attempted to run for 100+
                    //pdfs. Attempts were made to employ a "using" to dispose of the font, as well as to ensure the textbox passing it in was disposed of,
                    //however neither method succeeded. Since the only importance of the Font in this context is getting the position of the Next Line, it is also
                    //not necessary here because we obtain that from the Rtf and postNextLine. It's removal should not change the user experience. However, it will
                    //remain here, commented out, for future information so that others do not attempt to employ a font here.
                    //rtb.Font=textbox.Font;
                    rtb.Size = textbox.Size;
                    //According to MSDN, "If no paragraph is selected in the control, setting this property applies the alignment setting to the paragraph in
                    //which the insertion point appears as well as to paragraphs created after the paragraph that has the alignment property setting."
                    //https://msdn.microsoft.com/en-us/library/system.windows.forms.richtextbox.selectionalignment(v=vs.110).aspx
                    //When copying the RTF from the given textbox it also passes the selection to the new RichTextBox which is needed for the SelectionAlignment.
                    rtb.SelectionAlignment = textbox.SelectionAlignment;
                    rtb.AppendText("\r\n\t");                                                                 //Add a phony line.
                    posNextLine = rtb.GetPositionFromCharIndex(rtb.GetFirstCharIndexFromLine(lineIndex + 1)); //Top of next line=bottom of this line.
                }
            }
            lineInfo.Left   = posThisLine.X;
            lineInfo.Top    = posThisLine.Y;
            lineInfo.Bottom = posNextLine.Y;
            return(lineInfo);
        }
Beispiel #4
0
        ///<summary>Returns a list of strings representing the lines of sheet text which will display on screen when viewing the specified text.</summary>
        public static List <RichTextLineInfo> GetTextSheetDisplayLines(RichTextBox textbox)
        {
            List <RichTextLineInfo> listLines = new List <RichTextLineInfo>();
            int lineCount = GetTextLineCount(textbox);

            for (int i = 0; i < lineCount; i++)
            {
                RichTextLineInfo line = new RichTextLineInfo();
                line.FirstCharIndex = textbox.GetFirstCharIndexFromLine(i);
                Point pos = textbox.GetPositionFromCharIndex(line.FirstCharIndex);
                line.Left = pos.X;
                line.Top  = pos.Y;
                listLines.Add(line);
            }
            return(listLines);
        }
Beispiel #5
0
        ///<summary>If lineIndex is past the last line, then the information of the last line will be returned. </summary>
        public static RichTextLineInfo GetOneTextLine(RichTextBox textbox, int lineIndex)
        {
            if (lineIndex < 0 || GetTextLineCount(textbox) == 0)
            {
                return(new RichTextLineInfo());
            }
            RichTextLineInfo lineInfo = new RichTextLineInfo();
            Point            posThisLine;
            Point            posNextLine;

            using (RichTextBox rtb = new RichTextBox()) {
                //Copy values to new RichTextBox because we might modify text below.
                rtb.Text = textbox.Text;
                rtb.Font = textbox.Font;
                rtb.Size = textbox.Size;
                //According to MSDN, "If no paragraph is selected in the control, setting this property applies the alignment setting to the paragraph in
                //which the insertion point appears as well as to paragraphs created after the paragraph that has the alignment property setting."
                //https://msdn.microsoft.com/en-us/library/system.windows.forms.richtextbox.selectionalignment(v=vs.110).aspx
                //Since rb is new, there is no seletion and insertion point is 0.  Therefore, the entire text will be affected by this alignment.
                rtb.SelectionAlignment = textbox.SelectionAlignment;
                //GetFirstCharIndexFromLine() returns -1 if lineIndex is past the last line.
                lineInfo.FirstCharIndex = rtb.GetFirstCharIndexFromLine(lineIndex); //-1 if lineIndex >= count of lines in rtb.
                if (lineInfo.FirstCharIndex == -1)                                  //Return the last line's information.
                {
                    lineIndex = GetTextLineCount(rtb) - 1;
                    lineInfo.FirstCharIndex = rtb.GetFirstCharIndexFromLine(lineIndex); //First character of last line.
                }
                if (lineIndex == GetTextLineCount(rtb) - 1)                             //This is the last line.
                {
                    rtb.AppendText("\r\n\t");                                           //Add a phony line.
                }
                posThisLine = rtb.GetPositionFromCharIndex(lineInfo.FirstCharIndex);
                posNextLine = rtb.GetPositionFromCharIndex(rtb.GetFirstCharIndexFromLine(lineIndex + 1));            //Top of next line=bottom of this line.
            }
            lineInfo.Left   = posThisLine.X;
            lineInfo.Top    = posThisLine.Y;
            lineInfo.Bottom = posNextLine.Y;
            return(lineInfo);
        }