Link to home
Start Free TrialLog in
Avatar of garyLynn7
garyLynn7Flag for United States of America

asked on

Programmaticaly copy text from a text box to a Windows Web Form Control

I have a VB.Net 2005 Windows form application that takes text input into a text box control, performs some processing and adds some basic html encoding, and displays the results in a second text box control.

I also have a web browser control on the form, wich I want to use as an option to display the results from the second text box, but in an html view.

I want to establish a template for the browser control to include the head and body tags (standard stuff), and then paste the html coded text from the second text box into the template at the appropriate place (form tag?); once that has happend, display the text in the browser control for the end user.

Any ideas about how one may set this up?
Avatar of Jens Fiederer
Jens Fiederer
Flag of United States of America image

Sure.....you can assign innerHTML of elements in the DOM to whatever the contents of your input were.

As an example, if your browser control were called "web", then

Ctype(web.Document, mshtml.HTMLDocument).body.innerHTML = "<input type=text>"

would make your entire document just a single text box.
Avatar of garyLynn7

ASKER

Thanks for the reply.  So I change the document to the text box output?

In other words, "<input type=textbox1.text>"

I am moving the text from the text box into the web browser control, and by CType(web.Document, mshtml.HTMLDocument).Body.innerHTML = "<input type=textbox1.text>",
I'll be presenting the entire text box content into the body of the web document, correct?

Thanks for the clue - I'll check it out!

Gary

"presenting the entire text box content into the body of the web document"

No, not what I meant.  I was using
      "<input type=text>"
as an example of what your user might have typed INTO the textbox, HTML to create a simple empty input text box.  What they typed in, of course, could be as complex as you want.

The whole thing would be more like
    dim newHTML as string = textbox1.text
    Ctype(web.Document, mshtml.HTMLDocument).body.innerHTML = newHTML


Of course, my example replaces the entire document, which is by no means necessary.  If your original document were more complex, but had a DIV with an id of "replaceme", you could do
  Ctype(web.Document, mshtml.HTMLDocument).getElementById("replaceme") =
                  newHTML
instead, replacing ONLY the contents of the DIV.
Ahhhh! Thank you for the clarification!  Likely what will occur is that the client will place a chunk of text - it is intended that it will be some type of rtf or .doc formatted for web presentation - to be converted from it's current format, removing the extraneous preformatted portions; then converts character entities to numeric equivalent, and display result in text box #2.

Now this text may have a couple of html tags embedded, including breaks and or paragraphs; but should never include head, body, form opening and closing tags.

I now want the client to actually have a look at the converted text in a browser window, but it should already have the default html head, body and form tags in place.

So possibly the solution would be to:
a. have a template available which has the default html in place, and place the text from text box 2 into that template, then show it in the browser, or
b. send the converted text directly to the browser control. However, with this idea I am assuming that there would need to be a default document object which contains the default tags, and the text could paste directly into the document at the best location, say in a div tag.

Either way,  (continuing with your example) web.document would indicate the browser control called "web" contains a document which is an html document, and in that document I want to find the specific element with the id of "replaceme", then place the contents from textbox2 into that specific div element.

So it appears my work should be in creating a default template or html document, assigning identifiable id's, and then addressing the new text to that element.

OK, so if a default document can be set to the web browser control, then there should only be one function to place the new text into the document as it resides in the browser; whilst copying out to a template then calling the template into the browser would require a bit more code, yet may have more advantages if I wanted to add different presentations through a series of pre-formatted templates.

I'll follow-up today with how this works out, and thanks for the great assistance!

Gary
Sounds like you've got the idea....try it out and tell me how it goes!

OK, so far not getting too far.

Seems VS2005 designer doesn't like the Web.Document part of the code fragment.
This is the sub I'm trying to use, and its part of a forms load event.

Any further suggestions?

Imports System.Web
Public Class WebView

    Private Sub WebView_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
        Dim RtbOutput1 As New rtbOutput
        Dim newHTML As String = RtbOutput1.text
        CType(Web.Document, mshtml.HTMLDocument).body.innerHTML = newHTML
        Me.WebBrowser1.Show()
    End Sub

End Class


