internal static int GetBaselineOffsetAtCharIndex(TextBoxBase tb, int index) { if (!(tb is RichTextBox rtb) || !EnvUtils.RunningOnWindows()) { return(tb.Font.Height); } var lineNumber = rtb.GetLineFromCharIndex(index); var lineIndex = NativeMethods.SendMessageInt(rtb.Handle, NativeMethods.EM_LINEINDEX, new IntPtr(lineNumber), IntPtr.Zero).ToInt32(); var lineLength = NativeMethods.SendMessageInt(rtb.Handle, NativeMethods.EM_LINELENGTH, new IntPtr(lineNumber), IntPtr.Zero).ToInt32(); var charRange = new NativeMethods.CHARRANGE { cpMin = lineIndex, cpMax = lineIndex + lineLength }; var rect = new NativeMethods.RECT { Top = 0, Bottom = (int)AnInch, Left = 0, Right = 10000000 ////(int)(rtb.Width * anInch + 20); }; var rectPage = new NativeMethods.RECT { Top = 0, Bottom = (int)AnInch, Left = 0, Right = 10000000 ////(int)(rtb.Width * anInch + 20); }; var canvas = Graphics.FromHwnd(rtb.Handle); var canvasHdc = canvas.GetHdc(); var formatRange = new NativeMethods.FORMATRANGE { chrg = charRange, hdc = canvasHdc, hdcTarget = canvasHdc, rc = rect, rcPage = rectPage }; NativeMethods.SendMessage(rtb.Handle, NativeMethods.EM_FORMATRANGE, IntPtr.Zero, ref formatRange); canvas.ReleaseHdc(canvasHdc); canvas.Dispose(); return((int)((formatRange.rc.Bottom - formatRange.rc.Top) / AnInch)); }
private static Image RenderImage(string rtfContent, SizeF sizeInInches, Func <IntPtr, Size, Image> createImage) { using (var richText = new RichTextBox()) { richText.SetRtfOrText(rtfContent); richText.CreateControl(); using (var g = richText.CreateGraphics()) { var dpiX = g.DpiX; var dpiY = g.DpiY; richText.Width = (int)(sizeInInches.Width * dpiX); richText.Height = (int)(sizeInInches.Height * dpiY); var hdc = g.GetHdc(); var image = createImage(hdc, new Size(richText.Width, richText.Height)); using (var imageG = Graphics.FromImage(image)) { var formatRange = new NativeMethods.FORMATRANGE(); formatRange.hdc = formatRange.hdcTarget = imageG.GetHdc(); formatRange.rc.right = formatRange.rcPage.right = (int)Math.Ceiling(sizeInInches.Width * 1440); formatRange.rc.bottom = formatRange.rcPage.bottom = (int)Math.Ceiling(sizeInInches.Height * 1440); formatRange.chrg.cpMin = 0; formatRange.chrg.cpMax = -1; var lParam = Marshal.AllocCoTaskMem(Marshal.SizeOf(formatRange)); Marshal.StructureToPtr(formatRange, lParam, false); NativeMethods.SendMessage(richText.Handle, NativeMethods.EM_FORMATRANGE, 1, lParam); Marshal.FreeCoTaskMem(lParam); imageG.ReleaseHdc(formatRange.hdc); } g.ReleaseHdc(hdc); return(image); } } }