• Welcome to Powerbasic Museum 2020-B.
 

News:

Forum in repository mode. No new members allowed.

Main Menu

MSHTML - use it over and over?

Started by Edwin Knoppert, September 04, 2011, 05:56:23 PM

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

Edwin Knoppert

I am using an ATL window, how can i use your MSHTML/xml/html example over and over with new content.
The idea is that the control is created without progid or mshtml syntax.
I could initialize it first but my goal is not to do that.

Thanks,

José Roca

ATL is an AxtiveX container, not a web browser control. If you create an instance of it wihout nothing, you will get nothing.

Edwin Knoppert

My 2nd attempt is to load a dummy html fragment, this is shown fine.
Now i would like to access the document object but it fails.
My ATL code obtains the dispatch from the ATL control and usually i can obtain the document just fine.
I normally use late binding but since i could not get a reference i implemented the interfaces (for now).
Here is some test code:

    Local pIWebBrowser2 As IWebBrowser2
    Local pIHTMLDocument2 As IHTMLDocument2
    pIWebBrowser2 = oWB
    ? Str$( ObjPtr( pIWebBrowser2 ) ) 
    pIHTMLDocument2 = pIWebBrowser2.Document
    ? Str$( ObjPtr( pIHTMLDocument2 ) )


oWB is the dispatch and like i said i usually obtain the document via: Object Get oWB.Document To v
Any idea why pIWebBrowser2 remains empty?
I have seen your code which does nearly the same but via the document ready event.
I would not like to use that part this way.

The control is created and shows the MSHTML, i click a button to obtain the dispatch and then the document.
?


José Roca

To get the dispatch interface of the instance of the Web Browser control hosted in an ATL window you have to use something like:


' ========================================================================================
FUNCTION AtlAxGetDispatch (BYVAL hWndControl AS DWORD) AS IDispatch

   LOCAL hr AS LONG
   LOCAL pUnk AS IUnknown
   LOCAL pDispatch AS IDispatch
   LOCAL IID_IDispatch AS GUID

   ' Get the IUnknown of the OCX hosted in the control
   hr = AtlAxGetControl(hWndControl, pUnk)
   IF hr <> 0 THEN EXIT FUNCTION

   ' Query for the IDispatch interface
   IID_IDispatch = GUID$("{00020400-0000-0000-C000-000000000046}")
   hr = pUnk.QueryInterface(IID_IDispatch, BYVAL VARPTR(pDispatch))
   IF hr = %S_OK THEN FUNCTION = pDispatch

END FUNCTION
' ========================================================================================


Edwin Knoppert

#4
But i do have a reference to this dispatch (not shown in my code), obtaining the document fails when i use MSHTML, it's fine with ordinary html.
Combine your function with mine and that's all i do.

?

José Roca

Sorry, but if you don't show all the code I don't know what you're doing.

Edwin Knoppert


    Local oWB           As Dispatch 
    Local v             As Variant
    Local pIWebBrowser2 As IWebBrowser2
    Local pIHTMLDocument2 As IHTMLDocument2

    oWB = AtlAxGetDispatch( hWnd )
    If IsObject( oWB ) Then

        pIWebBrowser2 = oWB
        ? Str$( ObjPtr( pIWebBrowser2 ) ) 
        pIHTMLDocument2 = pIWebBrowser2.Document
        ? Str$( ObjPtr( pIHTMLDocument2 ) )

' Object Call oWB.document To v
' ? Str$( Variant#( v ) )

        End If

        oWB = Nothing

    End If


Where  ObjPtr( pIWebBrowser2 )  returns 0

José Roca

If the code not show is correct, it should work.

In the following example, this works:


   LOCAL pWB AS IWebBrowser2
   LOCAL oWB AS DISPATCH
   oWB = OC_GetDispatch(hCtl)
   pWB = oWB
   MSGBOX STR$(OBJPTR(pWB)) & STR$(OBJPTR(oWB))



#COMPILE EXE
#DIM ALL
%UNICODE = 1

' // Include files for external files
%USEWEBBROWSER = 1            ' // Use the WebBrowser control
#INCLUDE ONCE "CWindow.inc"   ' // CWindow class

' // Identifier
%IDC_WEBBROWSER = 101

' ########################################################################################
' Main
' ########################################################################################
FUNCTION WinMain (BYVAL hInstance AS DWORD, BYVAL hPrevInstance AS DWORD, BYVAL lpszCmdLine AS WSTRINGZ PTR, BYVAL nCmdShow AS LONG) AS LONG

   ' // Set process DPI aware