Thanks!
Well, on MY form I called the web browser control "web".  I am betting that you called it something ELSE on your form, such as maybe "WebBrowser1".

Have you tried WebBrowser1.Document?
Hi there, yes I did get to that, and in fact have found a few ways to display the new web control - specifically embedding it in a modal form. That seems to work OK.

The issue is still how to get the text from the text box  into the html page (preferred method) and then display in the browser.

Here's what I have so far:

An .html page (HTMLPage1.html) is in my app with default elements, and div tag ( <div id="replacedText">)

A form with navBar and link item to open web control,
a modal form with an embedded web control.

When the navBar link item is pressed, the following code is executed and the modal form
is loaded.

Dim rtbOutput1 As New rtbOutput
        rtbOutput1 = HoneyConverterModule1.RtbOutput1
        CType(WebView.WebBrowser1.Document, mshtml.HTMLDocument).body.innerHTML = rtbOutput1.Text
Me.WebBrowser1.Show()

And also attempted to target the Div id:  .GetElementByid("replacedText") = rtbOutput1
but both attempts throw a casting error:

Unable to cast object of type 'System.Windows.Forms.HtmlDocument' to type 'mshtml.HTMLDocument'.

Suggestions?

Thanks for  all your help!

Gary
Oh yes, forgot to mention the fact that in the above code, the target document isn't being refered to,
and looking at what is being refered to - rtbOutput1 text box -- it wouldn't have an "element id" per se.

So that is the heart of the issue:

text box content to the html page template, then to the browser control for viewing.

Thanks!

Gary
Hello, another change to this: I worked out the casting error by changing the mshtml.HTMLDocument to HtmlDocument, which is being referenced by the object Windows.Forms.HtmlDocument.
Apparently this is a feature of the Web namespace for VS 2005, and mshtml is a previous library.

From what I've read so far, some folks prefer the older reference and object model as being more feature rich and ultimately more desirable, it also means it will probably have less support in the future.

Anyway, now the problem is an error raised indicating an object reference not set to an instance of the object.
The error is being generated at the same location in code, the object casting param seems to be the issue now, and possibly because this is trying to work with a modal form.

I don't know for sure yet.

Still trying to figure that one out.

Suggestions?

Gary
OK - looks like we were using different forms (as you figured out) of browser controls.

What is the new code where the error occurs?
It's still being thrown by the cast.  Now it's and object reference not set to an instance of the object.
 Here's the entire sub.  I've including an error trap to display a message box, which allows just a bit of gracefulness when displaying the error!

  Private Sub browserView_LinkPressed(ByVal sender As Object, ByVal e As DevExpress.XtraNavBar.NavBarLinkEventArgs) Handles browserView.LinkPressed

        Dim _rtbOutput1 As New rtbOutput
        _rtbOutput1 = HoneyConverterModule1.RtbOutput1
        Try
            CType(WebView.WebBrowser1.Document, HtmlDocument).Body.InnerHtml = _rtbOutput1.Text
        Catch ex As Exception
            MessageBox.Show(ex.Message)
        End Try
        WebView.Show()

    End Sub


