Display a PDF in WPF Application [closed] - wpf

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Questions asking for code must demonstrate a minimal understanding of the problem being solved. Include attempted solutions, why they didn't work, and the expected results. See also: Stack Overflow question checklist
Closed 9 years ago.
Improve this question
Any ideas how to display a PDF file in a WPF Windows Application?
I am using the following code to run the browser but the Browser.Navigate method does not do anything!
WebBrowser browser = new WebBrowser();
browser.Navigate("http://www.google.com");
this.AddChild(browser); // this is the System.Windows.Window

You can get the Acrobat Reader control working in a WPF app by using the WindowsFormHost control. I have a blog post about it here:
http://hugeonion.com/2009/04/06/displaying-a-pdf-file-within-a-wpf-application/
I also have a 5 minute screencast of how I made it here:
http://www.screencast.com/t/JXRhGvzvB

You could simply host a Web Browser control on the form and use it to open the PDF.
There's a new native WPF "WebBrowser" control in .NET 3.51, or you could host the Windows.Forms browser in your WPF app.

Oops. this is for a winforms app. Not for WPF. I will post this anyway.
try this
private AxAcroPDFLib.AxAcroPDF axAcroPDF1;
this.axAcroPDF1 = new AxAcroPDFLib.AxAcroPDF();
this.axAcroPDF1.Dock = System.Windows.Forms.DockStyle.Fill;
this.axAcroPDF1.Enabled = true;
this.axAcroPDF1.Name = "axAcroPDF1";
this.axAcroPDF1.OcxState = ((System.Windows.Forms.AxHost.State)(resources.GetObject("axAcroPDF1.OcxState")));
axAcroPDF1.LoadFile(DownloadedFullFileName);
axAcroPDF1.Visible = true;

Try MoonPdfPanel - A WPF-based PDF viewer control
http://www.codeproject.com/Articles/579878/MoonPdfPanel-A-WPF-based-PDF-viewer-control
GitHub: https://github.com/reliak/moonpdf

Just use a frame and a webbrowser like so
Frame frame = new Frame();
WebBrowserbrowser = new WebBrowser();
browser.Navigate(new Uri(filename));
frame.Content = browser;
Then when you don't need it anymore do this to clean it up:
WebBrowser browser = frame.Content as WebBrowser;
browser.Dispose();
frame.Content = null;
If you don't clean it up then you might have memory leak problems depending on the version of .NET your using. I saw bad memory leaks in .NET 3.5 if I didn't clean up.

The following code expects Adobe Reader to be installed and the Pdf extension to be connected to this.
It simply runs it:
String fileName = "FileName.pdf";
System.Diagnostics.Process process = new System.Diagnostics.Process();
process.StartInfo.FileName = fileName;
process.Start();
process.WaitForExit();

