How can I render an html document with an image on it for the printdocument class so I can print it? - html

Private Sub document_PrintPage(ByVal sender As Object, _
ByVal e As System.Drawing.Printing.PrintPageEventArgs) _
Handles docToPrint.PrintPage
' Insert code to render the page here.
' This code will be called when the control is drawn.
' The following code will render a simple
' message on the printed document.
'Dim text As String = "In document_PrintPage method."
'Dim printFont As New System.Drawing.Font _
' ("Arial", 35, System.Drawing.FontStyle.Regular)
'' Draw the content.
'e.Graphics.DrawString(text, printFont, _
' System.Drawing.Brushes.Black, 10, 10)
End Sub
I have code to display a printer dialog box that will call this procedure to render a document for printing. The document I want to print is accessible from a URL as an HTML webpage, and the webpage is understood to be available for printing. The sample code above, for rendering strings only, will not do what I need. I was thinking of using system.drawing.graphics.drawimage, if that can be made to work. Any ideas? I'm having trouble fully picturing the process of converting the HTML page to an image datatype. If that's not necessary, all the better.

Is there any reason you can't use System.Windows.Forms.WebBrowser?
It has a Print() method, which would seem to make your task easier. . . 8-)
Rendering HTML into an image for printing is not a trivial task. One way or the other you'll need to leverage a library that knows how to do it.

First I changed my printer dialog call so that it runs client side by using a javascript function. That was easy. The next thing was to isolate the area to be printed to the rectangle enclosing the satellite map loaded as source into an iframe. As my understanding is the javascript printer dialog would dump the whole page to the printer, I tried several things and eventually enclosed the iframe in its own div section on the asp panel that has the html button tag that calls the printer dialog and the iframe. This was enough to get only the map printed. One thing that may be necessary to allow this is that you need to use subdomains to trick the browser into thinking the iframe host and the document host are on the same domain-- I had already worked with the mapping company and our local hosting company to get that part done. The only thing left to do is to get the iframe to hold a selected zoom status of the map when I click to open the printer dialog. I will post another question for opinions on how to get an asp panel to freeze its view, or whatever other trick might enable that.

Related

IE11 Automation via Excel VBA - Forms

This is part 2 from my original post here. So now once logged in, I have to make two clicks to display the information I'm ultimately trying to scrape. I cannot seem to figure out the proper way to drill down to get to the clicks to work. It is all buried within a form. The 1st image shows the form structure. The 2nd image shows all of the code where I'm trying to get to the Current Situation link below the Supervisor span. I had to use the following (as you see from my previous post) to get IE to stay connected so not sure if that has any impact:
Dim objIE As Object
Set objIE = GetObject("new:{D5E8041D-920F-45e9-B8FB-B1DEB82C6E5E}")
In an attempt to automate the Current Situation tab click, I've tried the following with no luck (with and without the 0)
objIE.document.getElementById("1617")(0).Click
I'm more interested in getting educated in addition to getting an answer. Is there a method to drilling down into information within a form? I was under the impression that ALL the elements of a webpage were pulled in during loading. So is this not truly an element in my minimal understanding with webpage automation?
As a note, I do have to click Supervisor to get the tree below it to display. Thanks in advance for your help!
UPDATE:
Ok a major oversight here I think. Based on my previous post, the login functions perfectly. But once logged in, a new window gets created. So I believe that is the challenge, right? It can't find any of these IDs or Elements because it's looking at the original IE object, not the new window. So how do I get it to activate/access the new window? Sorry I missed that earlier!
Method getElementById returns a single element, not a collection, unlike for example getElementsByClassName (look at "Element" vs "Elements" in method name). Therefore (0) or any other index of collection should not be used.
Correct syntax is:
objIE.document.getElementById("1617").Click
For pop-up windows try this:
Dim wURL As String
Dim myWindow As Object
For Each myWindow In CreateObject("Shell.Application").Windows
wURL = myWindow.LocationURL
If InStr(wURL, "constant_part_of_popup_window_link") <> 0 Then
'do stuff
myWindow.Quit
Exit For
End if
Next myWindow
For accessing an element within iFrame:
myWindow.document.getElementById("frameMainMenu").contentWindow.document.getElementById("1617").Click

