Solved

Need help with IID_IHTMLElement

Posted on 2001-08-07
15
1,452 Views
Last Modified: 2007-11-27
I found this code in newsgroup. The author made comment in russian. Don't understand anything. But this code fails on:
pdisp->QueryInterface (IID_IHTMLElement, (LPVOID *) &pItem);

And i'm new to this but i relly want to know what it does.

Please help me.

Regards
Andreas
   








#include <windows.h>
#include <mshtml.h>
#include <exdisp.h>

int main (void)
{
    CLSID clsid;
    LPUNKNOWN punk;
    IWebBrowser2 *pWB;
    IHTMLDocument2 *pHTML;
    IHTMLElementCollection *pElement;
    IHTMLElement *pItem;
    LPDISPACH pdisp;
    DISPID dispid, dispidNamed = DISPID_PROPERTYPUT;
    DISPPARAMS dispparams;
    UINT uArgErr;
    VARIANTARG vArg;
    VARIANT_BOOL bBusy;
    VARIANT varName, varIndex, var;
    BSTR bstr;

    OleInitialize (NULL);
    CLSIDFromProgID (OLESTR("InternetExplorer.Application"), &clsid);
    CoCreateInstance (clsid, NULL, CLSCTX_SERVER, IID__IUnknown,
                      (LPVOID *) &punk);
    punk->QueryInterface (IID_IWebBrowser2, (LPVOID *) &pWB);
    punk->Release();
    pWB->put_Visible (TRUE);
    BSTR bstrVal = SysAllocString (L"C:\\TEMP\\DHTML.HTM");
    var.vt = VT_I4;
    var.lVal = 0;
    pWB->Navigate (bstrVal, &var, &var, &var, &var);
    SysFreeString (bstrVal);
    do
    {
        Sleep (500);
        pWB->get_Busy (&bBusy);
    }
    while (bBusy);
    pWB->get_Document (&pdisp);
    pWB->Release();
    pdisp->QueryInterface (IID_IHTMLDocument2, (LPVOID *) &pHTML);
    pdisp->Release();
    pHTML->get_all (&pElements);
    varName.vt = VT_BSTR;
    varName.bstrVal = SysAllocString (L"mytitle");
    varIndex.vt = VT_I4;
    varIndex.lVal = 0;
    pElements->item (varName, varIndex, &pdisp);
    SysFreeString (varName.bstrVal);
//fails here
    pdisp->QueryInterface (IID_IHTMLElement, (LPVOID *) &pItem);
    pdisp->Release();
    bstr = SysAllocString (L"Hello from C++!");
    pItem->put_innerText (bstr);
    SysFreeString (bstr);
    pItem->Release();
    OleUninitialize ();
}
0
Comment
Question by:andla
  • 8
  • 5
  • 2
15 Comments
 
LVL 30

Expert Comment

by:Axter
ID: 6361738
You should do a test to see if pdisp is Null.
Example:
pElements->item (varName, varIndex, &pdisp);
if (pdisp == NULL)
{
//report error here, and back out
}
   SysFreeString (varName.bstrVal);
//fails here
   pdisp->QueryInterface (IID_IHTMLElement, (LPVOID *) &pItem);
0
 
LVL 30

Expert Comment

by:Axter
ID: 6361748
Every time you do a QueryInterface(IDD_???,(LPVOID*) &pSomeVar),
you should check to see if the variable (pSomeVar) is NULL.
0
 
LVL 1

Author Comment

by:andla
ID: 6362220
I'm sorry i took an unfiltered code. I have done some fixes and it should work now. I don't se any variables that is NULL after a function call. Please test this code and help me find the error.



#include <windows.h>
#include <mshtml.h>
#include <exdisp.h>