Disclosure: Here is a commercial one and I work for this company.
I realize that an answer has already been accepted but the following does not require Adobe Reader/Acrobat and it is a WPF solution - as opposed to Winforms. I also realize this is an old question but it has just been updated so I guess it is still actual.
PDFRasterizer.NET 3.0 allows you to render to a WPF FixedDocument. It preserves all vector graphics (PDF graphics are converted to more or less equivalent WPF elements. This is probably closest to what you need.
using (FileStream file = new FileStream(path, FileMode.Open, FileAccess.Read))
{
pdfDoc = new Document(file);
ConvertToWpfOptions convertOptions = new ConvertToWpfOptions();
RenderSettings renderSettings = new RenderSettings();
...
FixedDocument wpfDoc = pdfDoc.ConvertToWpf(renderSettings, convertOptions, 0, 9, summary);
}
You can pass the wpfDoc to e.g. the WPF DocumentViewer to quickly implement a viewer.

You can also use FoxitReader. It's free and comes with an ActiveX control that registers in the web browsers (IE and others) after you install the FoxitReader application.
So after you install FoxitReader on the system put a WebBrowser Control and set its Source property to point to the file path of your PDF file.

Check this out: http://itextsharp.sourceforge.net/
You may have to use a WindowsFormsHost, but since it is open source, you might be able to make it a little more elegant in WPF.

Related

WPF native windows 10 toasts

Using .NET WPF and Windows 10, is there a way to push a local toast notification onto the action center using c#? I've only seen people making custom dialogs for that but there must be a way to do it through the os.
You can use a NotifyIcon from System.Windows.Forms namespace like this:
class Test
{
private readonly NotifyIcon _notifyIcon;
public Test()
{
_notifyIcon = new NotifyIcon();
// Extracts your app's icon and uses it as notify icon
_notifyIcon.Icon = Icon.ExtractAssociatedIcon(Assembly.GetExecutingAssembly().Location);
// Hides the icon when the notification is closed
_notifyIcon.BalloonTipClosed += (s, e) => _notifyIcon.Visible = false;
}
public void ShowNotification()
{
_notifyIcon.Visible = true;
// Shows a notification with specified message and title
_notifyIcon.ShowBalloonTip(3000, "Title", "Message", ToolTipIcon.Info);
}
}
This should work since .NET Framework 1.1. Refer to this MSDN page for parameters of ShowBalloonTip.
As I found out, the first parameter of ShowBalloonTip (in my example that would be 3000 milliseconds) is generously ignored. Comments are appreciated ;)
I know this is an old post but I thought this might help someone that stumbles on this as I did when attempting to get Toast Notifications to work on Win 10.
This seems to be good outline to follow -
Send a local toast notification from desktop C# apps
I used that link along with this great blog post- Pop a Toast Notification in WPF using Win 10 APIs
to get my WPF app working on Win10. This is a much better solution vs the "old school" notify icon because you can add buttons to complete specific actions within your toasts even after the notification has entered the action center.
Note- the first link mentions "If you are using WiX" but it's really a requirement. You must create and install your Wix setup project before you Toasts will work. As the appUserModelId for your app needs to be registered first. The second link does not mention this unless you read my comments within it.
TIP- Once your app is installed you can verify the AppUserModelId by running this command on the run line shell:appsfolder . Make sure you are in the details view, next click View , Choose Details and ensure AppUserModeId is checked. Compare your AppUserModelId against other installed apps.
Here's a snipit of code that I used. One thing two note here, I did not install the "Notifications library" mentioned in step 7 of the first link because I prefer to use the raw XML.
private const String APP_ID = "YourCompanyName.YourAppName";
public static void CreateToast()
{
XmlDocument toastXml = ToastNotificationManager.GetTemplateContent(
ToastTemplateType.ToastImageAndText02);
// Fill in the text elements
XmlNodeList stringElements = toastXml.GetElementsByTagName("text");
stringElements[0].AppendChild(toastXml.CreateTextNode("This is my title!!!!!!!!!!"));
stringElements[1].AppendChild(toastXml.CreateTextNode("This is my message!!!!!!!!!!!!"));
// Specify the absolute path to an image
string filePath = Environment.GetFolderPath(Environment.SpecialFolder.ProgramFilesX86) + #"\Your Path To File\Your Image Name.png";
XmlNodeList imageElements = toastXml.GetElementsByTagName("image");
imageElements[0].Attributes.GetNamedItem("src").NodeValue = filePath;
// Change default audio if desired - ref - https://learn.microsoft.com/en-us/uwp/schemas/tiles/toastschema/element-audio
XmlElement audio = toastXml.CreateElement("audio");
//audio.SetAttribute("src", "ms-winsoundevent:Notification.Reminder");
//audio.SetAttribute("src", "ms-winsoundevent:Notification.IM");
//audio.SetAttribute("src", "ms-winsoundevent:Notification.Mail"); // sounds like default
//audio.SetAttribute("src", "ms-winsoundevent:Notification.Looping.Call7");
audio.SetAttribute("src", "ms-winsoundevent:Notification.Looping.Call2");
//audio.SetAttribute("loop", "false");
// Add the audio element
toastXml.DocumentElement.AppendChild(audio);
XmlElement actions = toastXml.CreateElement("actions");
toastXml.DocumentElement.AppendChild(actions);
// Create a simple button to display on the toast
XmlElement action = toastXml.CreateElement("action");
actions.AppendChild(action);
action.SetAttribute("content", "Show details");
action.SetAttribute("arguments", "viewdetails");
// Create the toast
ToastNotification toast = new ToastNotification(toastXml);
// Show the toast. Be sure to specify the AppUserModelId
// on your application's shortcut!
ToastNotificationManager.CreateToastNotifier(APP_ID).Show(toast);
}
UPDATE
This seems to be working fine on windows 10
https://msdn.microsoft.com/library/windows/apps/windows.ui.notifications.toastnotificationmanager.aspx
you will need to add these nugets
Install-Package WindowsAPICodePack-Core
Install-Package WindowsAPICodePack-Shell
Add reference to:
C:\Program Files (x86)\Windows Kits\8.1\References\CommonConfiguration\Neutral\Windows.winmd
And
C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework.NETCore\v4.5\System.Runtime.WindowsRuntime.dll
And use the following code:
XmlDocument toastXml = ToastNotificationManager.GetTemplateContent(ToastTemplateType.ToastImageAndText04);
// Fill in the text elements
XmlNodeList stringElements = toastXml.GetElementsByTagName("text");
for (int i = 0; i < stringElements.Length; i++)
{
stringElements[i].AppendChild(toastXml.CreateTextNode("Line " + i));
}
// Specify the absolute path to an image
string imagePath = "file:///" + Path.GetFullPath("toastImageAndText.png");
XmlNodeList imageElements = toastXml.GetElementsByTagName("image");
ToastNotification toast = new ToastNotification(toastXml);
ToastNotificationManager.CreateToastNotifier("Toast Sample").Show(toast);
The original code can be found here: https://www.michaelcrump.net/pop-toast-notification-in-wpf/
I managed to gain access to the working API for windows 8 and 10 by referencing
Windows.winmd:
C:\Program Files (x86)\Windows Kits\8.0\References\CommonConfiguration\Neutral
This exposes Windows.UI.Notifications.
You can have a look at this post for creating a COM server that is needed in order to have notifications persisted in the AC with Win32 apps https://blogs.msdn.microsoft.com/tiles_and_toasts/2015/10/16/quickstart-handling-toast-activations-from-win32-apps-in-windows-10/.
A working sample can be found at https://github.com/WindowsNotifications/desktop-toasts