'   SetProcessDPIAware

   ' // Create an instance of the class
   LOCAL pWindow AS IWindow
   pWindow = CLASS "CWindow"
   IF ISNOTHING(pWindow) THEN EXIT FUNCTION

   ' // Create the main window
   pWindow.CreateWindow(%NULL, "AddWebBrowser Template", 0, 0, 0, 0, 0, 0, CODEPTR(WindowProc))
   ' // Set the client siz
   pWindow.SetClientSize 600, 350
   ' // Center the window
   pWindow.CenterWindow

   ' // Add a WebBrowser control
   LOCAL hCtl AS DWORD
   LOCAL bstrURL AS WSTRING

   bstrURL = "http://www.jose.it-berater.org/smfforum/index.php"
   ' // Create the control
   hCtl = pWindow.AddWebBrowserControl(pWindow.hwnd, %IDC_WEBBROWSER, bstrURL, NOTHING, 0, 0, pWindow.ClientWidth, pWindow.ClientHeight)

   LOCAL pWB AS IWebBrowser2
   LOCAL oWB AS DISPATCH
   oWB = OC_GetDispatch(hCtl)
   pWB = oWB
   MSGBOX STR$(OBJPTR(pWB)) & STR$(OBJPTR(oWB))
   

   ' // Default message pump (you can replace it with your own)
   pWindow.DoEvents(nCmdShow)

END FUNCTION
' ########################################################################################

' ========================================================================================
' Main callback function.
' ========================================================================================
FUNCTION WindowProc (BYVAL hwnd AS DWORD, BYVAL uMsg AS DWORD, BYVAL wParam AS DWORD, BYVAL lParam AS LONG) AS LONG

   STATIC hInstance AS DWORD        ' // Instance handle
   STATIC lpc AS CREATESTRUCT PTR   ' // Pointer to the creation parameters
   STATIC pWindow AS IWindow        ' // Reference to the IWindow interface

   SELECT CASE uMsg

      CASE %WM_CREATE
         ' // Pointer to the creation parameters
         lpc = lParam
         ' // Instance handle
         hInstance = @lpc.hInstance
         ' // Get a reference to the IWindow interface from the CREATESTRUCT structure
         pWindow = CWindow_GetObjectFromCreateStruct(lParam)
         EXIT FUNCTION

      CASE %WM_SYSCOMMAND
         ' // Capture this message and send a WM_CLOSE message
         ' // Note: Needed with some OCXs, that otherwise remain in memory
         IF (wParam AND &HFFF0) = %SC_CLOSE THEN
            SendMessage hwnd, %WM_CLOSE, 0, 0
            EXIT FUNCTION
         END IF

      CASE %WM_COMMAND
         SELECT CASE LO(WORD, wParam)
            CASE %IDCANCEL
               ' // If the Escape key has been pressed...
               IF HI(WORD, wParam) = %BN_CLICKED THEN
                  ' // ... close the application by sending a WM_CLOSE message
                  SendMessage hwnd, %WM_CLOSE, 0, 0
                  EXIT FUNCTION
               END IF
         END SELECT

      CASE %WM_SIZE
         IF wParam <> %SIZE_MINIMIZED THEN
            ' // Resize the control
            pWindow.MoveWindow GetDlgItem(hwnd, %IDC_WEBBROWSER), 0, 0, pWindow.ClientWidth, pWindow.ClientHeight, %TRUE
         END IF

      CASE %WM_DESTROY
         ' // End the application
         PostQuitMessage 0
         EXIT FUNCTION

   END SELECT

   ' // Pass unprocessed messages to Windows
   FUNCTION = DefWindowProc(hwnd, uMsg, wParam, lParam)

END FUNCTION
' ========================================================================================


Edwin Knoppert

I just tried your code and indeed it works fine.
Though i don't think you have an ATL example present.
Maybe we need a different interface first (i mean maybe there is a difference in dispatches here?)

Anyway one thing i wanted to test today was the immediate html replacement (remember we spoke about the 'doevents' stuff?)
MSHTML seems to be handy for direct writing without the need for waiting until a document is present like:


   [b]bstrURL = MyHTMLCode()[/b]
   ' // Create the control
   hCtl = pWindow.AddWebBrowserControl( _
          pWindow.hWnd _
        , %IDC_WEBBROWSER _
        , bstrURL _
        , Nothing _
        , 0 _
        , 0 _
        , pWindow.ClientWidth _
        , pWindow.ClientHeight _
    )

   LOCAL pWB AS IWebBrowser2
   Local oWB As Dispatch
   oWB = OC_GetDispatch(hCtl)
   pWB = oWB
   'MSGBOX STR$(OBJPTR(pWB)) & STR$(OBJPTR(oWB))
   Local oDoc As Dispatch
   oDoc = pWB.document()
   
    Local v As Variant
    Local vHtml As Variant
    [b]vHtml = MyHTMLCode2() [/b]   
   
    v = "about:blank"
    Object Call oDoc.Open( v ) 
    Object Call oDoc.Write( vHtml ) 
    Object Call oDoc.Close() 
    oDoc = Nothing


