DHTML and MFC
-
I am developing a MFC (VC++ 6) application which should be able to display some dynamic HTML content. The HTML page has some static elements and some dynamic elements so I want to use DHTML. I want to use a static HTML template and let my MFC application fill in the dynamic content. To display the HTML page I will use the IE browser component (or the MFC wrapper from Gary R. Wheeler http://www.codeproject.com/miscctrl/simplebrowserformfc.asp) The problem which I have is: how can I access the dynamic HTML content (DOM) of my template and fill in my content using MFC. Is there a DOM/DHTML parser? I found a lot of information in the internet and in the MSDN library, but I could not find a good startig point. Can anyone give me some hints or direct me into the correct direction? At least a starting point would help me a lot. Thanks in advance.
-
I am developing a MFC (VC++ 6) application which should be able to display some dynamic HTML content. The HTML page has some static elements and some dynamic elements so I want to use DHTML. I want to use a static HTML template and let my MFC application fill in the dynamic content. To display the HTML page I will use the IE browser component (or the MFC wrapper from Gary R. Wheeler http://www.codeproject.com/miscctrl/simplebrowserformfc.asp) The problem which I have is: how can I access the dynamic HTML content (DOM) of my template and fill in my content using MFC. Is there a DOM/DHTML parser? I found a lot of information in the internet and in the MSDN library, but I could not find a good startig point. Can anyone give me some hints or direct me into the correct direction? At least a starting point would help me a lot. Thanks in advance.
Hi, So are you saying that you want to Navigate() to your static HTML page (template) and then you want to start populating the contents of the page using MFC? Andy
-
I am developing a MFC (VC++ 6) application which should be able to display some dynamic HTML content. The HTML page has some static elements and some dynamic elements so I want to use DHTML. I want to use a static HTML template and let my MFC application fill in the dynamic content. To display the HTML page I will use the IE browser component (or the MFC wrapper from Gary R. Wheeler http://www.codeproject.com/miscctrl/simplebrowserformfc.asp) The problem which I have is: how can I access the dynamic HTML content (DOM) of my template and fill in my content using MFC. Is there a DOM/DHTML parser? I found a lot of information in the internet and in the MSDN library, but I could not find a good startig point. Can anyone give me some hints or direct me into the correct direction? At least a starting point would help me a lot. Thanks in advance.
Thanks for your answer Andy, it's exactly what you say. Today I have found a solution. I can get a IHTMLDocument pointer. So I have access to the HTML code. But that leads me to another question. How can I insert an image into the HTML code which is in memory and not on HD. Must I save the image to a file in order to insert it into the HTML document or is there an other way?
-
Thanks for your answer Andy, it's exactly what you say. Today I have found a solution. I can get a IHTMLDocument pointer. So I have access to the HTML code. But that leads me to another question. How can I insert an image into the HTML code which is in memory and not on HD. Must I save the image to a file in order to insert it into the HTML document or is there an other way?
Hi, Yes indeed IHTMLDocumentPtr is the starting point into the DOM. One thing that will help in the long run is to import the HTML type library - thus getting Visual Studio to generate wrappers around the numerous interfaces and methods. It wraps using smart pointers - so no QueryInterface/Releases to take care of. e.g. insert the following into either your header/implementation file
#import "C:\Windows\system32\mshtml.tlb" no_auto_exclude
This will generate two files, mshtml.tlh and mshtml.tli, in your project directory. The first is a header file, the next the implementation. With this done, here is a simple DHTML process from within MFC to get an element from the page...
void CWebDlg::OnDocumentCompleteExplorer1(LPDISPATCH pDisp, VARIANT FAR* URL)
{
USES_CONVERSION;MSHTML::IHTMLDocument2Ptr spDoc(m\_ctlWeb1.GetDocument()); // This is the WebBrowser control if (spDoc) { MSHTML::IHTMLDocument3Ptr spDoc3 = spDoc; if (spDoc3) { MSHTML::IHTMLElementPtr spElem2 = spDoc3->getElementById(\_bstr\_t("idSpan1")); if (spElem2) { CString strText = W2T(spElem2->innerText); spElem2->innerText = \_bstr\_t("Hello There"); } } }
}
See how we can easily get the different interfaces of the object. The wrapper is doing the QI under the covers when we do a simple assignment. Plus the smart pointer will release that reference once the object goes out of scope. You can also easily create elements at will, e.g. here we create a BGSOUND element and append it to the DOM document.
MSHTML::IHTMLDocument2Ptr spDoc(m_ctlWeb1.GetDocument());
if (spDoc)
{
MSHTML::IHTMLElementPtr spElem = spDoc->createElement(_T("BGSOUND"));
if (spElem)
{
MSHTML::IHTMLBGsoundPtr spBG = spElem;
if (spBG)
{
CString strURL = _T("http://xyzxyz/snd/newalert.wav");
spBG->put_src((bstr_t)strURL);MSHTML::IHTMLDOMNodePtr spBody = spDoc->body; MSHTML::IHTMLDOMNodePtr spNode2Add = spBG; // append new element to BODY spBody->appendChild(spNode2Add); } }
}
To answer your question about inserting an image - I not too sure, something at the back of my mind does ring a bell about embedding IMG data in an HTML page. I'll see if I can find out. But for now I would think about saving the image to the file-system and then referencing the IMG src tag to the location. If you have any questions about DHTML or using MFC to generate DHTML I'll be happy to answer them. Hope this help
-
Hi, Yes indeed IHTMLDocumentPtr is the starting point into the DOM. One thing that will help in the long run is to import the HTML type library - thus getting Visual Studio to generate wrappers around the numerous interfaces and methods. It wraps using smart pointers - so no QueryInterface/Releases to take care of. e.g. insert the following into either your header/implementation file
#import "C:\Windows\system32\mshtml.tlb" no_auto_exclude
This will generate two files, mshtml.tlh and mshtml.tli, in your project directory. The first is a header file, the next the implementation. With this done, here is a simple DHTML process from within MFC to get an element from the page...
void CWebDlg::OnDocumentCompleteExplorer1(LPDISPATCH pDisp, VARIANT FAR* URL)
{
USES_CONVERSION;MSHTML::IHTMLDocument2Ptr spDoc(m\_ctlWeb1.GetDocument()); // This is the WebBrowser control if (spDoc) { MSHTML::IHTMLDocument3Ptr spDoc3 = spDoc; if (spDoc3) { MSHTML::IHTMLElementPtr spElem2 = spDoc3->getElementById(\_bstr\_t("idSpan1")); if (spElem2) { CString strText = W2T(spElem2->innerText); spElem2->innerText = \_bstr\_t("Hello There"); } } }
}
See how we can easily get the different interfaces of the object. The wrapper is doing the QI under the covers when we do a simple assignment. Plus the smart pointer will release that reference once the object goes out of scope. You can also easily create elements at will, e.g. here we create a BGSOUND element and append it to the DOM document.
MSHTML::IHTMLDocument2Ptr spDoc(m_ctlWeb1.GetDocument());
if (spDoc)
{
MSHTML::IHTMLElementPtr spElem = spDoc->createElement(_T("BGSOUND"));
if (spElem)
{
MSHTML::IHTMLBGsoundPtr spBG = spElem;
if (spBG)
{
CString strURL = _T("http://xyzxyz/snd/newalert.wav");
spBG->put_src((bstr_t)strURL);MSHTML::IHTMLDOMNodePtr spBody = spDoc->body; MSHTML::IHTMLDOMNodePtr spNode2Add = spBG; // append new element to BODY spBody->appendChild(spNode2Add); } }
}
To answer your question about inserting an image - I not too sure, something at the back of my mind does ring a bell about embedding IMG data in an HTML page. I'll see if I can find out. But for now I would think about saving the image to the file-system and then referencing the IMG src tag to the location. If you have any questions about DHTML or using MFC to generate DHTML I'll be happy to answer them. Hope this help
Thanks for the detailed answer. I think now I have the starting point I need. But do I need the wrappers if I don't add new HTML elements? My plan is to change existing HTML elements only. So If I get a pointer like IHTMLElement and change the properties of the object that should be no problem? The MSHTML documentation in the MSDN library seems also to be very good. Thanks for your help. :)
-
Thanks for the detailed answer. I think now I have the starting point I need. But do I need the wrappers if I don't add new HTML elements? My plan is to change existing HTML elements only. So If I get a pointer like IHTMLElement and change the properties of the object that should be no problem? The MSHTML documentation in the MSDN library seems also to be very good. Thanks for your help. :)
Hi, I would always use the wrappers as it will ease the time and readablity of your code. As an example, here is some code without the use of the wrappers:
IUnknown* lpUnk = m_pSite->GetObjectUnknown();
if ( lpUnk != NULL )
{
HRESULT hr;IHTMLDocument2\* pHTMLDocument2; hr = lpUnk->QueryInterface(IID\_IHTMLDocument2, (void \*\*)&pHTMLDocument2); if ( SUCCEEDED( hr ) ) { BSTR bstrColor = SysAllocString( buff ); VARIANT varColor; varColor.vt = VT\_BSTR; varColor.bstrVal = bstrColor; hr = pHTMLDocument2-> put\_bgColor( varColor ); pHTMLDocument2->Release(); }
}
and now the same code with the use of the wrappers:
MSHTML::IHTMLDocument2Ptr spDoc(m_pSite->GetObjectUnknown());
if (spDoc)
{
spDoc->bgColor = bstr_t("#ffffff");
}As you can see it is substantially cleaner. And this was a simple example. You can also call any Javascript functions (from MFC) that are in the HTML page (I can show you how if you need to) And also, you can implement an event handler at the MFC side such that, for example, an onclick HTML event will cause the web browser control to call into your application. Hope this helps, Andy
-
Hi, I would always use the wrappers as it will ease the time and readablity of your code. As an example, here is some code without the use of the wrappers:
IUnknown* lpUnk = m_pSite->GetObjectUnknown();
if ( lpUnk != NULL )
{
HRESULT hr;IHTMLDocument2\* pHTMLDocument2; hr = lpUnk->QueryInterface(IID\_IHTMLDocument2, (void \*\*)&pHTMLDocument2); if ( SUCCEEDED( hr ) ) { BSTR bstrColor = SysAllocString( buff ); VARIANT varColor; varColor.vt = VT\_BSTR; varColor.bstrVal = bstrColor; hr = pHTMLDocument2-> put\_bgColor( varColor ); pHTMLDocument2->Release(); }
}
and now the same code with the use of the wrappers:
MSHTML::IHTMLDocument2Ptr spDoc(m_pSite->GetObjectUnknown());
if (spDoc)
{
spDoc->bgColor = bstr_t("#ffffff");
}As you can see it is substantially cleaner. And this was a simple example. You can also call any Javascript functions (from MFC) that are in the HTML page (I can show you how if you need to) And also, you can implement an event handler at the MFC side such that, for example, an onclick HTML event will cause the web browser control to call into your application. Hope this helps, Andy
Thanks again :) I will try the wrappers. Since I only want to do some basic things I will not use JavaScript. The simple browser wrapper for the MS Web Browser control which I use is very good. It already offers message handlers. So this should be easy. You helped me a lot. :-D