TWebBrowser getElementByID

Hi, I'm having trouble working with TWebBrowser in RAD Studio Xe8 C++ builder.

I can't figure out how to access elements on a webpage, like reading the content of an input field...
All the relevant examples that I've found are in Delphi, I tried using this WebBrowser1->Document->getElementByID("input1")
But the method isn't a member of Document which type is IDispatch and I don't know what that is, Can I access the methods that I'm looking for through this IDispatch class? or am I on the wrong path?

Any simple code would be nice.
Thank you in advance
You need to cast your IDispatch interface into an IHTMLDocument2.
I couldn't find any proper documentation for C++ builder, but maybe you can use the delphi ones. All the properties and functions are the same.
http://www.cryer.co.uk/brian/delphi/twebbrowser/twebbrowser_properties.htm
http://delphidabbler.com/tips/56
Thank you for the fast response, but I already tried it and couldn't get it to work, what Am I doing wrong?

1
2
IHTMLDocument2 *Doc;
Doc=(IHTMLDocument2)w->Document;


"Cannot create instance of abstract class IHTMLDocument2"
Difficult to say without C++ Builder, but I would try this:
1
2
3
4
5
IHTMLDocument2 *Doc = dynamic_cast<IHTMLDocument2 *>(WebBrowser1->Document);
if (Doc != nullptr)
{
   // use Doc
}
'Cannot cast from "di_IDispatch"to "IHTMLDocument2 *" '
I can't believe no one have ever tried this before, at least on the first 5 pages of google
I found this German website with some code. Have a look, maybe with Google translate....
http://www.bytesandmore.de/rad/index.htm?http://www.bytesandmore.de/rad/cpp/snipp/sc08019.php
It seems almost everything is overly complicated in C++, in Delphi or .Net it would be easy.
I hope this helps at least one person out there.
Thank you Thomas for the link, I'll investigate it, Since I was already onto something, after 2 days of flounder and blunder I went on to see if it works, and it did.
It's not the most elegant/Straightforward way but it could work on any COM object.

The following code changes the HTML code of an element of the page.
I didn't do the best comments but I hope it helps

Must load the page beforehand otherwise, the GetIDsOfNames generates an error. Idk why
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
DISPID Id;
WCHAR * Name = L"getElementByID";// Method name

WebBrowser1->Document->GetIDsOfNames
(
IID_NULL,              // Must be null
&Name,                 // Name of the method we want
1,                     // Number of parameters we want to pass
LOCALE_SYSTEM_DEFAULT, //Seems to work just fine
&Id                    // The value of the method ID WE WANT!
);


DISPPARAMS DispParams;            // Parameters structure to pass to the getElementByID
                                  // through the following Invoke method
DispParams.cArgs=1;               // Number of parameters to pass
DispParams.cNamedArgs=0;          // Number of named parameters to pass
DispParams.rgdispidNamedArgs=NULL;//We don't want to pass arguments by name,
				  //just by position (in rgvarg array)

DispParams.rgvarg=new VARIANT[1];            // Allocate 1 variant for 1 parameter
DispParams.rgvarg[0].vt=VT_BSTR;             // Tells thet we want to pass a string by value
DispParams.rgvarg[0].bstrVal=L"txt_Username";// String we want to pass

VARIANT *ReturnParams =new VARIANT;
unsigned int ReturnInt;

WebBrowser1->Document->Invoke
(
Id,                   // got from GetIDsOfNames
IID_NULL,             // Must be
LOCALE_SYSTEM_DEFAULT,// Seems to work!
DISPATCH_METHOD,      // We want to call a method 'getElementById'
&DispParams,          // Parameters to pass to getElementById
ReturnParams,         // Contains a Element in the webpage in a DISPATCH interface
NULL,                 // Returns Exceptions, For simplicity we wont bother
&ReturnInt            // Only if there's an error in passed parameters
		      // DISP_E_TYPEMISMATCH or DISP_E_PARAMNOTFOUND.
);


IDispatch *Element;
Name=L"OuterHtml";       // The property we want to change the value of
Element=ReturnParams->pdispVal;

Element->GetIDsOfNames
(
IID_NULL,              // Must be!
&Name,                 // Name of the propery
1,                     // Number of parameters in this case the 'value'
LOCALE_SYSTEM_DEFAULT, // Seems to work
&Id                    // Returned Property ID
);


DispParams.cArgs=1;         	         // Number of values we want to pass
DispParams.cNamedArgs=0; 	         // 0 named params
DispParams.rgdispidNamedArgs=NULL;       // No named params
DispParams.rgvarg[0].vt=VT_BSTR;         // Pass the parameter by value
DispParams.rgvarg[0].bstrVal=L"EUREKA!"; // Put it in the corresponding field

// The rest is similar ...
Element->Invoke
(
Id,
IID_NULL,
LOCALE_SYSTEM_DEFAULT,
DISPATCH_PROPERTYPUT,
&DispParams,
NULL,
NULL,
&ReturnInt    // Or NULL because we don't expect a result
);


Sources:
GetIDsOfNames:
https://msdn.microsoft.com/en-us/library/windows/desktop/ms221306(v=vs.85).aspx

Invoke:
https://msdn.microsoft.com/en-us/library/windows/desktop/ms221479(v=vs.85).aspx

Passing paramerters:
https://msdn.microsoft.com/en-us/library/windows/desktop/ms221653(v=vs.85).aspx

DISPPARAMS structure:
https://msdn.microsoft.com/en-us/library/windows/desktop/ms221416(v=vs.85).aspx

HtmlElement methods and properties:
https://msdn.microsoft.com/en-us/library/system.windows.forms.htmlelement(v=vs.110).aspx
I feel a bit silly now that I've tried the german code:

This one finds the input element named "Username" and puts "Hohenheim" in it.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
IHTMLDocument3 *Doc;
IHTMLInputElement *Elem;

WebBrowser1->Document->QueryInterface(IID_IHTMLDocument3,(void**)&Doc);

IHTMLElementCollection *ElementsCol;
Doc->getElementsByName(L"Username",&ElementsCol);
VARIANT Name,Index;

Name.vt=VT_I4;
Name.llVal=0;

IDispatch * DispElement;
ElementsCol->item(Name,Index,&DispElement);

DispElement->QueryInterface(IID_IHTMLInputElement,(void**)&Elem);

Elem->put_value(L"Hohenheim");
Topic archived. No new replies allowed.