1、继承RichTextBox,创建
using System;
using System.Windows.Forms;
using System.Drawing;
using System.Runtime.InteropServices;
using System.Drawing.Printing;
/**//// <summary>
/// An extension for RichTextBox suitable for printing.
/// </summary>
public class RichTextBoxEx : RichTextBox
...{
[StructLayout(LayoutKind.Sequential)]
private struct STRUCT_RECT
...{
public Int32 left;
public Int32 top;
public Int32 right;
public Int32 bottom;
}
[StructLayout(LayoutKind.Sequential)]
private struct STRUCT_CHARRANGE
...{
public Int32 cpMin;
public Int32 cpMax;
}
[StructLayout(LayoutKind.Sequential)]
private struct STRUCT_FORMATRANGE
...{
public IntPtr hdc;
public IntPtr hdcTarget;
public STRUCT_RECT rc;
public STRUCT_RECT rcPage;
public STRUCT_CHARRANGE chrg;
}
[StructLayout(LayoutKind.Sequential)]
private struct CHARFORMATSTRUCT
...{
public int cbSize;
public UInt32 dwMask;
public UInt32 dwEffects;
public Int32 yHeight;
public Int32 yOffset;
public Int32 crTextColor;
public byte bCharSet;
public byte bPitchAndFamily;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 32)]
public char[] szFaceName;
}
[DllImport("user32.dll")]
private static extern Int32 SendMessage(IntPtr hWnd, Int32 msg,
Int32 wParam, IntPtr lParam);
// Windows Messages defines
private const Int32 WM_USER = 0x400;
private const Int32 EM_FORMATRANGE = WM_USER + 57;
private const Int32 EM_GETCHARFORMAT = WM_USER + 58;
private const Int32 EM_SETCHARFORMAT = WM_USER + 68;
// Defines for EM_SETCHARFORMAT/EM_GETCHARFORMAT
private const Int32 SCF_SELECTION = 0x0001;
private const Int32 SCF_WORD = 0x0002;
private const Int32 SCF_ALL = 0x0004;
// Defines for STRUCT_CHARFORMAT member dwMask
private const UInt32 CFM_BOLD = 0x00000001;
private const UInt32 CFM_ITALIC = 0x00000002;
private const UInt32 CFM_UNDERLINE = 0x00000004;
private const UInt32 CFM_STRIKEOUT = 0x00000008;
private const UInt32 CFM_PROTECTED = 0x00000010;
private const UInt32 CFM_LINK = 0x00000020;
private const UInt32 CFM_SIZE = 0x80000000;
private const UInt32 CFM_COLOR = 0x40000000;
private const UInt32 CFM_FACE = 0x20000000;
private const UInt32 CFM_OFFSET = 0x10000000;
private const UInt32 CFM_CHARSET = 0x08000000;
// Defines for STRUCT_CHARFORMAT member dwEffects
private const UInt32 CFE_BOLD = 0x00000001;
private const UInt32 CFE_ITALIC = 0x00000002;
private const UInt32 CFE_UNDERLINE = 0x00000004;
private const UInt32 CFE_STRIKEOUT = 0x00000008;
private const UInt32 CFE_PROTECTED = 0x00000010;
private const UInt32 CFE_LINK = 0x00000020;
private const UInt32 CFE_AUTOCOLOR = 0x40000000;
/**//// <summary>
/// Calculate or render the contents of our RichTextBox for printing
/// </summary>
/// <param name="measureOnly">If true, only the calculation is performed,
/// otherwise the text is rendered as well</param>
/// <param name="e">The PrintPageEventArgs object from the
/// PrintPage event</param>
/// <param name="charFrom">Index of first character to be printed</param>
/// <param name="charTo">Index of last character to be printed</param>
/// <returns>(Index of last character that fitted on the
/// page) + 1</returns>
public int FormatRange(bool measureOnly, PrintPageEventArgs e,
int charFrom, int charTo)
...{
// Specify which characters to print
STRUCT_CHARRANGE cr;
cr.cpMin = charFrom;
cr.cpMax = charTo;
// Specify the area inside page margins
STRUCT_RECT rc;
rc.top = HundredthInchToTwips(e.MarginBounds.Top);
rc.bottom = HundredthInchToTwips(e.MarginBounds.Bottom);
rc.left = HundredthInchToTwips(e.MarginBounds.Left);
rc.right = HundredthInchToTwips(e.MarginBounds.Right);
// Specify the page area
STRUCT_RECT rcPage;
rcPage.top = HundredthInchToTwips(e.PageBounds.Top);
rcPage.bottom = HundredthInchToTwips(e.PageBounds.Bottom);
rcPage.left = HundredthInchToTwips(e.PageBounds.Left);
rcPage.right = HundredthInchToTwips(e.PageBounds.Right);
// Get device context of output device
IntPtr hdc = e.Graphics.GetHdc();
// Fill in the FORMATRANGE struct
STRUCT_FORMATRANGE fr;
fr.chrg = cr;
fr.hdc = hdc;
fr.hdcTarget = hdc;
fr.rc = rc;
fr.rcPage = rcPage;
// Non-Zero wParam means render, Zero means measure
Int32 wParam = (measureOnly ? 0 : 1);
// Allocate memory for the FORMATRANGE struct and
// copy the contents of our struct to this memory
IntPtr lParam = Marshal.AllocCoTaskMem(Marshal.SizeOf(fr));
Marshal.StructureToPtr(fr, lParam, false);
// Send the actual Win32 message
int res = SendMessage(Handle, EM_FORMATRANGE, wParam, lParam);
// Free allocated memory
Marshal.FreeCoTaskMem(lParam);
// and release the device context
e.Graphics.ReleaseHdc(hdc);
return res;
}
/**//// <summary>
/// Convert between 1/100 inch (unit used by the .NET framework)
/// and twips (1/1440 inch, used by Win32 API calls)
/// </summary>
/// <param name="n">Value in 1/100 inch</param>
/// <returns>Value in twips</returns>
private Int32 HundredthInchToTwips(int n)
...{
return (Int32)(n * 14.4);
}
/**//// <summary>
/// Free cached data from rich edit control after printing
/// </summary>
public void FormatRangeDone()
...{
IntPtr lParam = new IntPtr(0);
SendMessage(Handle, EM_FORMATRANGE, 0, lParam);
}
/**//// <summary>
/// Sets the font size only for the selected part of the rich text box
/// without modifying the other properties like font or style
/// </summary>
/// <param name="size">new point size to use</param>
/// <returns>true on success, false on failure</returns>
public bool SetSelectionSize(int size)
...{
CHARFORMATSTRUCT cf = new CHARFORMATSTRUCT();
cf.cbSize = Marshal.SizeOf(cf);
cf.dwMask = CFM_SIZE;
// yHeight is in 1/20 pt
cf.yHeight = size * 20;
IntPtr lParam = Marshal.AllocCoTaskMem(Marshal.SizeOf(cf));
Marshal.StructureToPtr(cf, lParam, false);
int res = SendMessage(Handle, EM_SETCHARFORMAT, SCF_SELECTION, lParam);
return (res == 0);
}
using System.Windows.Forms;
using System.Drawing;
using System.Runtime.InteropServices;
using System.Drawing.Printing;
/**//// <summary>
/// An extension for RichTextBox suitable for printing.
/// </summary>
public class RichTextBoxEx : RichTextBox
...{
[StructLayout(LayoutKind.Sequential)]
private struct STRUCT_RECT
...{
public Int32 left;
public Int32 top;
public Int32 right;
public Int32 bottom;
}
[StructLayout(LayoutKind.Sequential)]
private struct STRUCT_CHARRANGE
...{
public Int32 cpMin;
public Int32 cpMax;
}
[StructLayout(LayoutKind.Sequential)]
private struct STRUCT_FORMATRANGE
...{
public IntPtr hdc;
public IntPtr hdcTarget;
public STRUCT_RECT rc;
public STRUCT_RECT rcPage;
public STRUCT_CHARRANGE chrg;
}
[StructLayout(LayoutKind.Sequential)]
private struct CHARFORMATSTRUCT
...{
public int cbSize;
public UInt32 dwMask;
public UInt32 dwEffects;
public Int32 yHeight;
public Int32 yOffset;
public Int32 crTextColor;
public byte bCharSet;
public byte bPitchAndFamily;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 32)]
public char[] szFaceName;
}
[DllImport("user32.dll")]
private static extern Int32 SendMessage(IntPtr hWnd, Int32 msg,
Int32 wParam, IntPtr lParam);
// Windows Messages defines
private const Int32 WM_USER = 0x400;
private const Int32 EM_FORMATRANGE = WM_USER + 57;
private const Int32 EM_GETCHARFORMAT = WM_USER + 58;
private const Int32 EM_SETCHARFORMAT = WM_USER + 68;
// Defines for EM_SETCHARFORMAT/EM_GETCHARFORMAT
private const Int32 SCF_SELECTION = 0x0001;
private const Int32 SCF_WORD = 0x0002;
private const Int32 SCF_ALL = 0x0004;
// Defines for STRUCT_CHARFORMAT member dwMask
private const UInt32 CFM_BOLD = 0x00000001;
private const UInt32 CFM_ITALIC = 0x00000002;
private const UInt32 CFM_UNDERLINE = 0x00000004;
private const UInt32 CFM_STRIKEOUT = 0x00000008;
private const UInt32 CFM_PROTECTED = 0x00000010;
private const UInt32 CFM_LINK = 0x00000020;
private const UInt32 CFM_SIZE = 0x80000000;
private const UInt32 CFM_COLOR = 0x40000000;
private const UInt32 CFM_FACE = 0x20000000;
private const UInt32 CFM_OFFSET = 0x10000000;
private const UInt32 CFM_CHARSET = 0x08000000;
// Defines for STRUCT_CHARFORMAT member dwEffects
private const UInt32 CFE_BOLD = 0x00000001;
private const UInt32 CFE_ITALIC = 0x00000002;
private const UInt32 CFE_UNDERLINE = 0x00000004;
private const UInt32 CFE_STRIKEOUT = 0x00000008;
private const UInt32 CFE_PROTECTED = 0x00000010;
private const UInt32 CFE_LINK = 0x00000020;
private const UInt32 CFE_AUTOCOLOR = 0x40000000;
/**//// <summary>
/// Calculate or render the contents of our RichTextBox for printing
/// </summary>
/// <param name="measureOnly">If true, only the calculation is performed,
/// otherwise the text is rendered as well</param>
/// <param name="e">The PrintPageEventArgs object from the
/// PrintPage event</param>
/// <param name="charFrom">Index of first character to be printed</param>
/// <param name="charTo">Index of last character to be printed</param>
/// <returns>(Index of last character that fitted on the
/// page) + 1</returns>
public int FormatRange(bool measureOnly, PrintPageEventArgs e,
int charFrom, int charTo)
...{
// Specify which characters to print
STRUCT_CHARRANGE cr;
cr.cpMin = charFrom;
cr.cpMax = charTo;
// Specify the area inside page margins
STRUCT_RECT rc;
rc.top = HundredthInchToTwips(e.MarginBounds.Top);
rc.bottom = HundredthInchToTwips(e.MarginBounds.Bottom);
rc.left = HundredthInchToTwips(e.MarginBounds.Left);
rc.right = HundredthInchToTwips(e.MarginBounds.Right);
// Specify the page area
STRUCT_RECT rcPage;
rcPage.top = HundredthInchToTwips(e.PageBounds.Top);
rcPage.bottom = HundredthInchToTwips(e.PageBounds.Bottom);
rcPage.left = HundredthInchToTwips(e.PageBounds.Left);
rcPage.right = HundredthInchToTwips(e.PageBounds.Right);
// Get device context of output device
IntPtr hdc = e.Graphics.GetHdc();
// Fill in the FORMATRANGE struct
STRUCT_FORMATRANGE fr;
fr.chrg = cr;
fr.hdc = hdc;
fr.hdcTarget = hdc;
fr.rc = rc;
fr.rcPage = rcPage;
// Non-Zero wParam means render, Zero means measure
Int32 wParam = (measureOnly ? 0 : 1);
// Allocate memory for the FORMATRANGE struct and
// copy the contents of our struct to this memory
IntPtr lParam = Marshal.AllocCoTaskMem(Marshal.SizeOf(fr));
Marshal.StructureToPtr(fr, lParam, false);
// Send the actual Win32 message
int res = SendMessage(Handle, EM_FORMATRANGE, wParam, lParam);
// Free allocated memory
Marshal.FreeCoTaskMem(lParam);
// and release the device context
e.Graphics.ReleaseHdc(hdc);
return res;
}
/**//// <summary>
/// Convert between 1/100 inch (unit used by the .NET framework)
/// and twips (1/1440 inch, used by Win32 API calls)
/// </summary>
/// <param name="n">Value in 1/100 inch</param>
/// <returns>Value in twips</returns>
private Int32 HundredthInchToTwips(int n)
...{
return (Int32)(n * 14.4);
}
/**//// <summary>
/// Free cached data from rich edit control after printing
/// </summary>
public void FormatRangeDone()
...{
IntPtr lParam = new IntPtr(0);
SendMessage(Handle, EM_FORMATRANGE, 0, lParam);
}
/**//// <summary>
/// Sets the font size only for the selected part of the rich text box
/// without modifying the other properties like font or style
/// </summary>
/// <param name="size">new point size to use</param>
/// <returns>true on success, false on failure</returns>
public bool SetSelectionSize(int size)
...{
CHARFORMATSTRUCT cf = new CHARFORMATSTRUCT();
cf.cbSize = Marshal.SizeOf(cf);
cf.dwMask = CFM_SIZE;
// yHeight is in 1/20 pt
cf.yHeight = size * 20;
IntPtr lParam = Marshal.AllocCoTaskMem(Marshal.SizeOf(cf));
Marshal.StructureToPtr(cf, lParam, false);
int res = SendMessage(Handle, EM_SETCHARFORMAT, SCF_SELECTION, lParam);
return (res == 0);
}