0

Web オブジェクトとそのプロパティにアクセスするために、IHTMLElement および IHTMLElement2 スクリプト インターフェイスを使用してきました。現在、要素が占有するクライアント領域から、境界線とスクロール バーが占める領域を引いたものを知りたいという状況にあります。メソッドClientRectangle()を持つHTMLDocumentクラスに出くわしました。そのドキュメントは、私たちが見ているものと非常によく似ています。可能であれば、このメソッドにアクセスする方法が本当にわかりません。

この HTMLDocument クラスのインスタンスを作成し、そのメソッドにアクセスすることは可能ですか?

私が話しているクラスのMSDNドキュメントへのリンク。 http://msdn.microsoft.com/en-us/library/system.windows.forms.htmlelement.clientrectangle.aspx?cs-save-lang=1&cs-lang=cpp#code-snippet-1

4

1 に答える 1

3

あなたの質問はやや広い解決策であるため、私はそれをやや大きく提供していますが、完全でテスト済みです。有効な IHTMLDocument または IHTMLElement オブジェクトへのポインターが既にある場合は、要素の位置とサイズを簡単に取得できます。寸法を取得するための唯一の要件は、ドキュメントが IHTMLWindow / IWebBrowser オブジェクトに添付されている必要があることです。テスト用に IWebBrowser オブジェクトと IHTMLDocument オブジェクトを作成するスタンド アロング関数を含めました。

途中で役立つコメントをいくつか含めました。これは、Internet Explorer 9 を搭載した Windows 7 システム上の Visual Studio 2010 でテストされました。これは、この例から取得した結果セットです。

Rect = x=8 y=89 width=992 height=31

内容=こんにちは

#include <comutil.h>    // _bstr_t
#include <mshtml.h>     // IHTMLDocument and IHTMLElement
#include <exdisp.h>     // IWebBrowser2
#include <atlbase.h>    // CComPtr
#include <string>
#include <iostream>

// Make sure we link in the support library!
#pragma comment(lib, "comsuppw.lib")

static const std::wstring
    exampleHtml(L"<body><html><br><br><p id=\"someid\">hello</p></body>");

HRESULT CreateBrowserDocument(
    const std::wstring& html,
    CComPtr<IWebBrowser2>& returnBrowser,
    CComPtr<IHTMLDocument3>& returnDoc);


int main()
{
    ///////////////////////////////////////////////////////////////////////////
    // In order to get the position and dimension of an element we need to
    // have a browser object that owns the document we will work on. If you
    // create and use a IHTMLDocument object through CoCreateInstance it does
    // not have any rendering capabilities by default.
    ///////////////////////////////////////////////////////////////////////////
    HRESULT hr;

    hr = CoInitialize(NULL);
    if(SUCCEEDED(hr))
    {
        // Make sure these two items are scoped so CoUninitialize doesn't gump
        // us up.
        CComPtr<IWebBrowser2> browser;
        CComPtr<IHTMLDocument3> document;

        hr = CreateBrowserDocument(exampleHtml, browser, document);

        if(SUCCEEDED(hr))
        {
            CComPtr<IHTMLElement> element;

            ///////////////////////////////////////////////////////////////////
            // We grab the element by id to make the example easier. in some
            // cases you may need to iterate through all of the elements of the
            // document or parent element to find the one you want the
            // dimensions for.
            ///////////////////////////////////////////////////////////////////

            hr = document->getElementById(_bstr_t(L"someid"), &element);
            if(SUCCEEDED(hr) && element != NULL)
            {
                ///////////////////////////////////////////////////////////////
                // Now that we have the browser object, document object and the
                // element we want to get the dimensions for .... do it the
                // easy way.
                ///////////////////////////////////////////////////////////////
                _bstr_t contents;
                long left, top, width, height;

                // I skip the error checking here. Add it when you implement
                // your solution.
                hr = element->get_innerHTML(contents.GetAddress());
                hr = element->get_offsetLeft(&left);
                hr = element->get_offsetTop(&top);
                hr = element->get_offsetWidth(&width);
                hr = element->get_offsetHeight(&height);

                std::cout
                    << "Rect = "
                    << "x=" << left << " "
                    << "y=" << top << "  "
                    << "width=" << width << " "
                    << "height=" << height << std::endl
                    << "contents=" << contents << std::endl;
            }
        }
    }

    CoUninitialize();

    return 0;
}