Get HTML Element from WebBrowser Control in VB

I am using Visual Studio 2010 and coding in VB.
I have a form with a WebBrowser object in it.
I have control over the HTML on the pages.
I need the user to be able to select a portion of text in the WebBrowser object and save it.
In the save process, I need to capture the selected text, the ID of the HTML element that contains the selected text, and the URL. Then when the user goes back to that page, the program can place an icon on the page right next to that object.
I do not have any code to accomplish this yet, I do not have much experience with the WebBrowser object so I didn't even know where to start. I can however give the names of my form objects and inform you that all of the html elements have an ID.
Form : frmContent
WebBrowser : wbContent
I am guessing that I could even record coordinates of the selected portion of text instead of the html element. Either way, the final outcome needs to save a list of these locations paired with their url so that for every saved "bookmark", there will be an icon placed on the page of that url in the saved location of the page.
Found that this works rather well for me.
GetElementFromPoint(e.ClientMousePosition)
I was able to set this to a variable and then able to get the attributes from the element.
Dim bookmarkElement = wbContent.Document.GetElementFromPoint(e.ClientMousePosition)
Dim elementID = bookmarkElement.GetAttribute("id").ToString()
Problem solved.

Auto-submit HTML Form using VB in Access 2007

I'm at my wit's end on this one.
Part of a project I'm working on requires interaction with an HTML form to bring up the correct page on an external web-based tool. I've managed to make this form accept entered variables and be generated on the fly using document.write, but what I haven't been able to do reliably is trigger the 'Submit' action in a way that will not throw off Error 91.
So far, I've been using a simple getelementbyid.click call... Here's a list of a few things I've tried to get it to trigger:
TestLoop:
Pause (1)
BrowserControl.document.getelementbyid("Submit").click
On Error Goto TestLoop
*(The 'Error Loop' tactic didn't really work at all.)
Pause (3)
BrowserControl.document.getelementbyid("Submit").click
(This actually works the best, but because different PCs might have different hardware specs and open applications that might slow it down, what works for me hasn't been working for another tester. If I make it TOO long, I end up adding additional delay to a form I'm already worried about being too slow.)
<script type="text/javascript">
window.onload = function(){
document.getElementById('Submit').click();;
}
</script>
(Embedding an auto-trigger in the generated HTML, frustratingly, works OUTSIDE of the embedded web browser control, but not inside it.)
Private Sub wb_NavigateComplete2(ByVal pDisp As Object, URL As Variant)
If Me.BrowserControl.Document.URL= "about:blank" Then
BrowserControl.document.getelementbyid("Submit").click
End If
End Sub
(For some insane reason, using debug.print I found that it's saying the navigation is complete before it's actually complete, so this didn't work at all.)
I may have missed a few... I've been attacking this from a bunch of different angles. The trick is that I have to use the HTML form to interact with this system that I don't have admin priveledges on, so changing how the information is recieved isn't really an option.
My last train of thought was to see if I could mimic a FORM submission using straight VB, bypassing the need for a 'click' event, but it's been exceptionally difficult to search for things related to HTML FORM interactions with Access 2007 Forms. :P
Any assistance would be greatly appreciated!
Well, after 7 months of testing and thousands of activations in that time, splitting the 'work' seems to have done the trick.
Form_Open: Initialises the Browser Object and sets its address to about:blank
Form_Current: Calls a formula that 'draws' the web form using Document.Write, then enters a loop...
TestLoop:
BrowserControl.document.getelementbyid("Submit").click
On Error Goto TestLoop

How to get the first visible html element in a WebBrowser?

I'm using the .Net 4.0 WebBrowser (from System.Windows.Controls). In my application the user can modify the html data and the webbrowser shows an update. The application should then automatically scroll to the previous element that was displayed.
I'm using WPF / c# 4.0 on windows 7.
In detail:
In the code I call WebBrowser.NavigateToString(htmlData1);
the user scrolls to an arbitrary position
the user changes (somehow) the html document
now I would like to find (and remember) the first html element that is displayed
I call WebBrowser.NavigateToString(htmlData2);
now I would like to use the memorized element to automatically scroll the html document (I know that there is IHTMLElement.scrollIntoView() to do this)
So the question is: How do I get the first visible html element in a WebBrowser?
You may say that the updated html will not have the memorized element anymore. Right. But I have timestamps in the document and will use the memorized html element to find the best position in the new html doc.
I think I found the right method to use. There are actually two possibilities to retain the scroll position when the document is being refreshed.
Assume the following members:
WebBrowser _browser;
HTMLDocument HtmlDoc { get { return (HTMLDocument)_browser.Document; } }
(1) If the document didn't really change (in my example only changed in style) I use the current scroll position to auto-scroll after an update:
before refresh:
_scrollPos = ((IHTMLElement2)(HtmlDoc.documentElement)).scrollTop;
after refresh:
HtmlDoc.parentWindow.scrollTo(0, _scrollPos);
(2) If the document has changed I use the left upper element of my document (that is of known structure)
before refresh:
IHTMLElement el = HtmlDoc.elementFromPoint(50, 0);
Do some magic with that el (requires knowledge of the doc) and remember some string that can be used to search for the best element after the update.
string beforeRefresh = fromElement(el);
after refresh use the remembered string and search for the best html element in the reloaded html doc.
IHTMLElement newEl = fromString(beforeRefresh);
newEl.scrollIntoView(true);
So the actual method I was missing was elementFromPoint(). The rest is "custom logic".

How can I track changes in content on an HTML page after page has loaded

I'm wracking my brain on this one.
After an HTML document loads in a browser, I want to be able to monitor
the page in case any content on it changes for any reason.
Is there a Javascript function with which I can track 'what has
changed' on the webpage. This should be irrespective of the type of content on the HTML page.
I have two examples for you to ponder on:
Ex1:
Say in an HTML document there are two select boxes s1 and s2.
The items list in s2 depends on selections in s1 (page is not
refreshed — that is, s2 is loaded through Ajax or something).
So after the HTML page loads I need to get a notification whenever s2
is populated...
Ex2:
Say, in an HTML page, there's a link, Onclicking which a light pop-up
div is created with some text.
How can I capture the content of this dynamic pop-up?
In all this discussion, I'm not taking into account any particular
format of HTML...the HTML content can be anything...I just need
to keep tracking if any content changes after the page loads...
Ideally I need to achieve this using JavaScript (client-side
scripting).
How can I achieve this?
You can keep track of changes in a textbox using onkeyup. This will tell you every time someone makes a change in a given textbox.
This could potentially fire alot of events. However, using onblur won't necessarily tell you about changes in the textbox and onchange's browser coverage is spotty at best.
If you are using AJAX, you could setup the response function to handle a home grown "event listening" system. So after the response does what it needs to do, it could call any methods that were registered with it, passing in the response text when necessary.
So from your examples above, in Ex1, when the AJAX returns from S1, it would load S2, then call a method saying S2 had changed. In Ex2, when the new AJAX returns the DIV's contents, after loading it into the DIV, it call a different method (or possibly the same depending on what your trying to do) and alerts it that the DIV has new contents.
You could set your "watcher" script as a timer, running a diff function on the current document.body.innerHTML and a stored version captured on load. Depending on how fast the diff will run will give you an idea on what timer interval to use.
This may not capture changes in form elements, but for those, it's easier to loop through all form elements in every form on the page.
Here's someone's diff function I found on Google: http://snowtide.com/jsdifflib