int main (void)
{
   CLSID clsid;
   LPUNKNOWN punk=NULL;
   IWebBrowser2 *pWB;
   IHTMLDocument2 *pHTML;
   IHTMLElementCollection *pElement;
   IHTMLElement *pItem;
   IDispatch *pdisp;
   DISPID dispid, dispidNamed = DISPID_PROPERTYPUT;
   DISPPARAMS dispparams;
   UINT uArgErr;
   VARIANTARG vArg;
   VARIANT_BOOL bBusy;
   VARIANT varName, varIndex, var;
   BSTR bstr;

   OleInitialize (NULL);
   CLSIDFromProgID (OLESTR("InternetExplorer.Application"), &clsid);
   CoCreateInstance (clsid, NULL, CLSCTX_SERVER, IID_IUnknown,
                     (LPVOID *) &punk);
   punk->QueryInterface (IID_IWebBrowser2, (LPVOID *) &pWB);
   punk->Release();
   pWB->put_Visible (TRUE);
   BSTR bstrVal = SysAllocString (L"C:\\TEMP\\DHTML.HTM");
   var.vt = VT_I4;
   var.lVal = 0;
   pWB->Navigate (bstrVal, &var, &var, &var, &var);
   SysFreeString (bstrVal);
   do
   {
       Sleep (500);
       pWB->get_Busy (&bBusy);
   }
   while (bBusy);
   pWB->get_Document (&pdisp);
   if (pdisp == NULL)
{
return 0;
}

   pWB->Release();
   pdisp->QueryInterface (IID_IHTMLDocument2, (LPVOID *) &pHTML);
   pdisp->Release();
   pHTML->get_all (&pElement);
   varName.vt = VT_BSTR;
   varName.bstrVal = SysAllocString (L"mytitle");
   varIndex.vt = VT_I4;
   varIndex.lVal = 0;
   pElement->item (varName, varIndex, &pdisp);
   SysFreeString (varName.bstrVal);
//fails here
   pdisp->QueryInterface (IID_IHTMLElement, (LPVOID *) &pItem);
   pdisp->Release();
   bstr = SysAllocString (L"Hello from C++!");
   pItem->put_innerText (bstr);
   SysFreeString (bstr);
   pItem->Release();
   OleUninitialize ();
}



Cheers
Andla
0
Free Tool: Path Explorer

An intuitive utility to help find the CSS path to UI elements on a webpage. These paths are used frequently in a variety of front-end development and QA automation tasks.

One of a set of tools we're offering as a way of saying thank you for being a part of the community.

 
LVL 1

Author Comment