Silverlight MP3 Playing Library

I'm trying to play MP3 files in SilverSprite, and it's super buggy. Is there an alternative library I can use to play MP3s in Silverlight?
Edit: Now that there's a bounty, I'm specifically looking for something that:
Works with SL 3-4
Is a separate project/DLL
Will work in SilverSprite projects (I'm using a layer on top of SS) -- no GUI, just methods I can call to play sounds
Works with content that has the build action set to Content. I cannot use embedded resources due to a bug in SilverSprite. My app will not run.
Plays MP3s.
Can play multiple audio files at the same time
I hope it's clear what I'm trying to find. I would like something I can embed in my own game engine, which sits on top of SilverSprite. I will supply all the audio files in the XAP. (The SilverSprite audio is quite broken and doesn't work.)
Update: The specific direction I would probably like to go in is to instantiate a new MediaElement, set the source, and play it. I have some code below, but a) NaturalDuration.TimeSpan.TotalMilliseconds reports 0, and b) the .MediaOpened never triggers.
MediaElement m = new MediaElement();
m.Source = new Uri("Content/Audio/chimes.mp3", UriKind.Relative);
m.Stop(); // useless?
//m.SetSource(new FileStream("Content/Audio/chimes.mp3", FileMode.Open)); // "Permission denied" exception, is it even finding the file?
m.Volume = 1; // Max
m.Position = TimeSpan.FromMilliseconds(0);
while (m.CurrentState != System.Windows.Media.MediaElementState.Closed)
{
Thread.Sleep(10);
}
m.MediaOpened += (sender, e) =>
{
m.Play();
};
m.Play();
For some working code rather similar to your updated approach see http://www.wiredprairie.us/blog/index.php/archives/577 . Beware that the MediaElement needs to be added to the control/component tree - see http://www.michaelsnow.com/2010/12/17/playing-sound-effects-on-windows-phone-7/.
Two very interesting options for your requirements is this library and this one.
For this kind of stuff you could also implement/use a custom MediaStreamSource like this one... see here and here.
EDIT - some other options:
Playing multiple sounds in parallel via XNA see source code at http://create.msdn.com/en-US/education/catalog/sample/silverlightsound
Using MediaPlayer class from XNA 4 for example:
MediaPlayer.Stop();
MediaPlayer.Volume = 1;
MediaPlayer.Play(Song.FromUri("TestSound", new Uri("/Content/Audio/chimes.mp3", UriKind.Relative)));
As for playing multiple sound files at the same time:
IIRC this is something which could cause your app to fail validation.

