将带有标题的RTF转换为多页Tiff的问题

时间:2019-02-06 20:33:42

标签: c# type-conversion tiff rtf

我有一个将RTF文档转换为Tiff图像以进行传真的程序。当前,它使用Word将文档另存为PDF,然后将其转换为Tiff。这导致Citrix服务器上的许可问题,我们需要另一种解决方案。我已经开始通过此代码获得一些成功,但是遇到了两个问题。首先也是最大的问题是,这会将标题从文档中删除。第二个是页面不是完整页面时,页面的其余部分将位于底部。我知道第一个问题是由RealTextBox剥离标题引起的。第二种可能是我设置循环的方式,但是我不太担心这一点,直到我想出一种在图像中包含标题的方式。

我已经创建了一个用于测试的简单控制台应用程序,程序的其余部分都很好,这只是我遇到问题的转换。整个代码如下。我已经在多个帮助论坛中将其拼凑而成,但此时此刻,我还是很困惑。我对页面大小和边距进行了硬编码,但是旁边有注释。我不知道我是否需要走另一条路,或者是否只需要使用其他处理程序或其他东西,以使标题不会被剥夺。任何帮助是极大的赞赏。

using System;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Runtime.InteropServices;
using System.Windows.Forms;

namespace RTFtoImageTest
{
    class Program
    {
    static void Main(string[] args)
    {

        try
        {
            string text = File.ReadAllText(@"C:\Test\TestRTFWithHeader.rtf");

            RichTextBox rtb = new RichTextBox();
            rtb.Rtf = text;
            Rectangle ImgSize = new Rectangle(100, 100, 750, 1000);//'make the width and height whatever size you want the image to be
            int checkPrint = 0;
            MemoryStream memoryStream = new MemoryStream();
            Bitmap bm = new Bitmap(ImgSize.Width, ImgSize.Height);

            ImageCodecInfo encoderInfo = GetEncoderInfo("image/tiff");

            EncoderParameters encoderParams = new EncoderParameters(2);
            EncoderParameter parameter = new EncoderParameter(
                System.Drawing.Imaging.Encoder.Compression, (long)EncoderValue.CompressionLZW);
            encoderParams.Param[0] = parameter;
            parameter = new EncoderParameter(System.Drawing.Imaging.Encoder.SaveFlag,
                (long)EncoderValue.MultiFrame);
            encoderParams.Param[1] = parameter;

            EncoderParameters EncoderParams = new EncoderParameters(2);
            EncoderParameter saveEncodeParam = new EncoderParameter(
                 System.Drawing.Imaging.Encoder.SaveFlag,
                 (long)EncoderValue.FrameDimensionPage);
            EncoderParameter CompressionEncodeParam = new EncoderParameter(
                 System.Drawing.Imaging.Encoder.Compression, (long)EncoderValue.CompressionLZW);
            EncoderParams.Param[0] = CompressionEncodeParam;
            EncoderParams.Param[1] = saveEncodeParam;

            using (bm)
            {
                using (Graphics grx = Graphics.FromImage(bm))
                {
                    grx.Clear(Color.White);
                    RichTextBoxPrintCtrl richTextBoxPrintCtrl = new RichTextBoxPrintCtrl();
                    bool done = false;
                    int cnt = 0;
                    Image tiff;

                    checkPrint = richTextBoxPrintCtrl.Print(rtb, checkPrint, rtb.TextLength, grx, ImgSize);
                    if (checkPrint >= rtb.TextLength)
                        done = true;

                    bm.Save(memoryStream, System.Drawing.Imaging.ImageFormat.Tiff);
                    tiff = Image.FromStream(memoryStream);
                    tiff.Save(@"C:\Test\rtftomultitiff.tif", encoderInfo, encoderParams);
                    while (!done)
                    {
                        checkPrint = richTextBoxPrintCtrl.Print(rtb, checkPrint, rtb.TextLength, grx, ImgSize);
                        if (checkPrint >= rtb.TextLength)
                            done = true;
                        bm.Save(memoryStream, System.Drawing.Imaging.ImageFormat.Tiff);
                        tiff.SaveAdd(Image.FromStream(memoryStream), EncoderParams);
                        cnt += 1;
                    }
                    EncoderParameter SaveEncodeParam = new EncoderParameter(
      System.Drawing.Imaging.Encoder.SaveFlag, (long)EncoderValue.Flush);
                    EncoderParams = new EncoderParameters(1);
                    EncoderParams.Param[0] = SaveEncodeParam;
                    tiff.SaveAdd(EncoderParams);

                }

            }
        }
        catch (Exception ex)
        {
            MessageBox.Show(ex.Message);
        }
    }

    private static ImageCodecInfo GetEncoderInfo(String mimeType)
    {
        int j;
        ImageCodecInfo[] encoders;
        encoders = ImageCodecInfo.GetImageEncoders();
        for (j = 0; j < encoders.Length; ++j)
        {
            if (encoders[j].MimeType == mimeType)
                return encoders[j];
        }
        return null;
    }
}


public class RichTextBoxPrintCtrl
{
    //Convert the unit used by the .NET framework (1/100 inch) 
    //and the unit 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 earlier declaration)
    }

    private const int WM_USER = 0x0400;
    private const int EM_FORMATRANGE = WM_USER + 57;

    [DllImport("USER32.dll")]
    private static extern IntPtr SendMessage(IntPtr hWnd, int msg, IntPtr wp, IntPtr lp);

    // Render the contents of the RichTextBox for printing
    // Return the last character printed + 1 (printing start from this point for next page)
    // ByVal gr As Graphics, ByVal bounds As Rectangle
    public int Print(Control rtb, int charFrom, int charTo, Graphics gr, Rectangle bounds)
    {
        //Calculate the area to render and print
        RECT rectToPrint;
        rectToPrint.Top = 1440;//(int)(bounds.Top * anInch);
        rectToPrint.Bottom = 14400;// (int)(bounds.Bottom * anInch);
        rectToPrint.Left = 1440; // (int)(bounds.Left * anInch);
        rectToPrint.Right = 10800; // (int)(bounds.Right * anInch);

        //Calculate the size of the page
        RECT rectPage;
        rectPage.Top = 0;// (int)(gr.ClipBounds.Top * anInch);
        rectPage.Bottom = 15840;// (int)(gr.ClipBounds.Bottom * anInch);
        rectPage.Left = 0;// (int)(gr.ClipBounds.Left * anInch);
        rectPage.Right = 12240;// (int)(gr.ClipBounds.Right * anInch);

        IntPtr hdc = gr.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

        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(rtb.Handle, EM_FORMATRANGE, wparam, lparam);

        //Free the block of memory allocated
        Marshal.FreeCoTaskMem(lparam);

        //Release the device context handle obtained by a previous call
        gr.ReleaseHdc(hdc);

        //Return last + 1 character printer
        return res.ToInt32();
    }

}
}

0 个答案:

没有答案