Replacement of WinForm WebBrower in Wpf - c#

I'm trying to use function from winform Project to my WPF Project, but the code seems not work with WPF or the structure of WPF. After many hours research I figured out that this code only work for winfowm. I really need to use it to print to thermal printer and I'm using to print html because my printer in this case will print Arabic characters.
Here is the code:
private void button2_Click(object sender, EventArgs e)
{
StartBrowser(xx);
}
public static void StartBrowser(string source)
{
var th = new Thread(() =>
{
var webBrowser = new WebBrowser();
webBrowser.ScrollBarsEnabled = false;
webBrowser.IsWebBrowserContextMenuEnabled = true;
webBrowser.AllowNavigation = true;
webBrowser.DocumentCompleted += webBrowser_DocumentCompleted1;
webBrowser.DocumentText = source;
Application.Run();
});
th.SetApartmentState(ApartmentState.STA);
th.Start();
}
static void webBrowser_DocumentCompleted1(object sender, WebBrowserDocumentCompletedEventArgs e)
{
var webBrowser = (WebBrowser)sender;
webBrowser.SetBounds(0, 0, 0, 0);
webBrowser.Print();
}
Is there any other way to print HTML like this using WPF?

You could do something similar using WebView2. However, this method doesn't replicate the current behaviour exactly. The WebView2 control needs to be added to the UI before it will be fully initialized.
Follow the steps in Get started with WebView2 in WPF apps:
Make sure you have the WebView2 runtime installed
Add the WebView2 control to your window/page/control:
<DockPanel>
<DockPanel DockPanel.Dock="Top">
<Button x:Name="PopulateWebView2"
Click="PopulateWebView2_Click"
Content="Print"/>
</DockPanel>
<wv2:WebView2 Name="webView2" />
</DockPanel>
Initialize WebView2, and call this in the window/page constructor:
void InitializeAsync()
{
webView2.EnsureCoreWebView2Async(null);
}
Handle the button click and print the page.
private void PopulateWebView2_Click(object sender, RoutedEventArgs e)
{
webView2.NavigateToString(xx); // your html string to populate the browser
webView2.NavigationCompleted += async (s, e) =>
{
await webView2.CoreWebView2.PrintToPdfAsync(#"Path/To/file.pdf");
};
}
As mentioned, the WebView2 control needs to be rendered on the UI before it can be fully initialized. This will print the page as a PDF file to the path specified in PrintToPdfAsync(path).
You could use the built-in print dialog and use the DOM to execute a print command instead using the following command, however that will require input from the user to select the file location:
await webView2.CoreWebView2.ExecuteScriptAsync("window.print();")

It will work as written in WPF, as well as it does in WinForms anyway...
First, add a reference to the System.Windows.Forms assembly.
Then qualify everything...
using WinForms = System.Windows.Forms;
public static void StartBrowser(string source)
{
var th = new Thread(() =>
{
var webBrowser = new WinForms.WebBrowser();
webBrowser.ScrollBarsEnabled = false;
webBrowser.IsWebBrowserContextMenuEnabled = true;
webBrowser.AllowNavigation = true;
webBrowser.DocumentCompleted += webBrowser_DocumentCompleted1;
webBrowser.DocumentText = source;
WinForms.Application.Run();
});
th.SetApartmentState(ApartmentState.STA);
th.Start();
}
static void webBrowser_DocumentCompleted1(object sender, WinForms.WebBrowserDocumentCompletedEventArgs e)
{
var webBrowser = (WinForms.WebBrowser)sender;
webBrowser.SetBounds(0, 0, 0, 0);
webBrowser.Print();
}

Related

C# Excel VSTO add-in - Excel process can't shut down after adding custom task pane

I'm trying to fix the issue in my Excel add-in where Excel gets stuck in the process when my user exits Excel.
I noticed that the issue starts to happen after adding a CustomTaskPane, then when I try to close Excel, it doesn't exit completely and stays in Task Manager. However if I close Excel before adding the CustomTaskPane, Excel closes properly.
Here's just a simple code on how I add the CustomTaskPane, it's just a simple blank Task Pane.
private void ThisAddIn_Startup(object sender, System.EventArgs e)
{
var host = new ElementHost();
host.Dock = DockStyle.Fill;
var taskPaneControl = new UserControl();
taskPaneControl.Controls.Add(host);
var taskPaneValue = CustomTaskPanes.Add(taskPaneControl, "My TaskPane");
taskPaneValue.Visible = true;
}
private void ThisAddIn_Shutdown(object sender, System.EventArgs e)
{
Office.CommandBar taskBar = null;
try
{
taskBar = Application.CommandBars["Task Pane"];
taskBar.Reset();
}
finally
{
if (taskBar != null)
{
Marshal.ReleaseComObject(taskBar);
taskBar = null;
}
}
}
As for the ThisAddIn_Shutdown method, it doesn't matter whether that function is empty or not, Excel still doesn't close properly.
What's with the issue where Excel does not close properly after adding a CustomTaskPane?
Please advise, thanks!
The correct way to add a task pane is given here : https://msdn.microsoft.com/en-us/library/aa942846.aspx , also there is no relation with the commandBars so you can delete your code inside shutdown.
private MyUserControl myUserControl1;
private Microsoft.Office.Tools.CustomTaskPane myCustomTaskPane;
private void ThisAddIn_Startup(object sender, System.EventArgs e)
{
myUserControl1 = new MyUserControl();
myCustomTaskPane = this.CustomTaskPanes.Add(myUserControl1, "My Task Pane");
myCustomTaskPane.Visible = true;
}
I can't tell you why Excel doesn't close after adding a custom taskpane in that way, you need to follow #Malick answer BUT
In a new class that we will call UserControlWinForm, you add a host elementHost1 and put your WPF usercontrol UserControlWpfMain
public class UserControlWinForm : UserControl
{
public UserControlWinForm()
{
var elementHost1 = new System.Windows.Forms.Integration.ElementHost();
elementHost1.Dock = DockStyle.Fill;
Controls.Add(elementHost1);
var frm = new UserControlWpfMain();
elementHost1.Child = frm;
}
}
And, following #Malick, you add your Winform usercontrol

Get final HTML content after javascript finished by Open Webkit Sharp

I'm writing a software that gets the content from URL. When working on that, I run into to problem that I can not get exactly the HTML content after the java script finished.
There are some websites that renders HTML by java-script, some do not support browsers which does not run js.
I tried using System.Windows.Controls.WebBrowser with WebBrowser.Document in LoadCompleted but no luck.
After that, I tried the OpenWebkitSharp library. On the UI, it showes the content of website correctly, but with code Document in DocumentCompleted, it still returns the content which does not rendered by java-script.
Here is my code:
...
using WebKit;
using WebKit.Interop;
public MainWindow()
{
windowFormHost = new System.Windows.Forms.Integration.WindowsFormsHost();
webBrowser = new WebKit.WebKitBrowser();
webBrowser.AllowDownloads = false;
windowFormHost.Child = webBrowser;
grdBrowserHost.Children.Add(windowFormHost);
webBrowser.Load += WebBrowser_Load;
}
private void WebBrowser_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
{
var contentHtml = ((WebKitBrowser)sender).DocumentAsHTMLDocument;
}
The contentHtml has value which is not rendered after java-script finished.
Do solve this problem, I have added some trick into my code to get the full Html content after java-script finished.
using WebKit;
using WebKit.Interop;
using WebKit.JSCore; //We need add refrence JSCore which following with Webkit package.
public MainWindow()
{
InitializeComponent();
InitBrowser();
}
private void InitBrowser()
{
windowFormHost = new System.Windows.Forms.Integration.WindowsFormsHost();
webBrowser = new WebKit.WebKitBrowser();
webBrowser.AllowDownloads = false;
windowFormHost.Child = webBrowser;
grdBrowserHost.Children.Add(windowFormHost);
webBrowser.Load += WebBrowser_Load;
}
private void WebBrowser_Load(object sender, EventArgs e)
{
//The ResourceIntercepter will throws exception if webBrowser have not finished loading its components
//We can not use DocumentCompleted to load the Htmlcontent. Because that event will be fired before Java-script is finised
webBrowser.ResourceIntercepter.ResourceFinishedLoadingEvent += new ResourceFinishedLoadingHandler(ResourceIntercepter_ResourceFinishedLoadingEvent);
}
private void ResourceIntercepter_ResourceFinishedLoadingEvent(object sender, WebKitResourcesEventArgs e)
{
//The WebBrowser.Document still show the html without java-script.
//The trict is call Javascript (I used Jquery) to get the content of HTML
JSValue documentContent = null;
var readyState = webBrowser.GetScriptManager.EvaluateScript("document.readyState");
if (readyState != null && readyState.ToString().Equals("complete"))
{
documentContent = webBrowser.GetScriptManager.EvaluateScript("$('html').html();");
var contentHtml = documentContent.ToString();
}
}
Hope this one can help you.

Use url drop of WebBrowser control in C#

I would like to use the drop functionality of the WebBrowser control in C#. Unfortunately it doesn't work although I set the AllowWebBrowserDrop property to true.
For testing I wrote this little programm with just a textbox and a webbrowser control:
public Form1()
{
InitializeComponent();
webBrowser1.AllowWebBrowserDrop = true;
textBox1.Text = "http://www.google.com";
}
private void textBox1_MouseMove(object sender, MouseEventArgs e)
{
if (e.Button == System.Windows.Forms.MouseButtons.Left)
DoDragDrop(textBox1.Text, DragDropEffects.Link);
}
private void webBrowser1_Navigating(object sender, WebBrowserNavigatingEventArgs e)
{
MessageBox.Show(e.Url.AbsoluteUri);
}
The DoDragDrop method gets executed correctly, but I never see the MessageBox appearing when dropping the string from the TextBox over the WebControl. Since the WebControl doesn't offer the usual drag & drop events I'm lost.
What do I have to do to make the url drop to the WebBrowser control work?
Use the following approach to initiate FileDrop dragging:
DataObject dObj = new DataObject();
var paths = new System.Collections.Specialized.StringCollection();
paths.Add(textBox1.Text);
dObj.SetFileDropList(paths);
textBox1.DoDragDrop(dObj, DragDropEffects.Link);

C# WebBrowser.ShowPrintDialog() not showing

I have this peculiar problem while wanting to print a html-report. The file itself is a normal local html file, located on my hard drive.
To do this, I have tried the following:
public static void PrintReport(string path)
{
WebBrowser wb = new WebBrowser();
wb.Navigate(path);
wb.ShowPrintDialog()
}
And I have this form with a button with the click event:
private void button1_Click(object sender, EventArgs e)
{
string path = #"D:\MyReport.html";
PrintReport(path);
}
This does absolutely nothing. Which is kind of strange... but things get stranger...
When editing the print function to do the following:
public static void PrintReport(string path)
{
WebBrowser wb = new WebBrowser();
wb.Navigate(path);
MessageBox.Show("TEST");
wb.ShowPrintDialog()
}
It works. Yes, only adding a MessageBox. The MessageBox is showing and after it comes the print dialog. I have also tried with Thread.Sleep(1000) instead, which doesn't work. Can anyone explain to me what's going on here? Why would a messagebox make any difference?
Can it be some kind of permission problem? I've reproduced this on both Windows 7 and 8, same thing. I made this small application with only the above code to isolate the problem. I am quite sure it works on windows XP though, since an older version of the application I'm working on runs on it. When trying to do this directly with the mshtml-dll instead I also get problems.
Any input or clarification is greatly appreciated!
The problem is that the browser is not ready to print yet. You will want to add an event handler WebBrowserDocumentCompletedEventHandler to the WebBrowser Object. Sample code below.
public static void PrintReport(string path)
{
WebBrowser wb = new WebBrowser();
wb.DocumentCompleted += new WebBrowserDocumentCompletedEventHandler(webBrowser_DocumentCompleted);
wb.Navigate(path);
}
public static void webBrowser_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
{
WebBrowser wb = (WebBrowser)sender;
if (wb.ReadyState.Equals(WebBrowserReadyState.Complete))
wb.ShowPrintDialog();
}

How can i show an image while my application is loading

i have and application windows form .net and my form1 takes a lot of time to appear because in it's event form1_Load does a lot of operation.
My goal is to show an image while the operation are being done.
private void form1_Load(object sender, EventArgs e)
{
methode1();
}
While my methode1() is working, my form doesnt show, i want to show an image on the screen while my methode1() is working because while methode1() is working, there is nothing on the screen.
All the visual things in .net is done on form. You can do it by creating an small form which contains an image load it before module1() and after completing module1() close it. Just below..
private void form1_Load(object sender, EventArgs e)
{
Form f = new Form();
f.Size = new Size(400, 10);
f.FormBorderStyle = FormBorderStyle.None;
f.MinimizeBox = false;
f.MaximizeBox = false;
Image im = Image.FromFile(path);
PictureBox pb = new PictureBox();
pb.Dock = DockStyle.Fill;
pb.Image = im;
pb.Location = new Point(5, 5);
f.Controls.Add(pb);
f.Show();
methode1();
f.Close();
}
Create another form, just for loading, with a static image, and display it before your application starts to load, and destroy it afterwards. Always on top, and with no border is the usual setup for such things.
Try this code
using System.Reactive.Linq;
private void RealForm_Load(object sender, EventArgs e)
{
var g = new Splash();
// place in this delegate the call to your time consuming operation
var timeConsumingOperation = Observable.Start(() => Thread.Sleep(5000));
timeConsumingOperation.ObserveOn(this).Subscribe(x =>
{
g.Close();
this.Visible = true;
});
this.Visible = false;
g.ShowDialog();
}
This code uses Microsoft Rx to execute operations in background threads among other cool features
http://msdn.microsoft.com/en-us/data/gg577609.aspx
In order for this code to work you need to reference two nuget packages: Rx and Rx windows forms
https://nuget.org/packages/Rx-Main/1.0.11226
https://nuget.org/packages/Rx-WinForms/1.0.11226
(splash screen c# -- google it)
Here's what I just found:
http://msdn.microsoft.com/en-us/library/aa446493.aspx
How about using the built in SplashScreen class?
http://msdn.microsoft.com/en-us/library/system.windows.splashscreen.aspx

Categories