none
how to save the content of richTextBox as jpg file? RRS feed

  • Question

  • Dear all,

    I looked through the website for the information about saving content of richTextBox as jpg file. E.g. there are some lines and some words in the richTextBox, and I wanna save them as the jpg file. However, it seems workless.

    Can you give me some hints?

    Thanks in advance,

    Cordially,

    B-D
    Wednesday, May 16, 2007 11:01 AM

Answers

  • Yes, RTB doesn't support the DrawToBitmap() method, that's why it is hidden in IntelliSense.  One workaround is to copy it off the screen:

        public static Bitmap RtbToBitmap(RichTextBox rtb) {
          rtb.Update();  // Ensure RTB fully painted
          Bitmap bmp = new Bitmap(rtb.Width, rtb.Height);
          using (Graphics gr = Graphics.FromImage(bmp)) {
            gr.CopyFromScreen(rtb.PointToScreen(Point.Empty), Point.Empty, rtb.Size);
          }
          return bmp;
        }

    This ought to work well, as long as no other window overlaps your RTB.  There's another way by asking the RTB to render itself into a device context but that's a whole heck of a lot harder.
    Sunday, May 20, 2007 1:02 PM
    Moderator
  • Use EM_FORMATRANGE msg to achieve this. following code demonstrates how to save RTB contents as a JPG image.

    the form contains a RichtextBox named richTextBox1. register for its content resized event. a button named SaveAsJpegButton.

     

    using System;

    using System.ComponentModel;

    using System.Drawing;

    using System.Text;

    using System.Windows.Forms;

    using System.Runtime.InteropServices;

     

    namespace WindowsApplication1 {

    public partial class Form1 : Form {

    [DllImport("USER32.dll")]

    private static extern Int32 SendMessage(IntPtr hWnd, int msg, int wParam, IntPtr lParam);

    private const int WM_USER = 0x400;

    private const int EM_FORMATRANGE = WM_USER + 57;

    [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;

    public int cpMax;

    }

    [StructLayout(LayoutKind.Sequential)]

    private struct FORMATRANGE {

    public IntPtr hdc;

    public IntPtr hdcTarget;

    public RECT rc;

    public RECT rcPage;

    public CHARRANGE chrg;

    }

    private const double inch = 14.4;

    private Rectangle contentRectangle;

    public Form1() {

    InitializeComponent();

    }

    private void SaveAsJpegButton_Click(object sender, EventArgs e) {

    RtbToBitmap(richTextBox1, contentRectangle, @"c:\rtb.jpg");

    }

    private void RtbToBitmap(RichTextBox rtb, Rectangle rectangle, string fileName) {

    Bitmap bmp = new Bitmap(rectangle.Width, rectangle.Height);

    using (Graphics gr = Graphics.FromImage(bmp)) {

    IntPtr hDC = gr.GetHdc();

    FORMATRANGE fmtRange;

    RECT rect;

    int fromAPI;

    rect.Top = 0; rect.Left = 0;

    rect.Bottom = (int)(bmp.Height + (bmp.Height * (bmp.HorizontalResolution/100)) * inch);

    rect.Right = (int)(bmp.Width + (bmp.Width * (bmp.VerticalResolution / 100)) * inch);

    fmtRange.chrg.cpMin = 0;

    fmtRange.chrg.cpMax = -1;

    fmtRange.hdc = hDC;

    fmtRange.hdcTarget = hDC;

    fmtRange.rc = rect;

    fmtRange.rcPage = rect;

    int wParam = 1;

    IntPtr lParam = Marshal.AllocCoTaskMem(Marshal.SizeOf(fmtRange));

    Marshal.StructureToPtr(fmtRange, lParam, false);

    fromAPI = SendMessage(rtb.Handle, EM_FORMATRANGE, wParam, lParam);

    Marshal.FreeCoTaskMem(lParam);

    fromAPI = SendMessage(rtb.Handle, EM_FORMATRANGE, wParam, new IntPtr(0));

    gr.ReleaseHdc(hDC);

    }

    bmp.Save(fileName, System.Drawing.Imaging.ImageFormat.Jpeg);

    bmp.Dispose();

    }

    private void richTextBox1_ContentsResized(object sender, ContentsResizedEventArgs e) {

    contentRectangle = e.NewRectangle;

    }

    }

    }

    Tuesday, May 22, 2007 11:00 AM