It's basicly the same code except for the change in type, but I can't quite tell from the stack trace which object is haveing the problem. I'm assuming the problem is coming from the module that contains the text box controls as reference in the declaration in the code.
Here's the stack trace:

   at MyHoneysConverter.frmMain.browserView_LinkPressed(Object sender, NavBarLinkEventArgs e) in C:\Users\Gary\Desktop\PROJECTS\MyHoneysProjects\MyHoneysConverter\MyHoneysConverter\frmMain.vb:line 19
   at DevExpress.XtraNavBar.NavBarItem.RaiseLinkEvent(Object linkEvent, NavBarItemLink link)
   at DevExpress.XtraNavBar.NavBarItem.RaiseLinkPressed(NavBarItemLink link)
   at DevExpress.XtraNavBar.NavBarItem.RaiseLinkPressedCore(NavBarItemLink link)
   at DevExpress.XtraNavBar.NavBarControl.RaiseLinkPressed(NavBarItemLink link)
   at DevExpress.XtraNavBar.ViewInfo.NavBarViewInfo.RaisePressedEvent(NavBarState state, NavBarHitInfo hit)
   at DevExpress.XtraNavBar.ViewInfo.NavBarViewInfo.DoPress(NavBarHitInfo hitInfo, NavBarState pressedState)
   at DevExpress.XtraNavBar.ViewInfo.NavBarViewInfo.OnMouseDown(MouseEventArgs e)
   at DevExpress.XtraNavBar.NavBarControl.OnMouseDown(MouseEventArgs ev)
   at System.Windows.Forms.Control.WmMouseDown(Message& m, MouseButtons button, Int32 clicks)
   at System.Windows.Forms.Control.WndProc(Message& m)
   at DevExpress.XtraNavBar.NavBarControl.WndProc(Message& m)
   at System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m)
   at System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)
   at System.Windows.Forms.NativeWindow.DebuggableCallback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
   at System.Windows.Forms.UnsafeNativeMethods.DispatchMessageW(MSG& msg)
   at System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(Int32 dwComponentID, Int32 reason, Int32 pvLoopData)
   at System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(Int32 reason, ApplicationContext context)
   at System.Windows.Forms.Application.ThreadContext.RunMessageLoop(Int32 reason, ApplicationContext context)
   at System.Windows.Forms.Application.Run(ApplicationContext context)
   at Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase.OnRun()
   at Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase.DoApplicationModel()
   at Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase.Run(String[] commandLine)
   at MyHoneysConverter.My.MyApplication.Main(String[] Args) in 17d14f5c-a337-4978-8281-53493378c1071.vb:line 81
   at System.AppDomain.nExecuteAssembly(Assembly assembly, String[] args)
   at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
   at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
   at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
   at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
   at System.Threading.ThreadHelper.ThreadStart()

Any ideas or suggestions would be most welcome!!

Gary

This should be easy to debug with a breakpoint.  Roll out the code a little to pinpoint the problem, like replacing
            CType(WebView.WebBrowser1.Document, HtmlDocument).Body.InnerHtml = _rtbOutput1.Text
with
            Dim doc as HtmlDocument = CType(WebView.WebBrowser1.Document, HtmlDocument)
            Dim htmlString as string = _rtbOutput1.Text
            doc.Body.InnerHtml = htmlString
Put a breakpoint on the first of these lines and step through it, checking where the error occurs.




OK, yes that brought the issue to this line:
doc.Body.InnerHtml = htmlString
Object Reference not set to an instance of an object.

Since I declared _rtbOutput1 as new rtbOutput (text box in module), that object should exist.

However, after setting the break point at the first declaration and running through debug, it's the line
doc.body.InnerHtml = htmlString
which is indicating the object ref problem.

Here's the code:
Dim _rtbOutput1 As New rtbOutput
        Dim doc As HtmlDocument = CType(WebView.WebBrowser1.Document, HtmlDocument)
        Dim htmlString As String = _rtbOutput1.Text
        doc.Body.InnerHtml = htmlString
        WebView.Show()

So let me add further project definition here:

A module contains the text boxes RtbInput1 and Rtboutput1.  These are infact extended RTF boxes, extended to make use of a spell checker.

This module is dropped onto the main form for display.
The main form contains a nav bar with link items.
A second Form contains the web control.
A link item pressed event is used to display the second form which contains the web control, and at the same time transfer the text from Rtboutput1 into the web control.

So the idea is to take the text from module1.rtboutput1, and place it in the web browser control.
Or, place the text into an existing html file, and then display the file in the browser control.

Suggestions?
Thanks!

Gary
Just before executing
          doc.Body.InnerHtml = htmlString
what are the values (you can use quickwatch) of
          htmlString
          doc
          doc.Body
          doc.Body.InnerHtml

?
Sorry, what is quickwatch?

Locals is showing this information:

htmlString is empty,

doc is displaying the message below:

 recieving a COM error for mshtml.HTMLDocument and shows this message:
at System.Windows.Forms.UnsafeNativeMethods.IHTMLDocument2.GetDomain() at System.Windows.Forms.HtmlDocument.get_Domain()

doc.body is dispalying the message "nothing",

