Showing posts with label PDF. Show all posts
Showing posts with label PDF. Show all posts

Tuesday, 1 May 2012

PDFs in Silverlight

Displaying PDFs

Your three main options are:

  1. Use the native web browser control in Silverlight, which requires a few hoops to jump through

  2. Use a free third party HTML content control, the example I show is the free control from DivElements

  3. Use a commercial third party HTML content control which is more robust, Infragistics is a good option.

Approach #1: Native Silverlight Web Browser control

To view PDFs in Silverlight you need to run the application with elevated permissions.  This can be done in browser but for this simple example I’ll show how to display PDFs in a Silverlight application running “out of browser”.

The key is the WebBrowser control that automatically hosts an Adobe Reader plugin, which is required to be installed on the client machine.

First create a Silverlight Application and update the MainPage.xaml file with a WebBrowser control and set the source property:

<UserControl x:Class="PdfsInSL4.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
d:DesignHeight="250"
d:DesignWidth="500"
mc:Ignorable="d">

<Grid x:Name="LayoutRoot">
<WebBrowser Source="http://stevenhollidge.com/cv/SJHAP-CV.pdf" />
</Grid>
</UserControl>


For this example I’m using my online CV as the sample PDF file.  If you run the application now you’ll see the browser is blocked.



1



In the project properties check “Enable running application out of browser” and click the “Out-of-browser Settings…” button and check the “Require elevated trust when running outside the browser:



0



Now when you run the Silverlight application you can right click and get the “Install {application name} Application onto this computer…” option.



2



3



Once the application is installed with elevated trust your web browser control will load the PDF.



4



Printing PDFs



The Adobe Reader plugin provides print functionality along with Find, Paging, Zoom, Rotate functionality and more.  Here is the print dialog:



5



Approach #2: HTML Content Viewer Controls

As well as HTML viewers from Telerik and Infragistics there is a third free option from DivElements. Some drawback are whilst it’s free it require the “windowless” Silverlight param property to be set to true and it’s not the most robust control in the world.

Setting Windowless = true (index.html in the example source code)

<body>
<form id="form1" runat="server" style="height:100%">
<div id="silverlightControlHost">
<object data="data:application/x-silverlight-2," type="application/x-silverlight-2" width="100%" height="100%">
<param name="source" value="ClientBin/DivElementTools.xap"/>
<param name="onError" value="onSilverlightError" />
<param name="background" value="white" />
<param name="minRuntimeVersion" value="5.0.61118.0" />
<param name="autoUpgrade" value="true" />
<param name="windowless" value="true" />
<a href="http://go.microsoft.com/fwlink/?LinkID=149156&v=5.0.61118.0" style="text-decoration:none">
<img src="http://go.microsoft.com/fwlink/?LinkId=161376" alt="Get Microsoft Silverlight" style="border-style:none"/>
</a>
</object>
<iframe id="_sl_historyFrame" style="visibility:hidden;height:0px;width:0px;border:0px"></iframe>
</div>
</form>
</body>
</html>

MainPage.xaml

<UserControl x:Class="DivElementTools.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:divtools="clr-namespace:Divelements.SilverlightTools;assembly=Divelements.SilverlightTools"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
d:DesignHeight="300"
d:DesignWidth="400"
mc:Ignorable="d">

<Grid x:Name="LayoutRoot" Background="White">
<Grid.RowDefinitions>
<RowDefinition Height="50" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="50" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<TextBlock Height="25"
Margin="10,17,10,10"
Text="Uri:" />
<TextBox x:Name="textboxUri"
Grid.Column="1"
Height="25"
Margin="10"
Text="http://stevenhollidge.com/cv/SJHAP-CV.pdf" />
</Grid>

<divtools:HtmlHost Name="htmlHost"
Grid.Row="1"
SourceUri="{Binding ElementName=textboxUri,
Path=Text}" />
</Grid>
</UserControl>


Vendor: http://www.divelements.co.uk/silverlight/tools.aspx

Online demo: http://stevenhollidge.com/blog-source-code/pdfs/

Example source code: http://stevenhollidge.com/blog-source-code/PdfsInSilverlight.zip


Approach #3: Infragistics HTML Content control


http://samples.infragistics.com/sllob/html-viewer/sl/#/navigating-and-custom-html

Thursday, 29 March 2012

WPF Interop: COM, ActiveX OCX and PDF fun

Here is an application that displays a PDF file inside a WPF window. 

To do this, the easiest way is to interop with the Adobe Reader COM ActiveX (OCX) control.

image

So how does WPF deal with COM and ActiveX (OCX controls), given the disparity between how classic Win32 and WPF handles HWNDs.

Classic Win32: One HWND per control
WPF: One HWND per window/dialog


Containers

The solution is to create:

  • a WPF window containing
  • a WindowsFormsHost control containing
  • a WinForms User Control containing
  • the ActiveX control


For our example we’ll be using the Adobe Acrobat Reader and you will need this installed if you wish to run the code and application.

Please note:
You cannot use this COM component outside of the main UI thread as the OCX is not thread-safe.

Here are the steps I took:

Add WinForms User Control

image

Add COM Reference to the project

add-COM-references

“Add Tab” to the Toolbox called Adobe, “Choose Items…” and add the Adobe PDF Reader

add-adobe-tab    choose-itemsCOM-components

You can now drag and drop the Adobe PDF Reader control from the Toolbox onto the WinForms User Control.

Drag-COM-OCX-component-to-WinFormUserControl

By dragging the control onto the surface it ensures the OCX is correctly registered by the form.

What C# code does that actually produce?

Add your code behind to the WinForms User Control

Finally, add a WindowsFormsHost control to your WPF window and add the WinForms UserControl as a child

To print just right click on the document and select Print.

Here is the same solution with a notify event raised by the WinForm User Control, to enable communication with the Wpf window:

Source code: http://stevenhollidge.com/blog-source-code/PdfViewAndPrint.zip

Source code:  http://stevenhollidge.com/blog-source-code/PdfViewAndPrint_with_event.zip