6

我尝试打印 RichTextBox 的内容,如果打印到打印机,错误太多。但是当我打印到 XPS 文件(通过 Windows 中的 XPS 打印机)然后将此文件打印到打印机时一切正常。

那么我可以以编程方式完成所有这些事情吗?

这是我的打印方法:

 public int PrintRotate(bool rotate, PrintPageEventArgs e, int charFrom, int 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.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


        SetGraphicsMode(fmtRange.hdc, GM_ADVANCED);

        XFORM par = new XFORM();

        par = new XFORM();
        par.eM11 = 1;
        par.eM12 = 0;
        par.eM21 = 0;
        par.eM22 = 1;
        par.eDx = -e.PageSettings.Margins.Left / 100 * e.PageSettings.PrinterResolution.X;
        par.eDy = -e.PageSettings.Margins.Top / 100 * e.PageSettings.PrinterResolution.Y;
        ModifyWorldTransform(fmtRange.hdc, ref par, MWT_LEFTMULTIPLY);

        IntPtr res = IntPtr.Zero;

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

        //Get the pointer to the FORMATRANGE structure in memory
        IntPtr lparam = IntPtr.Zero;
        lparam = Marshal.AllocCoTaskMem(Marshal.SizeOf(fmtRange));
        Marshal.StructureToPtr(fmtRange, lparam, false);

        //Send the rendered data for printing 
        res = SendMessage(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();
    }
4

1 回答 1

1

I've had a problem like this, and ended up making an .XPS file and then sending that to the printer.

From your question, it sounds like you already have the process of "printing" to the xps file down, which is good since I don't know anything about the process of printing the rich text box to the xps file. In my scenaria I needed to print a dokument without using ms office, so I ended up making a XPS file, edit it in code, and then send it to the printer.

This is the code I use to send the xps-file directly to the printer:

LocalPrintServer localPrintServer = new LocalPrintServer();
var queue = localPrintServer.GetPrintQueue("NameOfPrinter");
PrintSystemJobInfo xpsPrintJob = queue.AddJob("name of print job", "my/xps/path.xps",false);

Also remember that for this code to work you need to add references to System.Printing AND "ReachFramework". Took me longer than I care to remember to find out why I couldn't access the printjob.

Most printers should support this in my experience. The common ones and it even works on the odd "barcode-printer" at our storage-department.

于 2015-02-26T11:54:53.183 回答