Embedding word 2010 editor in a wpf application

How do I use the word editor in a WPF application? Is it possible using windows forms hosting in WPF only? Is there another way to accomplish that?
I found AvalonEdit but it does not have features that I need. So using this way, my problem may not be solved.
Also there is some stuffs out there to host a windows forms control in WPF, but it could not be my answer.
I want to understand that is there a way to use word editor in a native way in a wpf app?
Will all APIs be available in that solution?
Thanks in advance.
You can host MS Word (2007/2010 and probably other versions) from within a WebBrowser control, this works in WinForms and should work in WPF too. A .NET API is provided for automating Word, documented here. The required interop assemblies ship with Office 2010, so deployment is a lot simpler than previous Office versions.
See this Microsoft Support article for more details on hosting Word within a WebBrowser control. The Screenshot below shows Word embedded within a host Winforms application.
Note that this only works reliably for a single hosted instance of Word, so you can't show 2 Word documents side by side in the same application. Also, the Ribbon can sometimes go missing - but Word hasn't ever caused the application to crash.
Administrative rights are required to make the required registry updates as there are potential security issues. One easy method to make the registry updates is to write a script, but the following (revised/untested) code shows how this can be done in c# for Word, Excel and PowerPoint:
using System.Security.AccessControl;
private Dictionary<string,uint> OfficeBrowserRegKeys()
{
string[] officeRegKeyArray = new string[]
{
#"SOFTWARE\Classes\Word.Document.12",
#"SOFTWARE\Classes\Word.DocumentMacroEnabled.12",
#"SOFTWARE\Classes\Excel.Sheet.12",
#"SOFTWARE\Classes\Excel.SheetMacroEnabled.12",
#"SOFTWARE\Classes\Excel.SheetBinaryMacroEnabled.12",
#"SOFTWARE\Classes\PowerPoint.Show.12",
#"SOFTWARE\Classes\PowerPoint.ShowMacroEnabled.12",
#"SOFTWARE\Classes\PowerPoint.SlideShow.12",
#"SOFTWARE\Classes\PowerPoint.SlideShowMacroEnabled.12"
};
Dictionary<string,uint> officeRegKeys = new Dictionary<string, uint>();
uint wrdVal = 0x80000024;
uint excelVal = 0x80000A00;
uint powerPtVal = 0x800000A0;
foreach(string keyName in officeRegKeyArray)
{
if (keyName.Contains("Word"))
{
officeRegKeys.Add(keyName, wrdVal);
}
else if (keyName.Contains("Excel"))
{
officeRegKeys.Add(keyName, excelVal);
}
else
{
officeRegKeys.Add(keyName, powerPtVal);
}
}
return officeRegKeys;
}
private void setNewOfficeKeys()
{
uint editFlag = 0x00010000;
Dictionary<string,uint> officeRegKeys = OfficeBrowserRegKeys();
foreach (KeyValuePair<string, uint> kvp in officeRegKeys)
{
try
{
RegistryKey rKey = Registry.LocalMachine.OpenSubKey(kvp.Key,
RegistryKeyPermissionCheck.ReadWriteSubTree,
System.Security.AccessControl.RegistryRights.SetValue);
rKey.SetValue("BrowserFlags", unchecked((int)kvp.Value),
RegistryValueKind.DWord);
rKey.SetValue("EditFlags", unchecked((int)editFlag),
RegistryValueKind.DWord);
}
catch (Exception e) { string msg = e.Message; }
}
}
Well, Word proper isn't technically designed to be hosted by another app, whether it's WPF, WINFORMS or anything else.
You CAN use api tricks (like SetParent) to move the Main Word window into a WPF hosted window. I've done it before, but it's pretty tricky business and it's very easy to miss things that cause GPFs (both in Word and your app).
Is there any reason why it needs to be "Word in your app"? Why not write a little word addin and then launch Word from your app when necessary. then the Addin can communicate with your app, or your DB or whatever as necessary from within Word.
Users may find that to be a more usable approach in any case.

