📄 rtfprintdocument.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 + -