For testing i have two MSHTM html fragments, the 2nd seems to be loaded properly.
I still would like an atl solution or suggestion, it brings less code and project enhancements to me.

(At least i was 'forced' to do my first test using PwrDev 3 which is a unicode tool only, no issues found yet :) )

José Roca

Quote
For testing i have two MSHTM html fragments, the 2nd seems to be loaded properly.

But you don't show them... Remember that you have to prefix it with "MSHTML:".

José Roca

Another thing: "MSHTML:" only works when you pass it as the caption when you create an instance of the ATL control.

José Roca

Quote
    v = "about:blank"
    Object Call oDoc.Open( v ) 
    Object Call oDoc.Write( vHtml ) 
    Object Call oDoc.Close() 

What does this? You don't open a blank page; you navigate to it with Navigate2, and you have to retrieve the document reference to this new page.

Edwin Knoppert

#12
But every thing works fine except i can't get a reference to the document interface via atl when i use MSHTML.
Via OLECON it works fine, looks like it can not find the IID or so but i copied it from your files, so i don't see why it should not get a reference to IWebbrowser2.

Code i used is here, i took it from a topic of yours somewhere:

Function MyHTMLCode() As String

   Local s As String

   S =  "MSHTML:<?xml version=""1.0""?>"
   s += "<!DOCTYPE HTML PUBLIC ""-//W3C//DTD XHTML 1.0 Transitional//EN"" ""http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"">" & $CrLf
   s += "<html xmlns=""http://www.w3.org/1999/xhtml"">" & $CrLf
   s += "<head>" & $CrLf
   s += "<title>Image Test</title>" & $CrLf
   s += "</head>" & $CrLf
   s += "<body scroll=" & $Dq & "auto" & $Dq & " style=" & $Dq & "MARGIN: 0px 0px 0px 0px" & $Dq & " >" & $CrLf
   s += "Hello <b>world</b>" & $CrLf
   s += "</body>" & $CrLf
   s += "</html>" & $CrLf
   
   Function = s

End Function


The 2nd document is ordinary html:


Function MyHTMLCode2() As String

   Local s As String

   S =  ""
   s += "<!DOCTYPE HTML PUBLIC ""-//W3C//DTD XHTML 1.0 Transitional//EN"" ""http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"">" & $CrLf
   s += "<html xmlns=""http://www.w3.org/1999/xhtml"">" & $CrLf
   s += "<head>" & $CrLf
   s += "<title>Image Test</title>" & $CrLf
   s += "</head>" & $CrLf
   s += "<body scroll=" & $Dq & "show" & $Dq & " style=" & $Dq & "MARGIN: 100px 0px 0px 0px" & $Dq & " >" & $CrLf
   s += "AAAAAAAAAAAAAAAAAAAAAAAAaHello <b>world</b>" & $CrLf
   s += "</body>" & $CrLf
   s += "</html>" & $CrLf
   
   Function = s

End Function


Note that this actually works fine and even without the wait-for-ready and doevents stuff.

The ATL also shows the initial MSHTML part fine but the lack of a document handle is the problem to place a new html part.
(And yes, the MSHTML is passed as 'progid' part (the caption).


v = "about:blank"
    Object Call oDoc.Open( v ) 
    Object Call oDoc.Write( vHtml ) 
    Object Call oDoc.Close()


Read about this today on MSDN, it seems ok though.. (?)
The open is required when the first document is done loading.
The url is not optional and AB was suggested, it clears the existing document.

Edit:
Must have been wrong, this is ok as well:
Object Call oDoc.Open()

http://msdn.microsoft.com/en-us/library/aa752628(v=vs.85).aspx

José Roca

Quote
Object Call oDoc.Write( vHtml ) 

This is wrong. The parameter for the Write method must be a safe array of type VT_VARIANT.

José Roca

Quote
The open is required when the first document is done loading.
The url is not optional and AB was suggested, it clears the existing document.

No, it does not. It opens a NEW WINDOW.