All replies

  • All System.Windows.Forms.Control elements have a DrawToBitmap method...

    So, you can do it as following: (By heart, so you may need to fix a couple of compiler problems...)

    Code Snippet

    // Create Bitmap
    Bitmap bitmap = new Bitmap(textBox.Width, textBox.Height);

    // Draw into the newly created bitmap
    textBox.DrawToBitmap(bitmap);

    // Save bitmap to file
    bitmap.Save(@"c:\capture.jpg", ImageFormat.Jpg);


    Wednesday, May 16, 2007 11:08 AM
  • Hey timvw,

    Thanks for your reply. However, I can't find the method DrawToBitmap() for the richTextBox widget in my 2.0 DotNet framework??? My VS version is VS 2005, V 8.0.50727.42, and .Net Framework is V 2.0.50727.

    I don't know why?
    Wednesday, May 16, 2007 11:43 AM
  • Hey, timvw,

    I figure it out, that method is not visible from the editor, however we can use it according to the reference.

    Thanks for the web page that you provided. I read it before, but didn't understand it so well.

    I update the code a little bit, since it is required to define the rectangle().

    Bitmap _bitmap = new Bitmap(this.richTextBox.Width, this.richTextBox.Height);

    this.richTextBox.DrawToBitmap(_bitmap, new Rectangle(0, 0, this.richTextBox.Width, this.richTextBox.Height));
                           
    _bitmap.Save(_dlgsave.FileName, ImageFormat.Jpeg);

    However, I got one jpg file with totally black, i.e. there is nothing except for black. Does it the complier error you mentioned?

    Thanks for your comments!

    B.W

    B-D

    Wednesday, May 16, 2007 12:21 PM
  • I also found out "DrawToBitmap is not fully functional for the RichTextBox; only the border of a bitmap is drawn."

    Refer to the "http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=548686&SiteID=1"

    Whereby, is there anyway to solve it?
    Wednesday, May 16, 2007 12:29 PM
  • "DrawToBitmap" only works when saving the border of the RichTextBox, currently?
    Sunday, May 20, 2007 12:43 AM
  • Yes, RTB doesn't support the DrawToBitmap() method, that's why it is hidden in IntelliSense.  One workaround is to copy it off the screen:

        public static Bitmap RtbToBitmap(RichTextBox rtb) {
          rtb.Update();  // Ensure RTB fully painted
          Bitmap bmp = new Bitmap(rtb.Width, rtb.Height);
          using (Graphics gr = Graphics.FromImage(bmp)) {
            gr.CopyFromScreen(rtb.PointToScreen(Point.Empty), Point.Empty, rtb.Size);
          }
          return bmp;
        }

    This ought to work well, as long as no other window overlaps your RTB.  There's another way by asking the RTB to render itself into a device context but that's a whole heck of a lot harder.
    Sunday, May 20, 2007 1:02 PM
    Moderator
  • Hey Hans,

    It works fine!

    Thanks a lot!

    B.W.

    B-D
    Sunday, May 20, 2007 1:44 PM
  • Hey Hans,

    I just found out that your snippet of code only supports copying the content inside the screen, not all the content inside the RTB. E.g. if there are 3 parts, only currently visible part is copied.

    I try to use the  following code,

     Rectangle rc = new Rectangle(0, 0, rtb.Width, rtb.Height);
                    gr.CopyFromScreen(rc.Location.X, rc.Location.Y, 0, 0, rtb.Size);

    However, it copied different layers in my screen, not only the content in the RTB.

    Can you give me some helps?

    Thanks in advance,

    Cordially,

    B-D

     nobugz wrote:
    Yes, RTB doesn't support the DrawToBitmap() method, that's why it is hidden in IntelliSense. One workaround is to copy it off the screen:

    public static Bitmap RtbToBitmap(RichTextBox rtb) {
    rtb.Update(); // Ensure RTB fully painted
    Bitmap bmp = new Bitmap(rtb.Width, rtb.Height);
    using (Graphics gr = Graphics.FromImage(bmp)) {
    gr.CopyFromScreen(rtb.PointToScreen(Point.Empty), Point.Empty, rtb.Size);
    }
    return bmp;
    }

    This ought to work well, as long as no other window overlaps your RTB. There's another way by asking the RTB to render itself into a device context but that's a whole heck of a lot harder.
    Monday, May 21, 2007 12:02 AM
  • Well, sure, that's what DrawToBitmap would do too.  How could it work any way else, there's only so much text you can squeeze in a bitmap...
    Monday, May 21, 2007 8:20 AM
    Moderator
  • Use EM_FORMATRANGE msg to achieve this. following code demonstrates how to save RTB contents as a JPG image.

    the form contains a RichtextBox named richTextBox1. register for its content resized event. a button named SaveAsJpegButton.

     

    using System;

    using System.ComponentModel;

    using System.Drawing;

    using System.Text;

    using System.Windows.Forms;

    using System.Runtime.InteropServices;

     

    namespace WindowsApplication1 {

    public partial class Form1 : Form {

    [DllImport("USER32.dll")]

    private static extern Int32 SendMessage(IntPtr hWnd, int msg, int wParam, IntPtr lParam);

    private const int WM_USER = 0x400;

    private const int EM_FORMATRANGE = WM_USER + 57;

    [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;

    public int cpMax;

    }

    [StructLayout(LayoutKind.Sequential)]

    private struct FORMATRANGE {

    public IntPtr hdc;

    public IntPtr hdcTarget;

    public RECT rc;

    public RECT rcPage;

    public CHARRANGE chrg;

    }

    private const double inch = 14.4;

    private Rectangle contentRectangle;

    public Form1() {

    InitializeComponent();

    }

    private void SaveAsJpegButton_Click(object sender, EventArgs e) {

    RtbToBitmap(richTextBox1, contentRectangle, @"c:\rtb.jpg");

    }

    private void RtbToBitmap(RichTextBox rtb, Rectangle rectangle, string fileName) {

    Bitmap bmp = new Bitmap(rectangle.Width, rectangle.Height);

    using (Graphics gr = Graphics.FromImage(bmp)) {

    IntPtr hDC = gr.GetHdc();

    FORMATRANGE fmtRange;

    RECT rect;

    int fromAPI;

    rect.Top = 0; rect.Left = 0;

    rect.Bottom = (int)(bmp.Height + (bmp.Height * (bmp.HorizontalResolution/100)) * inch);

    rect.Right = (int)(bmp.Width + (bmp.Width * (bmp.VerticalResolution / 100)) * inch);

    fmtRange.chrg.cpMin = 0;

    fmtRange.chrg.cpMax = -1;

    fmtRange.hdc = hDC;

    fmtRange.hdcTarget = hDC;

    fmtRange.rc = rect;

    fmtRange.rcPage = rect;

    int wParam = 1;

    IntPtr lParam = Marshal.AllocCoTaskMem(Marshal.SizeOf(fmtRange));

    Marshal.StructureToPtr(fmtRange, lParam, false);

    fromAPI = SendMessage(rtb.Handle, EM_FORMATRANGE, wParam, lParam);

    Marshal.FreeCoTaskMem(lParam);

    fromAPI = SendMessage(rtb.Handle, EM_FORMATRANGE, wParam, new IntPtr(0));

    gr.ReleaseHdc(hDC);

    }

    bmp.Save(fileName, System.Drawing.Imaging.ImageFormat.Jpeg);

    bmp.Dispose();

    }

    private void richTextBox1_ContentsResized(object sender, ContentsResizedEventArgs e) {

    contentRectangle = e.NewRectangle;

    }

    }

    }

    Tuesday, May 22, 2007 11:00 AM
  • Thank you, that's what I was looking for.

    It works perfectly. I modified your code to a function that returns a Bitmap.

     

    // Convenient overload

    public static Bitmap RtbToBitmap(Control rtb)

    {

      return RtbToBitmap(rtb,

                         rtb.ClientRectangle.Width,

                         rtb.ClientRectangle.Height);

    }

     

    // Capture

    public Bitmap RtbToBitmap(Control rtb, int width, int height)

    {

      Bitmap bmp = new Bitmap(width, height);

     

      using (Graphics gr = Graphics.FromImage(bmp))

      {

        IntPtr hDC = gr.GetHdc();

        FORMATRANGE fmtRange;

        RECT rect;

        int fromAPI;

        rect.Top = 0; rect.Left = 0;

        rect.Bottom = (int)(bmp.Height

                           + (bmp.Height * (bmp.HorizontalResolution / 100))

                           * inch);

        rect.Right = (int)(bmp.Width

                          + (bmp.Width * (bmp.VerticalResolution / 100))

                          * inch);

        fmtRange.chrg.cpMin = 0;

        fmtRange.chrg.cpMax = -1;

        fmtRange.hdc = hDC;

        fmtRange.hdcTarget = hDC;

        fmtRange.rc = rect;

        fmtRange.rcPage = rect;

        int wParam = 1;

        IntPtr lParam = Marshal.AllocCoTaskMem(Marshal.SizeOf(fmtRange));

        Marshal.StructureToPtr(fmtRange, lParam, false);

        fromAPI = SendMessage(rtb.Handle, EM_FORMATRANGE, wParam, lParam);

        Marshal.FreeCoTaskMem(lParam);

        fromAPI = SendMessage(rtb.Handle, EM_FORMATRANGE,

                              wParam, new IntPtr(0));

        gr.ReleaseHdc(hDC);

      }

      return bmp;

    }

    Wednesday, June 13, 2007 11:07 PM
  • Hi, the code works great.

    But I have a question more: If the text is shorter than richtextbox width, the image which created has right spaces (because of using print screen and the size is equal to richtextbox size). How did I get rid of (rtrim) this?

    Thanks in advance

     

    Saturday, March 8, 2008 3:22 AM
  • This code :

    write the text with the Font , Color And Size  from a RichTextBox to a Windows.Forms.Panel  , ad then Hide it

    Is easy to adapt to a bitmap

        private bool HideTextBoxes()
            {
                //Get BackGrond
                Bitmap Bc = new Bitmap(Panels[0].Width, Panels[0].Height);
                Bc = (Bitmap)Panels[0].BackgroundImage;
               if (Bc == null)
                {
                    return false;
                }
               SolidBrush SelBrush = null;
                System.Drawing.Imaging.PixelFormat format =
                  Bc.PixelFormat;
                MemoBackGround = Bc.Clone(new System.Drawing.Rectangle(0, 0, Bc.Width, Bc.Height), format);
                if (Bc == null)
                {
                    MessageBox.Show("Save report");
                    return true;
                }
                 RichTextBox TempRtb = null;
                 foreach (Control Rtb in Panels[0].Controls)
                {
                    var ty = Rtb.GetType();
                    string strType = ty.ToString();
                    if (strType == "System.Windows.Forms.RichTextBox")
                    {
                        TempRtb = new RichTextBox();
                        TempRtb = (RichTextBox)Rtb;
                        Graphics Data;
                        Data = Graphics.FromImage(Bc);
                        StringFormat drawFormat = new StringFormat();
                        string Text = TempRtb.Text;
                        int co = 0;
                        string Substr = string.Empty;
                       foreach (char c in Text)
                        {
                        Point p =    TempRtb.GetPositionFromCharIndex(co);
                        char ch = TempRtb.GetCharFromPosition(p);
                               try
                                    {
                                      TempRtb.Select(co,1);
                                       char SelChar = TempRtb.Text[co];
                                       Color SelColor = TempRtb.SelectionColor;
                                       System.Drawing.Font SelFont = TempRtb.SelectionFont;
                                       float fontSize = SelFont.Size;
                                       SelBrush = new SolidBrush(SelColor);
                                        Data.DrawString(ch.ToString(), SelFont, SelBrush, TempRtb.Left + p.X, TempRtb.Top + p.Y, drawFormat);
                                    }
                                    catch
                                    {
                                    }
                               co++;
                             }
                       TempRtb.Visible = false;
                       }
                    }
                  Panels[0].BackgroundImage = Bc;
                return false;
            }

    Miguel

    Saturday, October 11, 2014 11:14 AM