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,
ATL is an AxtiveX container, not a web browser control. If you create an instance of it wihout nothing, you will get nothing.
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.
?
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
' ========================================================================================
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.
?
Sorry, but if you don't show all the code I don't know what you're doing.
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
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
' ========================================================================================
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 :) )
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:".
Another thing: "MSHTML:" only works when you pass it as the caption when you create an instance of the ATL control.
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.
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
Quote
Object Call oDoc.Write( vHtml )
This is wrong. The parameter for the Write method must be a safe array of type VT_VARIANT.
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.
When late bound it works fine but i let's forget that for a moment.
I really really tried everything via atl, even your includes and interfaces.
There really may be something different about the dispatch (oWB).
Can you please check with MSHTML code on ATL?
Like i said, using plain html it always worked fine.
Edit:
Goal is a reference to the document, i tried the interfaces because late binding also didn't work, i don't want the interfaces if not needed, just the document dispatch.
I really don't understand what you mean with MSHTML code and plain html.
I don't have anything that uses ATL since I wrote my OLE container, and much less using OBJECT CALL, that I always have disliked deeply. Write a compilable example and I will look at it.
I am using MSHTML to initialize the webcontrol *instead* of using about:blank.
AB requires 'doevents' to complete while MSHTML seems not.
While at first a document for these may not be the same, not sure, but i accomplished this fine using OLECON code but not with atl.
When the MSHTML initializes the webcontrol it was ready to obtain the document object right away and i could then write ordinary html to it (without the MSHTML/xml stuff up front).
So in fact i am trying to get me a document handle from the MSHTML container.
In ATL this keeps failing, i now have an ATL fragment of yours where i have made several kind of attempts to get me a document handle.
Maybe i should abandon this anyway, the document may not be of the same breed??
Anyway, i do have the atl project, i could pm it if you think it's still a valid attempt?
You can't get a reference to the document until it has been fully loaded. Attempting to do it will result in a null reference.
If you use my OLE container and the AddWebBrowserControl method of my CWindow class then you don't need to navigate to about:blank and pump windows events because the method does it for you, not because it is not needed.
Sigh..., now i see..
Call me persistant..., i have the idea of handling the messages to the windows i have listed via the messagepump:
Internet Explorer_Hidden
Internet Explorer_Hidden
Shell Embedding
Button
Button
Shell DocObject View
Internet Explorer_Server
I mean that i could simply prevent the messages for other parts of the program by not handling these messages.
In fact that's what i wanted in the first place, no intervening during the load of a webcontrol.
I am not sure it's allowed to post pone certain messages and allow the WC's messages, maybe the messagepump get's mixed up.. (i don't think so)
Disabling a form is very bad.., later :)