.net C# RichTextBox的打印预览

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


    
/// <summary>
    
/// Sets the bold style only for the selected part of the rich text box
    
/// without modifying the other properties like font or size
    
/// </summary>
    
/// <param name="bold">make selection bold (true) or regular (false)</param>
    
/// <returns>true on success, false on failure</returns>

    public bool SetSelectionBold(bool bold)
    
{
        
return SetSelectionStyle(CFM_BOLD, bold ? CFE_BOLD : 0);
    }


    
/// <summary>
    
/// Sets the italic style only for the selected part of the rich text box
    
/// without modifying the other properties like font or size
    
/// </summary>
    
/// <param name="italic">make selection italic (true) or regular (false)</param>
    
/// <returns>true on success, false on failure</returns>

    public bool SetSelectionItalic(bool italic)
    
{
        
return SetSelectionStyle(CFM_ITALIC, italic ? CFE_ITALIC : 0);
    }


    
/// <summary>
    
/// Sets the underlined style only for the selected part of the rich text box
    
/// without modifying the other properties like font or size
    
/// </summary>
    
/// <param name="underlined">make selection underlined (true) or regular (false)</param>
    
/// <returns>true on success, false on failure</returns>

    public bool SetSelectionUnderlined(bool underlined)
    
{
        
return SetSelectionStyle(CFM_UNDERLINE, underlined ? CFE_UNDERLINE : 0);
    }


    
/// <summary>
    
/// Set the style only for the selected part of the rich text box
    
/// with the possibility to mask out some styles that are not to be modified
    
/// </summary>
    
/// <param name="mask">modify which styles?</param>
    
/// <param name="effect">new values for the styles</param>
    
/// <returns>true on success, false on failure</returns>

    private bool SetSelectionStyle(UInt32 mask, UInt32 effect)
    
{
        CHARFORMATSTRUCT cf 
= new CHARFORMATSTRUCT();
        cf.cbSize 
= Marshal.SizeOf(cf);
        cf.dwMask 
= mask;
        cf.dwEffects 
= effect;

        IntPtr lParam 
= Marshal.AllocCoTaskMem(Marshal.SizeOf(cf));
        Marshal.StructureToPtr(cf, lParam, 
false);

        
int res = SendMessage(Handle, EM_SETCHARFORMAT, SCF_SELECTION, lParam);
        
return (res == 0);
    }

}


新类RichTextBoxEx

2、初始化,

            private RichTextBoxEx RTBBook;

           RTBBook = new RichTextBoxEx();
            RTBBook.Parent = this..Panel2;
            RTBBook.Dock = DockStyle.Fill;
3、增加 printDocument控件

4、设置printDocument的事件

 private int m_nFirstCharOnPage;
        private void printDocument_BeginPrint(object sender, System.Drawing.Printing.PrintEventArgs e)
        {
            m_nFirstCharOnPage = 0;
        }
        private void printDocument_PrintPage(object sender, System.Drawing.Printing.PrintPageEventArgs e)
        {
            // To print the boundaries of the current page margins
            // uncomment the next line:
            //e.Graphics.DrawRectangle(System.Drawing.Pens.Blue, e.MarginBounds);

            // make the RTBBook calculate and render as much text as will
            // fit on the page and remember the last character printed for the
            // beginning of the next page
            m_nFirstCharOnPage = RTBBook.FormatRange(false,
                e,
                m_nFirstCharOnPage,
                RTBBook.TextLength);

            // check if there are more pages to print
            if (m_nFirstCharOnPage < RTBBook.TextLength)
                e.HasMorePages = true;
            else
                e.HasMorePages = false;

        }
 private void printDocument_EndPrint(object sender, System.Drawing.Printing.PrintEventArgs e)
        {
            RTBBook.FormatRangeDone();
        }
5、预览

  private void 打印预览VToolStripMenuItem_Click(object sender, EventArgs e)
        {
         
            try
            {
                PrintPreviewDialog printPreviewDialog1 = new PrintPreviewDialog();
                printPreviewDialog1.Document = printDocument;
                printPreviewDialog1.FormBorderStyle = FormBorderStyle.Fixed3D;
                printPreviewDialog1.ShowDialog(this);
            }
            catch (Exception excep)
            {
                MessageBox.Show(excep.Message, "打印出错", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }
        }

6、打印

  private void 打印PToolStripMenuItem_Click(object sender, EventArgs e)
        {
            printDocument.Print();
        }

参考;MSDN

你可能感兴趣的:(.net C# RichTextBox的打印预览)