CheapWindowsHosting.com | Best and cheap SilverLight hosting. In this post I will explains about Print Screen in Silverlight.
I used a few other useful classes in my implementation.
Best OFFER Cheap SilverLight Hosting ! Click Here
WritableBitMap allows us to convert any XAML layout into a bitmap. This is very useful for my goal. I can convert a control into a bitmap, then pass it into PrintDocument. However, this does not work really well if the size of Silverlight application is larger than standard 8.5 x 11 page. If your control is larger, it will fall off the page. Also, you need to take into account page margins. So my goals adjusted for printing restrictions are:
One more important point is that Silverlight is displayed in standard 96 DPI on any resolution. I have to account for that when computing scales.
Here is what I ended up with. I tried to document my code to explain what I am doing in-line. I am using Size structure for my page sizes – standard page and printable area. I use the difference to compute margins. You also have to be careful how long it takes before you call PrintDocument.Print. If you take too long (more than a few seconds) you will get an error that dialogs must be initiated by user events. You could also inject additional data onto your control before you print. You just have to be careful to remove additional elements after your print.
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Printing;
// ReSharper disable CheckNamespace - we are putting it into the same namespace as control to avoid using statements everywhere.
namespace System.Windows.Controls
// ReSharper restore CheckNamespace
{
public static class ControlExtensions
{
private static readonly Size StandardLandscapePageSize = new Size(11, 8.5);
private static readonly Size StandardLandscapePrintableAreaSize = new Size(10, 7.5);
private const double DotsPerInch = 96;
public static void PrintScreen(this Control control)
{
try
{
double scaleX = 1;
double scaleY = 1;
double pixelWidth = DotsPerInch * StandardLandscapePrintableAreaSize.Width;
double pixelHeight = DotsPerInch * StandardLandscapePrintableAreaSize.Height;
// determine scale ratio to fit on a page
if (control.ActualWidth > pixelWidth)
scaleX = pixelWidth / control.ActualWidth;
if (control.ActualHeight > pixelHeight)
scaleY = pixelHeight / control.ActualHeight;
// create scale transform to use the scale above to automatically resize the
// control to be printed.
var transform = new ScaleTransform
{
CenterX = 0,
CenterY = 0,
ScaleX = scaleX,
ScaleY = scaleY
};
//create bit map for control, scaled appropriately
var writableBitMap = new WriteableBitmap(control, transform);
// put bit map on canvas
var canvas = new Canvas
{
Width = pixelWidth,
Height = pixelHeight,
Background = new ImageBrush { ImageSource = writableBitMap, Stretch = Stretch.Fill }
};
// create outer canvas to setup printable area margins
var outerCanvas = new Canvas
{
Width = StandardLandscapePageSize.Width * DotsPerInch,
Height = StandardLandscapePageSize.Height * DotsPerInch
};
outerCanvas.Children.Add(canvas);
//setup margins
canvas.SetValue(Canvas.LeftProperty, DotsPerInch * (StandardLandscapePageSize.Width - StandardLandscapePrintableAreaSize.Width) / 2);
canvas.SetValue(Canvas.TopProperty, DotsPerInch * (StandardLandscapePageSize.Height - StandardLandscapePrintableAreaSize.Height) / 2);
//fore refresh just in case
canvas.InvalidateMeasure();
canvas.UpdateLayout();
// create printable document
var printDocument = new PrintDocument();
printDocument.PrintPage += (s, args) =>
{
args.PageVisual = outerCanvas;
args.HasMorePages = false;
};
// launch print with the tile of Print Screen
printDocument.Print("Print Screen");
}
catch (Exception exception)
{
// replace with real error handling
MessageBox.Show("Error occurred while printing. Error message is " + exception.Message);
}
}
}
}
Enjoy it and happy coding 🙂
CheapWindowsHosting.com | Best and Cheap Silverlight hosting. In this post I will share anout implementing a silverlight Based ‘Vertical’ Tickertape.
Now to have an area of a Silverlight scroll an area, we can use the <ScrollViewer>
tag. This tag is replaced around whatever mark up we want to scroll. For the news feed or this example, this will be a StackPanel
, which will be orientated Vertical
.
<ScrollViewer x:Name="ScrollRegion"
VerticalScrollBarVisibility="Hidden"
HorizontalScrollBarVisibility="Hidden"
BorderThickness="0"
Background="White"
Height="150"
Width="200"
Cursor="Hand">
<StackPanel x:Name="ItemsStack" Orientation="Vertical" >
</StackPanel>
</ScrollViewer>
Best and cheap SilverLight Hosting >> Click Here
The above code creates a scrollable region containing a stack with no border, white background. At the moment, the stack panel is empty – this is because the content will be added by the code behind.
As this is an example, just to get an idea I’m not using real headlines but the Knights of the Roundtable. This is defined as an array of string
s thus:
String[] Knights = {
"King Arthur",
"Sir Lancelot",
"Sir Gawain",
"Sir Geraint",
"Sir Gareth",
"Sir Gaheris",
"Sir Bedivere",
"Sir Galahad",
"Sir Kay",
"Sir Bors de Ganis",
"Sir Lamorak",
"Sir Tristan",
"Sir Percivale"
};
Adding entries to our stack panel is fairly simple. We first get a reference to the stack panel, create a textblock, set the text to our next entry and add the textblock to the Children of the StackPanel
.
StackPanel sp = FindName("ItemsStack") as StackPanel;
TextBlock tb = new TextBlock();
tb.Text = Knights[0];
sp.Children.Add(tb);
We need our application to automatically add new entries to the news feed every so often. To do this, we need something that fires after a predetermined period of time and for this, we use the DispatchTimer
class.
DispatcherTimer dispatchTimer;
.
.
.
public Page()
{
InitializeComponent();
.
.
.
dispatchTimer = new DispatcherTimer();
dispatchTimer.Interval = new TimeSpan(0, 0, 30); // 30 Seconds
dispatchTimer.Tick +=new EventHandler(dispatchTimer_Tick);
dispatchTimer.Start();
What we now need is for new headings to be added to the display each time the interval fires and for this we define a handler for the Tick
event.
Adding is the same as the section above, but there are a number of additional activities that must be dealt with when adding more than the first entry. First we need to know how much space is taken up by the new heading. Once we have added the text to it, Silverlight provides the height taken up by it from the ‘ActualHeight
’ property.
UsedHeight += tb.ActualHeight; // increment the area that has been filled up till now
Next we check to see if in adding the entry, the display area needs to scroll and to do this we compare our ‘UsedHeight
’ with the actual height of the StackPanel
.
if (UsedHeight > sp.ActualHeight)
{
.
Now if it has scrolled, certain items will have vanished off the top of the region. So the application loops through each entry to see if it any part of the entry has gone over the top and then removes it.
for (i = 0; i < sp.Children.Count; i++)
{
TextBlock tbVisible = sp.Children[i] as TextBlock;
ItemHeight += tbVisible.ActualHeight;
if ((ItemHeight <= UsedHeight - sp.ActualHeight) ||
((ItemHeight - tbVisible.ActualHeight)) < (UsedHeight - sp.ActualHeight))
{
UsedHeight -= tbVisible.ActualHeight; // remove from the used height, the space taken by the item
sp.Children.RemoveAt(i); // now remove the item from the stackpanel
}
}
And that is how to create a scrollable region. I’ll be doing the actual collection of news items later and will likely post how that works at that point.