Monday, January 08, 2007

IHTMLFormElement::get_elements fails

Don't blow your head, you have this situation:
you have a valid form element and you want to access its elements.

IHTMLFormElement* pForm = ...

one way to do it is by:

HRESULT IHTMLFormElement::get_elements(IDispatch **p)

and the code looks like the following:

IDispatch* pDisp = NULL;

IHTMLElementCollection* pFormColl = NULL;
HRESULT hr = pDisp->QueryInterface(IID_IHTMLElementsCollection, (void**)&pFormColl);

but you get pFormColl having NULL value and hr = 0x80004002 which means

The QueryInterface method did not recognize the requested interface. The interface is not supported.

Google'ing it a bit you get plenty of similar behaviour. The workaround is to use

HRESULT IHTMLElement::get_children(IDispatch **p)

The hint is given by MSDN description for this method:

To access all elements contained in a form, call QueryInterface on IHTMLFormElement and request an IHTMLElement interface. Use the IHTMLElement::children property of the IHTMLElement interface to retrieve a collection of all elements in the form

So, translated into code:

IHTMLElement* pElem = NULL;
pFormElem->QueryInterface(IID_IHTMLElement, (void**)&pElem);

IHTMLElementCollection* pChildrenElem = NULL;

After all, this should be your preferred way since MSDN also says that you do not get actually all the form elements if you use IHTMLFormElement::get_elements :

The collection retrieved by the IHTMLFormElement::get_elements property does not include input type=image elements from a form

So, in order to obtain a IHTMLFormElement children elements, use IHTMLElement method instead.