doc.body.innerHtml is not in the locals.

Make any sense?
Ah, it looks like you are trying to CHANGE the body before it HAS a body.

You can't do the
      doc.Body.InnerHtml = 'stuff
until doc.Body as actually been LOADED.

Load something, ANYTHING, into that browser window before you start to modify it.
I'm able to display an html page and its text, but when I try to run the code block that we've been working with, I get the same error.

You just SAID that
   doc.Body
was nothing.

"Nothing"doesn't HAVE an innerHTML (doc.Body is an "object reference", and when it is "nothing" then it is not set to an instance of an object - just like the message said).

So whether you are able to display a page or not, at THAT POINT of the code you cannot set doc.Body.innerHTML.

You have to
      doc.Body.InnerHtml = 'stuff
AFTER doc.Body actually has a value.

Try, for example, after
        WebView.Show()
OK, we're halfway there!  I was able to use body. innerHtml, and that actually moved the text to the browser control.

However, when I tried to target the div id, intellisence says: Expression is a value and therefore cannot be the target of an assignment.

I tried this code:

Dim rtbOutput1 As New rtbOutput
        rtbOutput1 = HoneyConverterModule1.RtbOutput1
        CType(WebView.WebBrowser1.Document, HtmlDocument).GetElementById("replacedText") = rtbOutput1.Text        
        WebView.Show()

Getting closer!
Try:

CType(WebView.WebBrowser1.Document, HtmlDocument).GetElementById("replacedText").innerHTML = rtbOutput1.Text  
By the way, I do understand that nothing means something - in this case letting me know something should be in place.

My apologies, but I tend to comment out loud on occasion, so I likely appear as a moron at times.

Essentially what I needed to do was separate the two functions and initiate each with a separate sub -

In this case I placed code in the load event of the frmWebView to load a default htm page, and then open the form with a button click on the main form.
I then placed the code for moving the text box content to the browser control in a separate button sub, and was able to successfully load the text from the textbox into the browser control.

But that's just half the work.

Now that it's this far along, the next step is to get the text into the the existing html page's Div tag.

Thanks!
ASKER CERTIFIED SOLUTION
Avatar of Jens Fiederer
Jens Fiederer
Flag of United States of America image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
The innerHtml replaces the entire document.  Therefore it doesn't place the text in the html page, it seems to just over write the exiting document entirely with the text box info.

So This took care of the intellisence issue, but it isn't allowing the text to be placed into the div tag.

Also, I'll be working toward changing the open form and actual move routines since it doesn't make sense to have the client first open an empty browser, then send the text box contents in a seperate button click.

And, if the browser isn't open and the client clicks the button to send the text to the browser, it'll throw an object ref error. That's understandable since the object hasn't been instantiated yet.

Still plenty to do with this.

Thanks!
After some study and experimenting, I understand at least that the text - while not actually copied to the html template --  is being styled there, also I've done a bit of inline styling with it, and it definatley correctly sets fonts and colors and the like.

It's strange to have the control displaying a bunch of text, and there is no source in it to view, apparently the text IS the source in the browser viewer.

Another issue is how to open the modal viewer, load the template, and then load the text from the text box in one control click. Apparently the web browser control has to be loaded and active before it will accept and display new text from the output text box.  So far the only thing I've come up with is to open it when the parent form loads, and then set it's (web viewer) visible property to false.
When the end user does the button click to view the browser, all that's happenning is the text is moved to the viewer, and then the viewer's visible property is returned to true.

It's a bad fix for the moment, but gives me a place to work from!

Anyway, thanks for the great assistance.

Gary
> The innerHtml replaces the entire document.

Only SOMETIMES.

Really, the innerHtml replaces the entire ELEMENT.
When the element happens to be the entire body, your statement is true.
But when you replace the innerHtml of a DIV element that you get with getElementById, then ONLY the content of that element is replaced.

You'll get a feel for this as you play with it more.
Thanks for that.  I'm really interested in templateing this in various ways. I've done some stuff with xml and xlst and really like the power there, also.

I'm also interested in understanding DOM more as well.  I know the W3C has some stuff on there site that should be helpful.

Again, thanks for all the help!