Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

RichTextBox rotating text for printing

Good day!

I need to print short card from RichTextBox. Size of card is 10x14 cm.

Because of customer's printer features we can put card in a printer only this way:

example image

I've tried to set PageSettings two ways:

  1. PageSettings.Width = 10; PageSettings.Height = 14.
  2. PageSettings.Width = 14; PageSettings.Height = 10.

And printable area looks like this:

enter image description here

Here's the code how the printing is released:

btnRotate.CheckedChanged += (s, e) => InitPaperSize();

private void InitPaperSize()
    {
        string name = btnRotate.Checked ? "ShortCard (rotate)" : "ShortCard";
        int width = Centimeters(btnRotate.Checked ? 14 : 10);
        int height = Centimeters(btnRotate.Checked ? 10 : 14);

        System.Drawing.Printing.PaperSize ps = new System.Drawing.Printing.PaperSize(name, width, height);
        printDocument.DefaultPageSettings.PaperSize = ps;
    }

private int Centimeters(int centimeters)
    {
        return (int)((centimeters * 100) / 2.54);
    }

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;//делим на 100 так как границы указываются в сотых долях дюйма
        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();
    }

The only problem is that we can put card in a printer only horizontally.

like image 688
Dmitry Belov Avatar asked Nov 09 '12 08:11

Dmitry Belov


1 Answers

As someone said before, you should simply set the PageSettings.Landscape property. You can also draw directly by using the graphics context of PrintPageEventArgs.Graphics. Then you can draw any rotated element or rotated text. This gives a good example. Then you don't need to work with pointers (IntPtr) or device context (GetHDC).

like image 152
Matthias Avatar answered Oct 13 '22 19:10

Matthias