分类: 嵌入式
2010-11-10 10:14:10
When creating custom controls like charts, a canvas is often used as the container. If the canvas is very large, say 12000X12000 for example, printing the canvas requires some additional work. Simply rendering the canvas to a bitmap will likely cause and out of memory exception. The easiest solution is to use a transform to move portions of the image into a bitmap that is the size of the printable page. In this example I am using silverlight 4 and the new printing API’s, but the technique can be used in silverlight 3 as well.
Dialogs like file open and print require the dialog be user initiated, so first thing we need to do is create a button and button click event handler. In the event handler we need the following lines:
PrintDocument docToPrint = new PrintDocument();
docToPrint.PrintPage += new EventHandler(docToPrint_PrintPage);
docToPrint.Print("Large Canvas");
Now we need to create the PrintPage event handler. In the class where this is used, you need to have 2 member variables, both doubles. One should be called currentX the other currentY. You will also need a Boolean member named printComplete. The code that follows takes the very large canvas (in my example its named orgChart) and uses a transform to move sections of the image into the bitmap that is used as the source of an image, which is then passed as the visual to the print API.
void docToPrint_PrintPage(object sender, PrintPageEventArgs e)
{
WriteableBitmap wbmp = new WriteableBitmap((int)e.PrintableArea.Width,
(int)e.PrintableArea.Height);
// calculate the portion of the image to move into the bitmap
TranslateTransform tt = new TranslateTransform();
tt.X = (currentX) * -1;
tt.Y = (currentY) * -1;
// render the portion of the screen to the bitmap
wbmp.Render(orgChart.GetLayoutRoot(), tt);
// invalidate so the bitmap shows up
wbmp.Invalidate();
// determine if the current x and y values cover the entire chart
if (currentX + e.PrintableArea.Width > orgChart.Width)
{
currentX = 0;
currentY += e.PrintableArea.Height;
}
else
currentX += e.PrintableArea.Width;
if (currentY >= orgChart.Height)
{
printComplete = true;
}
// signal if we have more pages
e.HasMorePages = !printComplete;
Image img = new Image();
img.Source = wbmp;
e.PageVisual = img;
}