by:andla
ID: 6363335
I run the debugger but i will put up the null checker routines laiter. To bad there are not much source code on this. :-(

/Andla
0
 
LVL 1

Expert Comment

by:RideOn
ID: 6364214
seems to be interesting code...
let's see
before the exception occurs, the pdisp is NULL
0
 
LVL 1

Expert Comment

by:RideOn
ID: 6364220
pdisp is NULL after this Line:

  pElement->item (varName, varIndex, &pdisp);

so, somthing has to be wrong here
0
 
LVL 1

Author Comment

by:andla
ID: 6365196
I think the mytitle is missing but i don't know how to make a reverse enginering on this. ?


 varName.vt = VT_BSTR;
  varName.bstrVal = SysAllocString (L"mytitle");
  varIndex.vt = VT_I4;
  varIndex.lVal = 0;


/Andla
0
 
LVL 30

Expert Comment

by:Axter
ID: 6366439
Exactly what are you trying to do with this code?
I might be able to help you get to the end result if I know what you want out of it.
0
 
LVL 30

Expert Comment

by:Axter
ID: 6366587
#include <windows.h>
#include <mshtml.h>
#include <exdisp.h>

#pragma warning(disable:4786)
#include <vector>
#include <string>

int function1 (void)
{
     CLSID clsid;
     LPUNKNOWN punk=NULL;
     IWebBrowser2 *pWB = NULL;
     IHTMLDocument2 *pHTML = NULL;
     IHTMLElementCollection *pElement = NULL;
     IDispatch *pdisp = NULL;
     DISPID  dispidNamed = DISPID_PROPERTYPUT;
     VARIANT_BOOL bBusy;
     VARIANT varName, varIndex, var;
     BSTR bstr;

     OleInitialize (NULL);
     CLSIDFromProgID (OLESTR("InternetExplorer.Application"), &clsid);
     CoCreateInstance (clsid, NULL, CLSCTX_SERVER, IID_IUnknown, (LPVOID *) &punk);
     punk->QueryInterface (IID_IWebBrowser2, (LPVOID *) &pWB);
     punk->Release();
     pWB->put_Visible (TRUE);
     BSTR bstrVal = SysAllocString (L"www.axter.com");
     var.vt = VT_I4;
     var.lVal = 0;
     pWB->Navigate (bstrVal, &var, &var, &var, &var);
     SysFreeString (bstrVal);
     do
     {
       Sleep (500);
       pWB->get_Busy (&bBusy);
     }
     while (bBusy);
     pWB->get_Document (&pdisp);
     if (pdisp == NULL)
     {//Report error here
          return 0;
     }

     pWB->Release();
     pdisp->QueryInterface (IID_IHTMLDocument2, (LPVOID *) &pHTML);
     pdisp->Release();
     pHTML->get_all (&pElement);
     long NumItems = 0;
     pElement->get_length(&NumItems);
     if (!NumItems)
     {//Report error here
          return 0;
     }
     std::vector<std::string> ListOfTagNames;
     std::vector<std::string> ListOfInnerHTML;
     std::vector<std::string> ListOfOuterHTML;
     for (int item_number_index = 0;item_number_index < NumItems;item_number_index++)
     {
          varName.vt = VT_I4;
          //varName.bstrVal = SysAllocString (L"A Valid Name");//Only use this if you know the name of the object
          varName.lVal = item_number_index;//Get item via index number (zero based number)
          varIndex.vt = VT_I4;
          varIndex.lVal = 1;
          IDispatch *pdisp2 = NULL;
          if (pElement->item (varName, varIndex, &pdisp2) != S_OK)
          {//Report error here
               return 0;
          }
          if (pdisp2 == NULL)
          {//Report error here
               return 0;
          }
          //SysFreeString (varName.bstrVal);//Only use this if used above
          IHTMLElement *pItem = NULL;
          pdisp2->QueryInterface (IID_IHTMLElement, (LPVOID *) &pItem);
          pdisp2->Release();
          if (pItem == NULL)
          {//Report error here
               return 0;
          }
          CString TempVariable;
     

          pItem->get_tagName(&bstr);
          TempVariable = bstr;
          std::string szTagName = (LPCTSTR)TempVariable;
          ListOfTagNames.push_back(szTagName);

          pItem->get_innerHTML(&bstr);
          TempVariable = bstr;
          std::string szInnerHTML = (LPCTSTR)TempVariable;
          ListOfInnerHTML.push_back(szInnerHTML);

          pItem->get_outerHTML(&bstr);
          TempVariable = bstr;
          std::string szOuterHTML = (LPCTSTR)TempVariable;
          ListOfOuterHTML.push_back(szOuterHTML);

          bstr = SysAllocString (L"Hello from C++!");
          pItem->put_innerText (bstr);
          SysFreeString (bstr);
          pItem->Release();
     }
     OleUninitialize ();
     return 1;
}

0
 
LVL 30

Accepted Solution

by:
Axter earned 50 total points
ID: 6366609
The above posted code is a working example of the code you posted.

I modified a few items.
I deleted all the unused variables.
I modified the following line:
BSTR bstrVal = SysAllocString (L"www.axter.com");
I made it point to an actual web page.  Previously it was pointing to a local file on your hard drive.  If this file did not exist, the rest of the code does not work.

I commented out the following line:
varName.bstrVal = SysAllocString (L"mytitle");

You can only use that line if you know the name of the tag element that you're trying to get.
I added the following line:
varName.vt = VT_I4;
varName.lVal = item_number_index;

By changing the varName to a number, you can make the query get the element by number instead of by name.
If you don't know the tag name, then you should query for the element via index number.  The number is a zero based number.

I added a loop to the code so that it pulls all the elements on the given page, and adds the elements properties to the following variables:
std::vector<std::string> ListOfTagNames;
std::vector<std::string> ListOfInnerHTML;
std::vector<std::string> ListOfOuterHTML;

After exiting the loop, the above variables should contain all the properties of all the elements that were found in the select web page.

By the way, I beleave the following code only works if you're view a local page on your hard drive.
Since the code I posted is not viewing a local page, the code will not be able to modify it.
bstr = SysAllocString (L"Hello from C++!");
pItem->put_innerText (bstr);
SysFreeString (bstr);


I beleave the function of the code is to modify the text inside a specfic tag.
So if you tried to retrieve the following "TITLE" tag:
"<TITLE>Axter Inc. ***Quality Software***</TITLE>"

The code should change it to the following:
"<TITLE>Hello from C++!</TITLE>"

That is, it should change it if it were pointing to a page that it could modify. (Local Hard drive file)
0
 
LVL 30

Expert Comment

by:Axter
ID: 6366622
To get additional information on any IDD_??? item, just remove the IDD_ and put the rest of the text in the VC help index box.  It should list information on the item.

Example:
pdisp->QueryInterface (IID_IHTMLDocument2, (LPVOID *) &pHTML);
The above code uses IID_IHTMLDocument2.
If you want to get information on what the QueryInterface() function will return using IID_IHTMLDocument2, you can look in the VC++ help index for "IHTMLDocument2".
It'll list all the methods available for the object.

You can also get more information on the object by search the VC++ include file directory for the IDD_????

To do that, you can use the following method.

1.  Click EDIT on the main menu of Visual C++ IDE
2.  Select "FIND-IN-FILES"
3.  In the "Find What" field, enter "IID_IHTMLDocument2" (with out the quotes)
4.  Change the "In Folder" field to point to the VC++ directory.
Example: "C:\Program Files\Microsoft Visual Studio\VC98"
5.  Select the "Look In Subfolders" field so that it is set.
6.  Make sure the "In Files/File Types" field is set to the following:
 "*.c;*.cpp;*.cxx;*.tli;*.h;*.tlh;*.inl;*.rc"
7.  Click the find button.

That should list all the VC++ source code for the object.  Which will give you some insigt as to how it works.

Good luck, and let me know if you have any questions.
0
 
LVL 1

Author Comment

by:andla
ID: 6367156
Hi!

I have tested your new code.
Let se if i got this right.

pElement->get_length(&NumItems);

This is the number of tags found in the webpage.
If this is the case then i don't know how it is count.
If i count my self i get more than seven.
I could figure out this myself but appreciate your help.

Nice homepage :-)
I saw that you used AolPress to create it. I like this editor to bad they don't do any upgrades.