// Here we create web browser and document objects. The additional browser
// object is required for layout management. I have taken a shortcut here and
// create an instance Internet Explorer instead. This allows the browser to
// create and initializes a HTMLDocument when we call IWebBrowser::Navigate.
HRESULT CreateBrowserDocument(
    const std::wstring& html,
    CComPtr<IWebBrowser2>& returnBrowser,
    CComPtr<IHTMLDocument3>& returnDoc)
{
    CComPtr<IHTMLDocument2> document;
    CComPtr<IWebBrowser2> browser;
    HRESULT hr;

    hr = CoCreateInstance(
        CLSID_InternetExplorer,
        NULL,
        CLSCTX_SERVER,
        IID_IWebBrowser2,
        reinterpret_cast<void**>(&browser));
    if(SUCCEEDED(hr))
    {
        // The browser does not contain a document by default. We can force
        // one though by navigating to the `about` page. This is fast and
        // does not require an internet connection.
        VARIANT empty;

        VariantInit(&empty);

        hr = browser->Navigate(
            _bstr_t(L"about:"), &empty, &empty, &empty, &empty);

        //  Wait for the load.
        if(SUCCEEDED(hr))
        {
            READYSTATE state;

            while(SUCCEEDED(hr = browser->get_ReadyState(&state)))
            {
                if(state == READYSTATE_COMPLETE) break;
            }
        }

        // The browser now has a document object. Grab it.
        if(SUCCEEDED(hr))
        {
            CComPtr<IDispatch> dispatch;

            hr = browser->get_Document(&dispatch);
            if(SUCCEEDED(hr) && dispatch != NULL)
            {
                hr = dispatch.QueryInterface<IHTMLDocument2>(&document);
            }
            else
            {
                hr = E_FAIL;
            }
        }
    }

    if(SUCCEEDED(hr))
    {
        // Since the about page is empty we can just write out our test HTML
        // directly to the document. Takes some effort since we need to
        // use a safe array to send it to the document.
        SAFEARRAY *pString = SafeArrayCreateVector(VT_VARIANT, 0, 1);
        if (pString != NULL)
        {
            VARIANT *param;

            hr = SafeArrayAccessData(pString, reinterpret_cast<void**>(&param));
            if(SUCCEEDED(hr))
            {
                const _bstr_t htmlString(SysAllocString(html.c_str()));

                param->vt = VT_BSTR;
                param->bstrVal = htmlString;

                hr = SafeArrayUnaccessData(pString);
                if(SUCCEEDED(hr))
                {
                    hr = document->write(pString);
                    document->close();
                }
            }

            SafeArrayDestroy(pString);
        }

        //  Set the return values
        if(SUCCEEDED(hr) && document != NULL && browser != NULL)
        {
            CComPtr<IHTMLDocument3> temp;
            hr = document.QueryInterface<IHTMLDocument3>(&temp);
            if(SUCCEEDED(hr) && temp != NULL)
            {
                document = temp;
            }
            else 
            {
                hr = E_FAIL;
            }

            CComPtr<IHTMLDocument3> tempDoc;
            if(SUCCEEDED(hr))
            {
                hr = document.QueryInterface<IHTMLDocument3>(&tempDoc);
            }

            if(SUCCEEDED(hr) && tempDoc != NULL)
            {
                returnDoc = tempDoc;
                returnBrowser = browser;
            }
        }
        else if(!FAILED(hr))
        {
            hr = E_FAIL;
        }
    }

    return hr;
}



[編集 1 : への不要な呼び出しを削除IWebBrowser::put_RegisterAsBrowser]

[編集 2IHTMLElement::get_OffsetXXX :の代わりに使用して寸法を取得する簡略化IHTMLElement::get_clientXXX]

于 2013-04-22T23:09:48.693 に答える