Swami goes Techie

Here i would share my insights on technologies.

Saturday, July 18, 2009

RADTreeView –Print Utility


Utility Overview:

RADTreeView control is a popular product of Telerik which I have used in my sample .Net WinForm application. Though there were a plenty of print tree utilities available on the net there was not much for printing RADTreeView controls. The snippets that are available were either making use of the Win APIs or printing a simple .Net treeview control, neither of them was of my interest. At the dieing moment’s of my depth first search, thanks to Mark Pitman blog for giving insight on capturing and preparing a tree image for printing. With this I went ahead in writing my own pseudo code to print RADTreeView .

Printer Utility:
I would like to split this pseudo code explanation into 2 segments,

1. Preparing the treeview for print
This step is crucial though for the reason, to capture the complete snapshot of the data or content within a treeview or any control for that matter which has the nature to grow and expand using horizontal and vertical scrollbars is not a cakewalk. It’s tricky and needs a bit of work around. In order to capture a snapshot of the complete node collection of the treeview, first we need to get hold of the virtual width and height of the tree in its expanded state; the Width and Height or the ClientSize.Width and ClientSize.Height properties of the treeview just gets the size of the treeview that is visible or rendered on the UI, they are completely ignorant of the virtual width and height of the expanded tree. Thanks to RADTreeView control which has a ready to use property as such as VirtualWidth and VirtualHeight for this purpose.

Work around Algorithm:
a) Get the Handle / Reference of the RADTreeView .
b) Store the current settings (original width, height and docking styles) in some temp variables.
c) Draw a virtual snapshot of the tree to a bitmap image, by resizing it to its virtual width and height.
d) Reset the tree to its default original settings for to be rendered as similar as it was rendered initially.

Code Snippet:
// storing the original tree settings in temp variables.
int tempHeight = tree.Height;
int tempWidth = tree.Width;
DockStyle tempDockStyle = tree.Dock;

// creating a virtual tree to capture all node details.

int scrollOffset = 10; // an offset to capture the entire tree image eradicating scrollbar mishaps.
tree.Dock = DockStyle.None; // helps to resize the tree to its virtual width and height.
tree.Width = tree.VirtualWidth;
tree.Height = tree.VirtualHeight + scrollOffset;

// Capturing the complete tree’s snapshot into a bitmap
memoryImage = new Bitmap(tree.Width, tree.Height);
tree.DrawToBitmap(memoryImage, new Rectangle(0, 0, tree.Width, tree.Height - scrollOffset));

// setting back the default settings of the original tree.
tree.Width = tempWidth;
tree.Height = tempHeight;
tree.Dock = tempDockStyle;

Above snippet is self explanatory though, there are 3 key things to watch out for,

a) Dock Style: It’s a very important property that needs to be attended. When we try to expand the tree view to its virtual width and height, and if the tree control is docked to its parent container, we should ensure that tree view’s dock property is set to DockStyle.None. Only after undocking, the tree view can be resized to its virtual width and height for the snapshot.

b) scrollOffset: Its any arbitrary integer, not required though, but I had to use it in order to
Eliminate scroll bar mishaps. Ideally the virtual width and height should get the complete tree nodes, eliminating the scrollbars but was not happening in my case. I had to do some work around like, add this scrollOffset to the virtual height during tree expansion in order to capture the missed out fragment of data at the bottom end of the tree and also subtracting the same from virtual height during bitmap generation for cropping out the visible horizontal scrolls from the print document.

c) DrawToBitmap: Performs rendering of the specified control to a bitmap object of specified size into the rectangle boundary specified.

Bitmap treeImage = new Bitmap(tree.Width, tree.Height);
tree.DrawToBitmap(treeImage, new Rectangle(0, 0, tree.Width, tree.Height - scrollOffset));

2. Printing the treeview image
Now, we are ready to print the prepared snapshot. For this I am sticking to the .Net books by making use of the PrintDocument and PrintPreviewDialog classes of System.Drawing.Printing assembly. PrintPreviewDialog class helps to show a preview of the document that is to be printed; we can also programmatically make printer configurations and other custom settings using PrintDialog class which are out of box stuffs pertaining to our context.

PrintDialog printd = new PrintDialog();
DialogResult res = printd.ShowDialog();
if (res == DialogResult.OK)
{
PrintPreviewDialog pp = new PrintPreviewDialog();
pp.Document = this._printDoc;
pp.Document.PrinterSettings = printd.PrinterSettings;
pp.Show();
}

PrintDocument class does the actually printing business; three important events that are to be handled are,
a) BeginPrint: Any initialization code required for printing, like document Page numbers can be set here.
b) PrintPage: The document printing operation takes place here.
Draws the specified portion of the specific image in the specified location with the specified size.

Graphics g = e.Graphics; // System.Drawing.Printing.PrintPageEventArgs e
g.DrawImage(treeImage, destinationRect, sourceRect, GraphicsUnit.Pixel);

c) EndPrint: Memory flush out operations can be performed here.
Hope this article along with pseudo code throws a bit of light in creating utility class for printing RADTreeView control.

Labels: , ,

0 Comments:

Post a Comment

Subscribe to Post Comments [Atom]

<< Home