// コントロールを、与えられたGraphicsオブジェクト中に直接生成します。 // ( この時、ターゲットのGraphicsオブジェクト中で切り取るセットは考慮されません。) public void RenderToDirect(Graphics g, Rectangle rc) { // 四角形をピクセルからtwipsに変換します。 rc.X = (int)(rc.X * 1440 / g.DpiX); rc.Y = (int)(rc.Y * 1440 / g.DpiY); rc.Width = rc.X + (int)((rc.Width) * 1440 / g.DpiX); rc.Height = rc.Y + (int)((rc.Height) * 1440 / g.DpiY); // dcを取得します。 IntPtr hdc = g.GetHdc(); // FORMATRANGE構造体を設定します。 FORMATRANGE fmt = new FORMATRANGE(); fmt.hdc = fmt.hdcTarget = hdc; fmt.rc = fmt.rcPage = rc; fmt.cpMin = 0; fmt.cpMax = -1; // RTFを生成します(これをコンパイルするため、 // プロジェクトのプロパティは安全でないブロックを許可する必要があります)。 int render = 1; unsafe { SendMessage(EM_FORMATRANGE, (IntPtr)render, (IntPtr)(&fmt)); } // クリーンアップ SendMessage(EM_FORMATRANGE, IntPtr.Zero, IntPtr.Zero); // dcを用いて実行します。 g.ReleaseHdc(hdc); }
/// <summary> /// Calculate or render the contents of our RichTextBox for printing /// </summary> /// <param name="e">The PrintPageEventArgs object from the PrintPage event</param> /// <param name="posIniChar">Index of first character to be printed</param> /// <param name="posEndChar">Index of last character to be printed</param> /// <returns>Index of last character that fitted on the page, plus 1</returns> public int DoPrint(int posIniChar, int posEndChar, PrintPageEventArgs e) { // Fill in the FORMATRANGE struct var fr = FORMATRANGE.Set(e, posIniChar, posEndChar); // Allocate memory for the FORMATRANGE struct and copy this to the memory IntPtr lParam = Marshal.AllocCoTaskMem(Marshal.SizeOf(fr)); Marshal.StructureToPtr(fr, lParam, false); // Zero wParam means measure, non-zero wParam means render Int32 wParam = (MeasureOnly ? 0 : 1); // Measure to get end char index needed for call delegate before print if (beforePagePrintDelegate != null && !MeasureOnly) { int nextIndex = SendMessage(richTextBox.Handle, EM_FORMATRANGE, 0, lParam); beforePagePrintDelegate(posIniChar, nextIndex - 1, e); } // Send the Win32 message for printing int res = SendMessage(richTextBox.Handle, EM_FORMATRANGE, wParam, lParam); // Free allocated memory Marshal.FreeCoTaskMem(lParam); // Release the device context handle obtained by a previous call e.Graphics.ReleaseHdc(fr.hdc); return(res); }
//-------------------------------------------------------------------------------- #region ** Rendering // render the control directly into a given Graphics object // (this does not honor clipping set in the target Graphics object; it that is // a problem, use the RenderClipped method instead). public void Render(Graphics g, Rectangle rc) { // convert rect from pixels to twips rc.X = (int)(rc.X * 1440 / g.DpiX); rc.Y = (int)(rc.Y * 1440 / g.DpiY); rc.Width = rc.X + (int)((rc.Width) * 1440 / g.DpiX); rc.Height = rc.Y + (int)((rc.Height) * 1440 / g.DpiY); // get dc IntPtr hdc = g.GetHdc(); // set up FORMATRANGE struct FORMATRANGE fmt = new FORMATRANGE(); fmt.hdc = fmt.hdcTarget = hdc; fmt.rc = fmt.rcPage = rc; fmt.cpMin = 0; fmt.cpMax = -1; // render RTF int render = 1; SendMessageFormatRange(Handle, EM_FORMATRANGE, render, ref fmt); // clean up SendMessage(Handle, EM_FORMATRANGE, render, 0); // done with dc g.ReleaseHdc(hdc); }
public int PrintImage(int nStartForm, Graphics g) { RECT rcToPrint = default(RECT); FORMATRANGE fr = default(FORMATRANGE); IntPtr iptHdc = IntPtr.Zero; IntPtr iptRes = IntPtr.Zero; IntPtr iptParam = IntPtr.Zero; rcToPrint.Top = 0; rcToPrint.Bottom = (int)Math.Ceiling((g.VisibleClipBounds.Height * anInch)); rcToPrint.Left = 0; rcToPrint.Right = (int)Math.Ceiling((g.VisibleClipBounds.Width * anInch)); iptHdc = g.GetHdc(); fr.chrg.cpMin = nStartForm; fr.chrg.cpMax = -1; fr.hdc = fr.hdcTarget = iptHdc; fr.rc = rcToPrint; iptParam = Marshal.AllocCoTaskMem(Marshal.SizeOf(fr)); Marshal.StructureToPtr(fr, iptParam, false); iptRes = SendMessage(this.Handle, EM_FORMATRANGE, 1, iptParam.ToInt32()); Marshal.FreeCoTaskMem(iptParam); g.ReleaseHdc(iptHdc); return(iptRes.ToInt32()); }
public void Draw(Graphics g, Rectangle hdcArea, Rectangle layoutArea, Color color) { using (var brush = new SolidBrush(color)) { g.FillRectangle(brush, layoutArea); }; IntPtr hdc = g.GetHdc(); var canvasAreaTwips = new RECT().ToInches(hdcArea); var layoutAreaTwips = new RECT().ToInches(layoutArea); var formatRange = new FORMATRANGE() { charRange = new CHARRANGE() { cpMax = -1, cpMin = 0 }, hdc = hdc, hdcTarget = hdc, rect = layoutAreaTwips, rectPage = canvasAreaTwips }; IntPtr lParam = Marshal.AllocCoTaskMem(Marshal.SizeOf(formatRange)); Marshal.StructureToPtr(formatRange, lParam, false); SendMessage(this.Handle, EM_FORMATRANGE, (IntPtr)1, lParam); Marshal.FreeCoTaskMem(lParam); g.ReleaseHdc(hdc); }
// Render the contents of the RichTextBox for printing //Return the last character printed + 1 (printing start from this point for next page) public int Print(int charFrom, int charTo, PrintPageEventArgs e) { //Calculate the area to render and print RECT rectToPrint; rectToPrint.Top = (int)(e.MarginBounds.Top * anInch); rectToPrint.Bottom = (int)(e.MarginBounds.Bottom * anInch); rectToPrint.Left = (int)(e.MarginBounds.Left * anInch); rectToPrint.Right = (int)(e.MarginBounds.Right * anInch); //Calculate the size of the page RECT rectPage; rectPage.Top = (int)(e.PageBounds.Top * anInch); rectPage.Bottom = (int)(e.PageBounds.Bottom * anInch); rectPage.Left = (int)(e.PageBounds.Left * anInch); rectPage.Right = (int)(e.PageBounds.Right * anInch); IntPtr hdc = e.Graphics.GetHdc(); FORMATRANGE fmtRange = new FORMATRANGE(); fmtRange.chrg.cpMax = charTo; //Indicate character from to character to fmtRange.chrg.cpMin = charFrom; fmtRange.hdc = hdc; //Use the same DC for measuring and rendering fmtRange.hdcTarget = hdc; //Point at printer hDC fmtRange.rc = rectToPrint; //Indicate the area on page to print fmtRange.rcPage = rectPage; //Indicate size of page IntPtr res = IntPtr.Zero; IntPtr wparam = IntPtr.Zero; wparam = new IntPtr(1); //Specifies whether to render the text. If this parameter is not zero, the text is rendered. Otherwise, the text is just measured. /* * //Get the pointer to the FORMATRANGE structure in memory * IntPtr lparam = IntPtr.Zero; * //Marshal Provides a collection of methods for allocating unmanaged memory, copying unmanaged memory blocks, and converting managed to unmanaged types, * //as well as other miscellaneous methods used when interacting with unmanaged code. * lparam = Marshal.AllocCoTaskMem(Marshal.SizeOf(fmtRange));//returns an integer representing the address of the block of memory allocated. * Marshal.StructureToPtr(fmtRange, lparam, false);// Marshals data from a managed object to an unmanaged block of memory. * //lparam - A FORMATRANGE structure containing information about the output device, or NULL to free information cached by the control. * //Send the rendered data for printing * res = SendMessage(Handle, EM_FORMATRANGE, wparam, lparam); */ res = SendMessage(Handle, EM_FORMATRANGE, wparam, ref fmtRange); //Free the block of memory allocated //Marshal.FreeCoTaskMem(lparam); //Release the device context handle obtained by a previous call e.Graphics.ReleaseHdc(hdc); //Return last + 1 character printer return(res.ToInt32()); }
// send the EM_FORMATRANGE message to the RichTextBox to render or measure // a range of the document into a target specified by a FORMATRANGE structure. int FormatRange(RichTextBox rtb, bool render, ref FORMATRANGE fmt) { // render int nextChar = SendMessageFormatRange( rtb.Handle, EM_FORMATRANGE, render ? 1 : 0, ref fmt); // reset SendMessage(rtb.Handle, EM_FORMATRANGE, 0, 0); // return next character to print return(nextChar); }
// render a page into the PrintDocument protected override void OnPrintPage(PrintPageEventArgs e) { // get a page count if that is required if (_pageCount < 0) { _pageCount = GetPageCount(e); } // update current page _currentPage++; // render text FORMATRANGE fmt = GetFormatRange(e, _firstChar); int nextChar = FormatRange(_rtb, true, ref fmt); e.Graphics.ReleaseHdc(fmt.hdc); // render header if (!string.IsNullOrEmpty(Header)) { var rc = e.MarginBounds; rc.Y = 0; rc.Height = e.MarginBounds.Top; RenderHeaderFooter(e, Header, HeaderFont, rc); e.Graphics.DrawLine(Pens.Black, rc.X, rc.Bottom, rc.Right, rc.Bottom); } // render footer if (!string.IsNullOrEmpty(Footer)) { var rc = e.MarginBounds; rc.Y = rc.Bottom; rc.Height = e.PageBounds.Bottom - rc.Y; RenderHeaderFooter(e, Footer, FooterFont, rc); e.Graphics.DrawLine(Pens.Black, rc.X, rc.Y, rc.Right, rc.Y); } // check whether we're done e.HasMorePages = nextChar > _firstChar && nextChar < _rtb.TextLength; // save start char for next time _firstChar = nextChar; // fire event as usual base.OnPrintPage(e); }
// get a page count by using FormatRange to measure the content int GetPageCount(PrintPageEventArgs e) { int pageCount = 0; // count the pages using FormatRange FORMATRANGE fmt = GetFormatRange(e, 0); for (int firstChar = 0; firstChar < _rtb.TextLength;) { fmt.cpMin = firstChar; firstChar = FormatRange(_rtb, false, ref fmt); pageCount++; } e.Graphics.ReleaseHdc(fmt.hdc); // done return(pageCount); }
//--------------------------------------------------------------------------- #region ** implementation // build a FORMATRANGE structure with the proper page size and hdc // (the hdc must be released after the FORMATRANGE is used) FORMATRANGE GetFormatRange(PrintPageEventArgs e, int firstChar) { // get page rectangle in twips var rc = e.MarginBounds; rc.X = (int)(rc.X * 14.4 + .5); rc.Y = (int)(rc.Y * 14.4 + .5); rc.Width = (int)(rc.Width * 14.4 + .5); rc.Height = (int)(rc.Height * 14.40 + .5); // set up FORMATRANGE structure var hdc = e.Graphics.GetHdc(); var fmt = new FORMATRANGE(); fmt.hdc = fmt.hdcTarget = hdc; fmt.rc.SetRect(rc); fmt.rcPage = fmt.rc; fmt.cpMin = firstChar; fmt.cpMax = -1; // done return(fmt); }
//Code converted from code found here: http://support.microsoft.com/kb/812425/en-us public void Draw(Graphics g, Rectangle hdcArea, Rectangle layoutArea) { IntPtr hdc = g.GetHdc(); var canvasAreaTwips = new RECT().ToInches(hdcArea); var layoutAreaTwips = new RECT().ToInches(layoutArea); FORMATRANGE fmtRange = new FORMATRANGE() { chrg = new CHARRANGE() { cpMax = -1, cpMin = 0 }, hdc = hdc, hdcTarget = hdc, rc = layoutAreaTwips, rcPage = canvasAreaTwips }; IntPtr lParam = Marshal.AllocCoTaskMem(Marshal.SizeOf(fmtRange)); Marshal.StructureToPtr(fmtRange, lParam, false); SendMessage(this.Handle, EM_FORMATRANGE, (IntPtr)1, lParam); Marshal.FreeCoTaskMem(lParam); g.ReleaseHdc(hdc); }
static private extern int SendMessageFormatRange( IntPtr hWnd, uint wMsg, int wParam, ref FORMATRANGE lParam);
/// <summary>Prints the specified character from.</summary> /// <param name="charFrom">The character from.</param> /// <param name="charTo">The character to.</param> /// <param name="e">The <see cref="PrintPageEventArgs"/> instance containing the event data.</param> /// <returns></returns> public int Print(int charFrom, int charTo, PrintPageEventArgs e) { CHARRANGE cHARRANGE = new CHARRANGE(); FORMATRANGE fORMATRANGE = new FORMATRANGE(); RECT rECT = new RECT(), rECT1 = new RECT(); cHARRANGE.cpMin = charFrom; cHARRANGE.cpMax = charTo; Rectangle marginBounds = e.MarginBounds; rECT1.Top = checked ((int)Math.Round((double)marginBounds.Top * 14.4)); marginBounds = e.MarginBounds; rECT1.Bottom = checked ((int)Math.Round((double)marginBounds.Bottom * 14.4)); marginBounds = e.MarginBounds; rECT1.Left = checked ((int)Math.Round((double)marginBounds.Left * 14.4)); marginBounds = e.MarginBounds; rECT1.Right = checked ((int)Math.Round((double)marginBounds.Right * 14.4)); marginBounds = e.PageBounds; rECT.Top = checked ((int)Math.Round((double)marginBounds.Top * 14.4)); marginBounds = e.PageBounds; rECT.Bottom = checked ((int)Math.Round((double)marginBounds.Bottom * 14.4)); marginBounds = e.PageBounds; rECT.Left = checked ((int)Math.Round((double)marginBounds.Left * 14.4)); marginBounds = e.PageBounds; rECT.Right = checked ((int)Math.Round((double)marginBounds.Right * 14.4)); IntPtr hdc = e.Graphics.GetHdc(); fORMATRANGE.chrg = cHARRANGE; fORMATRANGE.hdc = hdc; fORMATRANGE.hdcTarget = hdc; fORMATRANGE.rc = rECT1; fORMATRANGE.rcPage = rECT; IntPtr zero = IntPtr.Zero, intPtr = IntPtr.Zero; intPtr = new IntPtr(1); IntPtr zero1 = IntPtr.Zero; zero1 = Marshal.AllocCoTaskMem(Marshal.SizeOf <FORMATRANGE>(fORMATRANGE)); Marshal.StructureToPtr <FORMATRANGE>(fORMATRANGE, zero1, false); zero = SendMessage(Handle, 1081, intPtr, zero1); Marshal.FreeCoTaskMem(zero1); e.Graphics.ReleaseHdc(hdc); return(zero.ToInt32()); }
public static extern IntPtr SendMessage(IntPtr hWnd, uint msg, IntPtr wp, ref FORMATRANGE lp);
//private static extern IntPtr SendMessage(IntPtr hWnd, int msg, IntPtr wp, IntPtr lp); private static extern IntPtr SendMessage(IntPtr hWnd, int msg, IntPtr wp, ref FORMATRANGE lp);
// send the EM_FORMATRANGE message to the RichTextBox to render or measure // a range of the document into a target specified by a FORMATRANGE structure. int FormatRange(RichTextBox rtb, bool render, ref FORMATRANGE fmt) { // render int nextChar = SendMessageFormatRange( rtb.Handle, EM_FORMATRANGE, render ? 1 : 0, ref fmt); // reset SendMessage(rtb.Handle, EM_FORMATRANGE, 0, 0); // return next character to print return nextChar; }
// build a FORMATRANGE structure with the proper page size and hdc // (the hdc must be released after the FORMATRANGE is used) FORMATRANGE GetFormatRange(PrintPageEventArgs e, int firstChar) { // get page rectangle in twips var rc = e.MarginBounds; rc.X = (int)(rc.X * 14.4 + .5); rc.Y = (int)(rc.Y * 14.4 + .5); rc.Width = (int)(rc.Width * 14.4 + .5); rc.Height = (int)(rc.Height * 14.40 + .5); // set up FORMATRANGE structure var hdc = e.Graphics.GetHdc(); var fmt = new FORMATRANGE(); fmt.hdc = fmt.hdcTarget = hdc; fmt.rc.SetRect(rc); fmt.rcPage = fmt.rc; fmt.cpMin = firstChar; fmt.cpMax = -1; // done return fmt; }
internal static extern IntPtr SendMessage(IntPtr hWnd, uint msg, IntPtr wp, ref FORMATRANGE lp);
static extern int SendMessageFormatRange(IntPtr hWnd, uint wMsg, int wParam, ref FORMATRANGE lParam);