Internet Explorer 9 RC stops my WinForms WebBrowser control to work in editing mode

Using the IHtmlDocument2.designMode property set to On to switch a WebBrowser control hosted on a Windows Forms form to editing mode suddenly stopped working after installing Microsoft Internet Explorer 9 RC.
Question:
Any chance to fix this?
I already tried to tweak with doctype or with the EmulateIE7 meta tag but without success.
(An example would be this project)
Update 2011-02-21:
As Eric Lawrence suggested, I adjusted the "Zeta" example to set the document text before setting the edit mode.
Unfortunately I did not manage to switch to design mode, either.
Update 2011-02-24:
Parts of the discussion also take place in Eric's blog.
Update 2011-02-26:
What I currently eperience is that the behaviour seems to be different for HTTP URLs and for content that was added via WebBrowser.DocumentText.
First tests seems to prove this assumption.
I'm now going to build a solution around this assumption and post updates and a proof-of-concept here.
Update 2011-02-26 (2):
I've now built a proof-of-concept with a built-in web server which I believe is also working well with IE 9. If anyone would like to download and test whether it is working and give me a short feedback, I can clean up and release the source code for this.
Update 2011-02-26 (3):
No feedback yet, I still updated the HTML Edit Control article and demo over at the Code Project.
Update 2011-03-16:
Since Internet Explorer 9 was released yesterday, we updated our major products to use the idea with the integrated web server as described in the HTML Edit Control article.
After nearly a month of testing, I think it works quite well.
If you do experience any issues in the future with this approach, please post your comments here and I can investigate and fix.
I had a similar problem and got around it by adding the following line to the DocumentCompleted event:
((HTMLBody)_doc.body).contentEditable = "true";
We just need an empty editable control. I did however step through debugger and add value to the control's InnerHtml and it displayed it fine, and I could edit it.
Small update, we were able to get the control editable using this line also:
browserControl.browser.Document.Body.SetAttribute("contentEditable", "true");
This allows us to avoid referencing mshtml, (don't have to include Microsoft.mshtml.dll)
This lets us avoid increasing our installation size by 8 megs.
What's your exact code?
If I set the following code:
private void cbDesign_CheckedChanged(object sender, EventArgs e){
var instance =
Microsoft.VisualBasic.CompilerServices.NewLateBinding.LateGet(
wbView.ActiveXInstance,
null,
#"Document",
new object[0],
null,
null, null );
var objArray1 = new object[] { cbDesign.Checked ? #"On" : #"Off" };
Microsoft.VisualBasic.CompilerServices.NewLateBinding.LateSetComplex(
instance,
null,
#"designMode",
objArray1,
null,
null,
false,
true );
The IE9 Web Browser instance enters designMode without any problems. If you change the "Zeta" example to not set the document text after entering design mode, it also works fine.
Just want to add that I am also unable to enter designmode (using a WebBrowser control in my case). This was not an issue in the beta. Definitely new with the RC.
Another Code Project user suggested to use the following code:
First, add event DocumentCompleted:
private void SetupEvents()
{
webBrowser1.Navigated += webBrowser1_Navigated;
webBrowser1.GotFocus += webBrowser1_GotFocus;
webBrowser1.DocumentCompleted += this.theBrowser_DocumentCompleted;
}
Then write the function:
private void theBrowser_DocumentCompleted(
object sender,
WebBrowserDocumentCompletedEventArgs e)
{
webBrowser1.Document.Write(webBrowser1.DocumentText);
doc.designMode = "On";
}
Although I did not test this, I want to document it here for completeness.
It's fixed if the property is set after the document is loaded
private void DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
{
IHTMLDocument2 Doc = Document.DomDocument as IHTMLDocument2;
Doc.designMode = #"On";
}
Yesterday, Internet Explorer 9 RTM finally was released.
I did some more tiny adjustments to my control, but basically the idea with the intergrated, small web server seems to work rather well.
So the solution is in this Code Project article:
Zeta HTML Edit Control
A small wrapper class around the Windows Forms 2.0 WebBrowser control
This was the only solution that worked for me.
I hope it is OK to answer my own question and mark my answer as "answered", too?!?
I was also able to get this to work using the following inside the DocumentCompleted event:
IHTMLDocument2 Doc = browserControl.browser.Document.DomDocument as IHTMLDocument2;
if (Doc != null) Doc.designMode = #"On";
Thanks everyone!
I use HTML Editor Control, I solved this problem adding the DocumentComplete event
private void webBrowser1_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
{
(((sender as WebBrowser).Document.DomDocument as IHTMLDocument2).body as HTMLBody).contentEditable = "true";
}

Random GUI errors using C# Mono on Mac OS X

I'm developing an application in C# (Windows Forms), which uses Mono to run on Mac OS X.
It contains some dynamic controls, for example a custom groupbox which contains some labels and textboxes, a button, etc.These boxes can both be added and removed dynamically.
My CustomGrpBx inherits from GroupBox and this is the contructor I use:
public CustomGrpBx(Point CreateHere,Info Inf)
{
this.Name = Inf.Name;
this.Location = CreateHere;
CreateHere.Y = 10;
CreateHere.X = 10;
CreateHere.Y += 7;
Button btnPress = new Button();
btnPress.Location = CreateHere;
btnPress.Size = new Size(40, 24);
btnPress.Text = Name;
btnPress.Enabled = false;
this.Controls.Add(btnPress);
CreateHere.X += 45;
CreateHere.Y += 2;
TextBox txtName = new TextBox();
txtName.Location = CreateHere;
txtName.Size = new Size(75, 20);
txtName.Text = Name;
txtName.ReadOnly = true;
this.Controls.Add(txtName);
CreateHere.X += 80;
//More code here, but the same pattern as above
this.Size = new Size(CreateHere.X + 30, CreateHere.Y + 35);
}
The problem arises both when they are created, and removed, or even when a messagebox is shown.
What happens is that sometimes on rendering white boxes appears, or some labels are not drawn correctly. And sometimes when a messagebox appears, it first opens up like 5 dummies which are just blank, and which you can't close.
Am I doing something wrong, should I sleep the GUI thread a bit after each creation, or should I invalidate stuff on my own? Or should I try GTK#?
Many thanks on input on this.
It is hard to advise something without seeing actual code, but first of all, check your assembly with MoMa for incompatibility issues (for example, pinvoke's), if you primarily developed your project targeting .NET platform. Then, mono team claims that windows form support in mono is complete:
Support for Windows Forms 2.0 is complete. At this point, we are largely just fixing bugs and polishing our code.
So, you can try to run your project under .NET and see if the bug persists.
As for Gtk#. I think it is better to use gtk# if a primary OS for your project is OSX. At the very least you will be able to use some OSX-specific stuff, for example, integrate in it's toolbar. Look here for an open-source example of Gtk# project which uses some native OSX features and integrates well in it's environment. There also is a support for gtk# in MonoDevelop's designer.
P.S.
Some interesting Gtk# projects to play with:
Beagle,
Tomboy

Resources