Thanks for your help.

Cheers
Andla.
0
 
LVL 30

Expert Comment

by:Axter
ID: 6371489
>>I saw that you used AolPress to create it. I like this
>>editor to bad they don't do any upgrades.
Yes, I like it too.  I try using other editors, but I always end up going back to AolPress.

>>This is the number of tags found in the webpage.
That's right.

>>If i count my self i get more than seven.
It's counting the tags in the FRAME page.  Did you view the frame page?

The frame page only has seven.
I'll try posting the seven tags on my next comment, but I don't know if it'll show up, because EE some times has problems displaying tags in the comment block.
0
 
LVL 30

Expert Comment

by:Axter
ID: 6371533
I'm wrong, and you're right.  It does have more then seven tags.

HTML
HEAD
TITLE
!--
FRAMESET COLS
FRAME SRC=
FRAME SRC=

NOFRAMES
BODY
P

The last three tags were not counted (NOFRAMES, BODY, P).

I believe the last three tags were not counted because they're only used for a No-Frame browser.
0
 
LVL 1

Author Comment

by:andla
ID: 6373243
Ok Axter you have been very helpful.

BTW about the Aolpress i discovered that if you copy an image on the screen 'Ctrl+C' and paste it in AolPress 'Ctrl+V' it will automatically paste the bitmap image in AolPress and convert it to jpeg and you don't even have to name them. If you create a tutorial with screen shots you can do this in notime. I use irfanview to take screen shots every second and save it to a folder.

Cheers
Andla
0

Featured Post

Free Tool: Site Down Detector

Helpful to verify reports of your own downtime, or to double check a downed website you are trying to access.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Introduction This article is a continuation of the C/C++ Visual Studio Express debugger series. Part 1 provided a quick start guide in using the debugger. Part 2 focused on additional topics in breakpoints. As your assignments become a little more …
This article shows you how to optimize memory allocations in C++ using placement new. Applicable especially to usecases dealing with creation of large number of objects. A brief on problem: Lets take example problem for simplicity: - I have a G…
The goal of the video will be to teach the user the difference and consequence of passing data by value vs passing data by reference in C++. An example of passing data by value as well as an example of passing data by reference will be be given. Bot…
The viewer will learn how to use the return statement in functions in C++. The video will also teach the user how to pass data to a function and have the function return data back for further processing.

856 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question