BHO OnDocumentComplete for the top frame only? - c#

I'm developing a BHO in CSHARP and I have an issue in onDocumentComplete method.
It runs on every IFRAME that the main document loads. How can I avoid it? I only want to handle events in the main window.
public void OnDocumentComplete(object pDisp, ref object URL)
{
document = (HTMLDocument)webBrowser.Document;
document.body.style.backgroundColor = "red";
}

Compare this.site with pDisp. If they're equal, then the code is running in the main frame:
public void OnDocumentComplete(object pDisp, ref object URL)
{
if (pDisp != this.site) {
// Ignore subframes
return;
}
document = (HTMLDocument)webBrowser.Document;
document.body.style.backgroundColor = "red";
}

Related

How to call in VSTO build in function after were overwritten?

In my Ribbon.xml is given:
<command idMso="FileSave" onAction="SaveIntercept" getEnabled="IsSaveInterceptEnabled" />
in my Ribbon.cs
public void SaveIntercept(IRibbonControl control, ref bool cancelDefault)
{
if (!IsFileSavedBefore()) <= works :)
{
call here build in FileSave
(Build in function switch tab when file was never saved before)
return;
}
... File was saved before ... continue with my code
}
I already try
RibbonUi.ActivateTabMso("TabSave");
and
Application.CommandBars.ExecuteMso("FileSave");
How call origial functionality?
Maybe this could work?
public void SaveIntercept(IRibbonControl control, ref bool cancelDefault)
{
if (!IsFileSavedBefore())
{
cancelDefault = false;
return;
}
...

White/blank screen when opening PDF multiple times xamarin (Seems to be a memory error)

I am currently making a xamarin application that contains a listview which when clicked opens a generated pdf using google.docs in a webview (Not the cleanest way but works for what I need). The PDF is opened using rg.plugin popup window that contains the webview. When the user is done viewing the pdf they can exit and return to the listview page.
Everything works correctly but once I have opened/closed 4/5 pdfs the webview starts to show just a blank screen. I believe this must be an error in the webview/application holding onto those pdfs rather than releasing that memory.
What I'm asking really is, what can be done to mitigate this issue be it cleaning up after the popup window is closed or something else?
Many thanks
I managed to solve my issue building from what you said before just thought I'd post my solution incase it's useful to anyone else looking for this.
In my custom webview renderer android I created a custom webviewclient that used onPageCommitVisible to check if the page had loaded correctly. If the load wasn't successful the page is loaded again solving the issue.
class CustomWebViewClient : WebViewClient
{
bool pageCommitted = false;
public override void OnPageFinished(Android.Webkit.WebView view, string url)
{
if (!pageCommitted)
{
view.LoadUrl(url);
}
base.OnPageFinished(view, url);
}
public override void OnPageCommitVisible(Android.Webkit.WebView view, string url)
{
pageCommitted = true;
}
}
Attached that to my OnElementChanged event
protected override void OnElementChanged(ElementChangedEventArgs<CustomWebView> e)
{
base.OnElementChanged(e);
//Control.LoadUrl("about:blank");
if (Control == null)
{
var webView = new Android.Webkit.WebView(_context);
webView.Settings.SetSupportZoom(true);
webView.Settings.BuiltInZoomControls = true;
webView.Settings.DisplayZoomControls = false;
webView.Settings.JavaScriptEnabled = true;
webView.Settings.SetEnableSmoothTransition(true);
webView.SetWebViewClient(new CustomWebViewClient());
SetNativeControl(webView);
Control.LoadUrl(Element.Uri);
}
}
This is a similar problem occured to me. This is an issue with Android Webview not with Xamarin. You can see my question
Android Webview cannot render the pdf sometimes and shows blank/white page instead
You can solved the Problem in the two ways.
1. One is to use the Js.Pdf Plugin on the server end.
2. Second option is not the recommended one. You can recursively called the function to load webview. Below is the code:
private void showPdf(final String imageString) {
pdfView.invalidate();
pdfView.getSettings().setJavaScriptEnabled(true);
pdfView.getSettings().setSupportZoom(true);
pdfView.loadUrl("http://docs.google.com/gview?embedded=true&url=" + imageString);
pdfView.setWebViewClient(new WebViewClient() {
boolean checkhasOnPageStarted = false;
#Override
public void onPageStarted(WebView view, String url, Bitmap favicon) {
}
#Override
public void onPageFinished(WebView view, String url) {
if(view.Title == ""){
view.Reload();
}
});}

Get HTML source code from CefSharp web browser

I am using aCefSharp.Wpf.ChromiumWebBrowser (Version 47.0.3.0) to load a web page. Some point after the page has loaded I want to get the source code.
I have called:
wb.GetBrowser().MainFrame.GetSourceAsync()
however it does not appear to be returning all the source code (I believe this is because there are child frames).
If I call:
wb.GetBrowser().MainFrame.ViewSource()
I can see it lists all the source code (including the inner frames).
I would like to get the same result as ViewSource(). Could some one point me in the right direction please?
Update – Added Code example
Note: The address the web browser is pointing too will only work up to and including 10/03/2016. After that it may display different data which is not what I would be looking at.
In the frmSelection.xaml file
<cefSharp:ChromiumWebBrowser Name="wb" Grid.Column="1" Grid.Row="0" />
In the frmSelection.xaml.cs file
public partial class frmSelection : UserControl
{
private System.Windows.Threading.DispatcherTimer wbTimer = new System.Windows.Threading.DispatcherTimer();
public frmSelection()
{
InitializeComponent();
// This timer will start when a web page has been loaded.
// It will wait 4 seconds and then call wbTimer_Tick which
// will then see if data can be extracted from the web page.
wbTimer.Interval = new TimeSpan(0, 0, 4);
wbTimer.Tick += new EventHandler(wbTimer_Tick);
wb.Address = "http://www.racingpost.com/horses2/cards/card.sd?race_id=644222&r_date=2016-03-10#raceTabs=sc_";
wb.FrameLoadEnd += new EventHandler<CefSharp.FrameLoadEndEventArgs>(wb_FrameLoadEnd);
}
void wb_FrameLoadEnd(object sender, CefSharp.FrameLoadEndEventArgs e)
{
if (wbTimer.IsEnabled)
wbTimer.Stop();
wbTimer.Start();
}
void wbTimer_Tick(object sender, EventArgs e)
{
wbTimer.Stop();
string html = GetHTMLFromWebBrowser();
}
private string GetHTMLFromWebBrowser()
{
// call the ViewSource method which will open up notepad and display the html.
// this is just so I can compare it to the html returned in GetSourceAsync()
// This is displaying all the html code (including child frames)
wb.GetBrowser().MainFrame.ViewSource();
// Get the html source code from the main Frame.
// This is displaying only code in the main frame and not any child frames of it.
Task<String> taskHtml = wb.GetBrowser().MainFrame.GetSourceAsync();
string response = taskHtml.Result;
return response;
}
}
I don't think I quite get this DispatcherTimer solution. I would do it like this:
public frmSelection()
{
InitializeComponent();
wb.FrameLoadEnd += WebBrowserFrameLoadEnded;
wb.Address = "http://www.racingpost.com/horses2/cards/card.sd?race_id=644222&r_date=2016-03-10#raceTabs=sc_";
}
private void WebBrowserFrameLoadEnded(object sender, FrameLoadEndEventArgs e)
{
if (e.Frame.IsMain)
{
wb.ViewSource();
wb.GetSourceAsync().ContinueWith(taskHtml =>
{
var html = taskHtml.Result;
});
}
}
I did a diff on the output of ViewSource and the text in the html variable and they are the same, so I can't reproduce your problem here.
This said, I noticed that the main frame gets loaded pretty late, so you have to wait quite a while until the notepad pops up with the source.
I was having the same issue trying to get click on and item located in a frame and not on the main frame. Using the example in your answer, I wrote the following extension method:
public static IFrame GetFrame(this ChromiumWebBrowser browser, string FrameName)
{
IFrame frame = null;
var identifiers = browser.GetBrowser().GetFrameIdentifiers();
foreach (var i in identifiers)
{
frame = browser.GetBrowser().GetFrame(i);
if (frame.Name == FrameName)
return frame;
}
return null;
}
If you have a "using" on your form for the module that contains this method you can do something like:
var frame = browser.GetFrame("nameofframe");
if (frame != null)
{
string HTML = await frame.GetSourceAsync();
}
Of course you need to make sure the page load is complete before using this, but I plan to use it a lot. Hope it helps!
Jim

BHO only working in first IE window or tab open

I've been reading and following up on how to write a BHO in IE using C# and I can register it just fine and run it but it only works properly when in the first window\tab I've got open.
I know aspects of it are triggering in every new window but the changes don't "stick" or apply if they're affecting the DOM. So, for example, I load a page that displays some text in the top of the page, it will always be there in the first tab but all the others it may be there are first then disappear or not show up at all.
I'm using c# 4 on Win7x64 using IE11. Protected mode doesn't appear to affect this one way or the other.
My code is just a mix of what's up here tutorial wise, so nothing fancy.
namespace IEExtention
{
[
ComVisible(true),
Guid("e8483cfd-d208-45f7-837c-3cdca573d84a"),
ClassInterface(ClassInterfaceType.None)
]
public class BHO : IObjectWithSite
{
private WebBrowser webBrowser;
private static readonly ILog log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
private object mySite;
public int SetSite(object site)
{
if (site != null)
{
mySite = site;
webBrowser = (WebBrowser)site;
webBrowser.DocumentComplete +=
new DWebBrowserEvents2_DocumentCompleteEventHandler(
this.OnDocumentComplete);
}
else
{
webBrowser.DocumentComplete -=
new DWebBrowserEvents2_DocumentCompleteEventHandler(
this.OnDocumentComplete);
webBrowser = null;
}
return 0;
}
public int GetSite(ref Guid guid, out IntPtr ppvSite)
{
IntPtr punk = Marshal.GetIUnknownForObject(webBrowser);
int hr = Marshal.QueryInterface(punk, ref guid, out ppvSite);
Marshal.Release(punk);
return hr;
}
public void OnDocumentComplete(object pDisp, ref object URL)
{
log.Debug("test");
if (pDisp != mySite)
{
return;
}
HTMLDocument document = (HTMLDocument)this.webBrowser.Document;
document.title = "Hello, StackOverflow!";
try
{
IHTMLDOMNode greetings = document.createTextNode("Hi there!");
IHTMLDOMNode body = document.body as IHTMLDOMNode;
body.insertBefore(greetings, body.firstChild);
}
catch (Exception e)
{
//whoo!!
}
}
It's had me stumped for a few days as even something as changing the document.title doesn't always stay.
I was able to work around this issue by threading my BHO and sleeping it for about half a second. Interestingly enough I needed to up the sleep to about 1.5 seconds to deal with outside links (say something coming from outlook) to load up and get everything to display.
I'm not sure if this is the best way to do it but it solved my problem with it only working in the first tab.

Print html document from Windows Service without print dialog

I am using a windows service and i want to print a .html page when the service will start. I am using this code and it's printing well. But a print dialog box come, how do i print without the print dialog box?
public void printdoc(string document)
{
Process printjob = new Process();
printjob.StartInfo.FileName = document;
printjob.StartInfo.UseShellExecute = true;
printjob.StartInfo.Verb = "print";
printjob.StartInfo.CreateNoWindow = true;
printjob.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
printjob.Start();
}
Have there any other way to print this without showing the print dialog box.
Update: in response to this:
But i have already used this class but when i am calling the
axW.ExecWB(SHDocVw.OLECMDID.OLECMDID_PRINT,SHDocVw.OLECMDEXECOPT.OLECMDEXECOPT_PROMPTUSER , ref em, ref em);
My program getting block here when i am using from window service but it is working fine from windows application.
First off, here's the code:
using System.Reflection;
using System.Threading;
using SHDocVw;
namespace HTMLPrinting
{
public class HTMLPrinter
{
private bool documentLoaded;
private bool documentPrinted;
private void ie_DocumentComplete(object pDisp, ref object URL)
{
documentLoaded = true;
}
private void ie_PrintTemplateTeardown(object pDisp)
{
documentPrinted = true;
}
public void Print(string htmlFilename)
{
documentLoaded = false;
documentPrinted = false;
InternetExplorer ie = new InternetExplorerClass();
ie.DocumentComplete += new DWebBrowserEvents2_DocumentCompleteEventHandler(ie_DocumentComplete);
ie.PrintTemplateTeardown += new DWebBrowserEvents2_PrintTemplateTeardownEventHandler(ie_PrintTemplateTeardown);
object missing = Missing.Value;
ie.Navigate(htmlFilename, ref missing, ref missing, ref missing, ref missing);
while (!documentLoaded && ie.QueryStatusWB(OLECMDID.OLECMDID_PRINT) != OLECMDF.OLECMDF_ENABLED)
Thread.Sleep(100);
ie.ExecWB(OLECMDID.OLECMDID_PRINT, OLECMDEXECOPT.OLECMDEXECOPT_DONTPROMPTUSER, ref missing, ref missing);
while (!documentPrinted)
Thread.Sleep(100);
ie.DocumentComplete -= ie_DocumentComplete;
ie.PrintTemplateTeardown -= ie_PrintTemplateTeardown;
ie.Quit();
}
}
}
You can access the SHDocVw namespace by adding a reference to 'Microsoft Internet Controls', found on the COM tab of the Add Reference dialog.
More information on the InternetExplorer object can be found on MSDN.
The Navigate() method will load the HTML file. The other parameters allow you to specify optional parameters, such as flags and headers.
We can't print until the document is loaded. Here, I enter a loop waiting until the DocumentComplete event is called, upon which a flag is set notifying us that navigation has completed. Note that DocumentComplete is called whenever navigation is finished - upon success or failure.
Once the documentLoaded flag is set, the printing status is queried via QueryStatusWB() until printing is enabled.
Printing is started with the ExecWB() call. The OLECMDID_PRINT command is specified, along with the option OLECMDEXECOPT_DONTPROMPTUSER to automatically print without user interaction. An important note is that this will print to the default printer. To specify a printer, you will have to set the default printer (in code, you could call SetDefaultPrinter()). The two final parameters allow optional input and output parameters.
We don't want to quit until printing is complete, so once again a loop is entered. After the PrintTemplateTeardown event is fired, the documentPrinted flag is set. The objects can then be cleaned up.
From this site http://www.ussbd.com/printhtm.html
using HtmlPrinter;
hpObj=new HtmlPrinter.HtmlPrinter();
hpObj.PrintUrlFromMemory(txtUrl.Text);
Now you add the code in your project to print html page from its source text:
HtmlPrinter.HtmlPrinter hpObj=new HtmlPrinter.HtmlPrinter();
hpObj.PrintHtml(txtString.Text, true);
If you want to print without the print dialog then use the following line:
hpObj.PrintHtml(txtString.Text, false);
Here's another way to print without a print dialog. You create a PrintDialog object, initialize it and then call the Print() method.
The function below is used to print a small 2"x0.75" barcode label. You'll need to figure out a way to get an Document object from the html file.
public void PrintToPrinter(string printerName)
{
PrintDialog pd = new PrintDialog();
pd.Document = userControl11.PrintDoc; // <--- Update this line with your doc
pd.PrinterSettings.PrinterName = printerName;
try
{
pd.Document.DocumentName = "My Label";
pd.Document.DefaultPageSettings.PaperSize = new System.Drawing.Printing.PaperSize("2-.75", 200, 75);
pd.Document.DefaultPageSettings.Margins = new System.Drawing.Printing.Margins(0, 0, 0, 0);
//pd.PrinterSettings.Copies = (short)mNumCopies;
pd.Document.PrinterSettings.Copies = (short) mNumCopies;
pd.Document.Print();
}
catch
{
MessageBox.Show("INVALID PRINTER SPECIFIED");
}
}
You can use the PrintDocument class in the System.Drawing.Printing namespace to give you more control over the printing, see here for more info.
For example you can do the following:
using (PrintDocument doc = new PrintDocument())
{
doc.PrintPage += this.Doc_PrintPage;
doc.DefaultPageSettings.Landscape = true;
doc.DocumentName = fileNameOfYourDocument;
doc.Print();
}
Then a function is raised for each page to be printed and you are given a Graphics area to draw to
private void Doc_PrintPage(object sender, PrintPageEventArgs ev)
{
....
ev.Graphics.DrawImage(image, x, y, newWidth, newHeight);
}
This does require you handle the actual drawing on the text/image to the page, see here for more info.
OLECMDEXECOPT_PROMPTUSER seems to force a prompt to the user to select printer and all associated stuff, which I am pretty sure is not allowed from a service. Can someone verify this?

Categories

Resources