0

I'm working with MSHTML API lately, and I find it very inconvenient. I'm more used to WinAPI then COM programming, so maybe it's just me, but consider the following example of querying the rectangle of an element;

Expectations:

RECT rc;
hr = element2->GetElementRect(&rc);

Reality:

CComPtr<IHTMLRect> rect;
hr = element2->getBoundingClientRect(&rect);
if(FAILED(hr))
    return hr;
if(!rect)
    return E_FAIL;

long left, right, top, bottom;
hr = rect->get_left(&left);
if(FAILED(hr))
    return hr;
hr = rect->get_right(&right);
if(FAILED(hr))
    return hr;
hr = rect->get_top(&top);
if(FAILED(hr))
    return hr;
hr = rect->get_bottom(&bottom);
if(FAILED(hr))
    return hr;

Am I missing something?

My question: are there any wrappers for this API? Surely, smart pointers such as CComPtr make things much easier, but still, I feel like struggling with the API.

Paul
  • 6,061
  • 6
  • 39
  • 70

1 Answers1

3

One way is to use the #import directive and use the native C++ compiler COM support classes instead of ATL (such as _com_ptr_t<>).

Your code then boils down to 2 lines of code:

MSHTML::IHTMLElement2Ptr element;

MSHTML::IHTMLRectPtr rect = element->getBoundingClientRect();
RECT rc = { rect->left, rect->top, rect->right, rect->bottom };

Import the mshtml stuff like this:

#pragma warning(push)
// warning C4192: automatically excluding '<xyz>' while importing type library 'mshtml.tlb'
#pragma warning(disable: 4192)
#import <mshtml.tlb>
#pragma warning(pop)

All the boiler-plate code is hidden because #import automatically creates property wrappers and methods doing HRESULT checking.

klaus triendl
  • 1,237
  • 14
  • 25
  • Looks very promising, thanks! I've never seen the usage of #import before. Is this API documented anywhere? What happens on an error, does it throw an exception? Do the variables get cleaned upon destruction? – Paul Jan 08 '14 at 19:32
  • You find `#import` in the [MSDN documentation](http://msdn.microsoft.com/en-us/library/8etzzkb6.aspx). [`_com_ptr_t`](http://msdn.microsoft.com/en-us/library/417w8b3b.aspx) is a smart pointer, so it properly cleans up in any case. – klaus triendl Jan 08 '14 at 20:03
  • Yep, that's exactly what I was looking for, thanks! To answer my last unanswered question - "What happens on an error, does it throw an exception?" - yes, a `_com_error`. – Paul Jan 08 '14 at 22:27