⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 rtfprintdocument.cs

📁 个人信息的源代码
💻 CS
字号:
using System;
using System.Drawing;
using System.Windows.Forms;
using System.Drawing.Printing;
using System.Runtime.InteropServices;


namespace PublicUIComponent
{
	/// <summary>
	/// 此类用于实现所见即所得的格式打印。
	/// </summary>
	public class RTFPrintDocument : PrintDocument
	{
		#region Windows 窗体设计器生成的代码

		/// <summary>
		/// 必需的设计器变量。
		/// </summary>
		private System.ComponentModel.Container components = null;

		public RTFPrintDocument()
		{
			//
			// Windows 窗体设计器支持所必需的
			//
			InitializeComponent();

			//
			// TODO: 在 InitializeComponent 调用后添加任何构造函数代码
			//
		}

		/// <summary>
		/// 清理所有正在使用的资源。
		/// </summary>
		protected override void Dispose( bool disposing )
		{
			if( disposing )
			{
				if(components != null)
				{
					components.Dispose();
				}
			}
			base.Dispose( disposing );
		}

		/// <summary>
		/// 设计器支持所需的方法 - 不要使用代码编辑器修改
		/// 此方法的内容。
		/// </summary>
		private void InitializeComponent()
		{
			this.components = new System.ComponentModel.Container();
		}

		#endregion

		#region 所见及所得的打印

		//Convert the unit that is used by the .NET framework (1/100 inch)
		//and the unit that is used by Win32 API calls (twips 1/1440 inch)
		private const double AnInch = 14.4;

		[StructLayout(LayoutKind.Sequential)]
		private struct RECT
		{
			public int Left;
			public int Top;
			public int Right;
			public int Bottom;
		}

		[StructLayout(LayoutKind.Sequential)]
		private struct CHARRANGE
		{
			public int cpMin;//First character of range (0 for start of doc)
			public int cpMax;//Last character of range (-1 for end of doc)
		}

		[StructLayout(LayoutKind.Sequential)]
		private struct FORMATRANGE
		{
			public IntPtr hdc;				//Actual DC to draw on
			public IntPtr hdcTarget;		//Target DC for determining text formatting
			public RECT rc;					//Region of the DC to draw to (in twips)
			public RECT rcPage;				//Region of the whole DC (page size) (in twips)
			public CHARRANGE chrg;			//Range of text to draw (see above declaration)
		}
		private const int WM_USER = 0x0400;
		private const int EM_FORMATRANGE = WM_USER + 57;

		[DllImport("User32.dll")] 
		public static extern IntPtr SendMessage(IntPtr hWnd, int msg, IntPtr wp, IntPtr lp); 

		//包容的RichTextBox对象
		RichTextBox _rtf;

		/// <summary>
		/// 重载构造函数
		/// </summary>
		/// <param name="rtf"></param>
		public RTFPrintDocument(RichTextBox rtf)
		{
			InitializeComponent();
			this._rtf = rtf;
		}
		/// <summary>
		/// Render the contents of the RichTextBox for printing
		/// </summary>
		/// <param name="charFrom"></param>
		/// <param name="charTo"></param>
		/// <param name="e"></param>
		/// <returns>Return the last character printed + 1 (printing start from this point for next page)</returns>
		private int PrintRtf(int charFrom, int charTo, PrintPageEventArgs e)
		{
			//Mark starting and ending character
			CHARRANGE cRange;
			cRange.cpMin = charFrom;
			cRange.cpMax = charTo;

			//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;
			fmtRange.chrg = cRange;			//Indicate character from to character to
			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 whole size of page

			IntPtr res = IntPtr.Zero;
			
			IntPtr wparam = IntPtr.Zero;
			wparam = new IntPtr(1);

			//MessageBox.Show("wparam:" + wparam.ToString());

			//Move the pointer to the FORMATRANGE structure in memory
			IntPtr lparam = IntPtr.Zero;
			lparam = Marshal.AllocCoTaskMem(Marshal.SizeOf(fmtRange));
			//MessageBox.Show("lparam:" + lparam.ToString());
			Marshal.StructureToPtr(fmtRange, lparam, false);

			//Send the rendered data for printing
			res = SendMessage(_rtf.Handle, EM_FORMATRANGE, wparam, lparam);

			//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();
		}

		private static int printedChar = 0;//已打印的字符
		private static int Page = 0;//页码
		/// <summary>
		/// 实现多页连续打印,覆盖基类的OnPrintPage方法
		/// </summary>
		/// <param name="e"></param>
		protected override void OnPrintPage(PrintPageEventArgs e)
		{
			base.OnPrintPage (e);

			Page ++;
			printedChar = PrintRtf(printedChar, _rtf.TextLength + 1, e);

			//MessageBox.Show(printedChar.ToString());
			//MessageBox.Show(_rtf.TextLength.ToString());

			//打印页码
			e.Graphics.DrawString(Page.ToString(), new Font("宋体",10), Brushes.Black, e.PageBounds.Width / 2, e.PageBounds.Bottom + 10);
			if(printedChar < _rtf.TextLength)
			{
				e.HasMorePages = true;
			}
			else
			{
				e.HasMorePages = false;
				//复原初始设置
				printedChar = 0;
				Page = 0;
			}
		}

		#endregion
	}
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -