Monday, March 19, 2012

Displaying RTF fields in a report

Hi,

I would appreciate it anyone could help. I've saved RTF formatted data to a text field in the sql server db. I want to display this formatted text in a report with. Any ideas?

shot

I have the same problem, but I think I'm reallllly close to the solution.

I'm rendering the RTF to an image file and trying to load it into an image control via a referenced class. I have the class returning either an image or a byte array. Reporting services image controls apparently only work with a byte array, but as of yet I can't get it to work.

Using the same assembly reference I am able to view the resulting image with the pictureBox control, and the byte array appears to be populated as intended, it just won't load up in reporting services.

I'll attach my code thus far in hopes that you'll be able to get further than I have (if you do, be sure to post the fix).

I'm setting the image source to database, the mime type to image\bmp and value to "=Code.GetImage()". Oh, and don't forget to add the dll to the assembly cache when you add the reference to the assembly dll in reporting services, it doesn't seem to play well otherwise.

In the code section I've added the following function:

Function GetImage() As Byte()
objRTFImage.Rtf = "This is a test"
return objRTFImage.PrintToByteArray(200, 100) ' Syntax PrintToByteArray(int32 width, int32 height)
End Function

The class code in my assembly is posted below.

using System;

using System.Collections.Generic;

using System.ComponentModel;

using System.Data;

using System.Drawing;

using System.Text;

using System.Windows.Forms;

using System.Runtime.InteropServices;

using System.Drawing.Imaging;

using System.IO;

namespace RichTextRenderer

{

public partial class RTFImage : RichTextBox

{

public RTFImage()

{

}

protected override void OnPaint(PaintEventArgs pe)

{

// Calling the base class OnPaint

base.OnPaint(pe);

}

//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)

public Image PrintToImage(String plainText, Int32 width, Int32 height)

{

this.Text = plainText;

return PrintToImage( width, height);

}

public Image PrintToImage(Int32 width, Int32 height)

{

Image image = new Bitmap(width, height);

Graphics g = Graphics.FromImage(image);

Int32 retVal = this.Print(0, this.Text.Length, g, new Rectangle(this.Location, new Size(width, height)));

return image;

}

public byte[] PrintToByteArray(String plainText, Int32 width, Int32 height)

{

return ConvertImageToByteArray(PrintToImage(plainText, width, height));

}

public byte[] PrintToByteArray(Int32 width, Int32 height)

{

return ConvertImageToByteArray(PrintToImage(width, height));

}

public int Print(int charFrom, int charTo, Graphics gr, Rectangle bounds)

{

//Calculate the area to render and print

RECT rectToPrint;

rectToPrint.Top = 0;// (int)(bounds.Top * anInch);

rectToPrint.Bottom = (int)(bounds.Height * anInch);// (int)(bounds.Bottom * anInch);

rectToPrint.Left = 0;// (int)(bounds.Left * anInch);

rectToPrint.Right = (int)(bounds.Width * anInch);// (int)(bounds.Right * anInch);

//Calculate the size of the page

RECT rectPage;

rectPage.Top = 0;//(int)(bounds.Top * anInch);

rectPage.Bottom = (int)(gr.ClipBounds.Height * anInch);//(int)(bounds.Bottom * anInch);

rectPage.Left = 0;//(int)(bounds.Left * anInch);

rectPage.Right = (int)(gr.ClipBounds.Right * anInch);//(int)(bounds.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(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();

}

public static byte[] ConvertImageToByteArray(System.Drawing.Image imageToConvert)

{

byte[] Ret;

//try

//{

using (System.IO.MemoryStream ms = new MemoryStream())

{

imageToConvert.Save(ms,ImageFormat.Bmp);

ms.Position = 0;

Ret = ms.ToArray();

}

//}

//catch (Exception) { throw; }

return Ret;

}

}

}

|||

Hi

Thanks so much for your response, i luckily have the option of using Crystal....which supports RTF fields apparently - and which i'll def be using!!

Good luck with the RTF prob, i might pursue it in my personal time - please let me know if/when you have a solution and how you solved it.

thanks

No comments:

Post a Comment