Загрузка страницы элемента C++ CHTMLView, а затем исчезновение

В моем приложении C++ CHTMLView используется для загрузки некоторого HTML-кода на веб-страницу. Он работает, записывая HTML во временный файл, а затем вызывая Navigate2() в CHTMLView для перехода к местоположению файла.

Что мы обнаруживаем, так это то, что навигация происходит, файл пишется, появляется полностью правильное содержимое страницы, но затем оно быстро исчезает и становится пустым. Но это визуальная вещь; щелчок правой кнопкой мыши и произнесение «Просмотр исходного кода» показывает правильный источник, а наведение курсора на элементы на странице, которые реагируют на наведение, заставляют их снова отображаться (но все остальное остается белым). Изменение размера окна или прокрутка — единственный способ отобразить все.

Я попытался сначала перейти к about:blank, а затем запустить навигацию в нужное место с помощью события OnDocumentComplete(). Я даже пытался сначала перейти на пустую фиктивную страницу, а затем перейти оттуда. Ничего не меняется.

Любой совет?!

Производный класс — ScriptViewer.

ScriptViewer.h

class CScriptViewer : public CHtmlView
{
protected:
    CScriptViewer();           // protected constructor used by dynamic creation
    DECLARE_DYNCREATE(CScriptViewer)

// html Data
public:
    //{{AFX_DATA(CScriptViewer)
        // NOTE: the ClassWizard will add data members here
    //}}AFX_DATA

// Attributes
public:
    CAMAgentDesktopDoc* m_pDoc;
    CScriptDlg* m_pDlg;

    CString strScriptLocation;
    BOOL m_bInitialLoad;

// Operations
public:
    void GetAllValues( map<CString,CString>& mValues );
    void GetValuesIn( IHTMLDocument2* pHTMLDoc, map<CString,CString>& mValues );

// Overrides
    // ClassWizard generated virtual function overrides
    //{{AFX_VIRTUAL(CScriptViewer)
    public:
    virtual void OnInitialUpdate();
    virtual void OnBeforeNavigate2(LPCTSTR lpszURL, DWORD nFlags, LPCTSTR lpszTargetFrameName, CByteArray& baPostedData, LPCTSTR lpszHeaders, BOOL* pbCancel);
    virtual void OnDocumentComplete(LPCTSTR lpszURL);
    protected:
    virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support
    //}}AFX_VIRTUAL

// Implementation
protected:
    virtual ~CScriptViewer();
#ifdef _DEBUG
    virtual void AssertValid() const;
    virtual void Dump(CDumpContext& dc) const;
#endif

    CAMTrace m_trace;

    // Generated message map functions
    //{{AFX_MSG(CScriptViewer)
        // NOTE - the ClassWizard will add and remove member functions here.
    //}}AFX_MSG
    DECLARE_MESSAGE_MAP()
};

ScriptViewer.cpp

CScriptViewer::CScriptViewer()
{
    //{{AFX_DATA_INIT(CScriptViewer)
        // NOTE: the ClassWizard will add member initialization here
    //}}AFX_DATA_INIT
    m_trace.SetEXEName( _T("CScriptViewer") );
    m_trace.Trace( _T("constructor"), FALSE, 0 );

    strScriptLocation = _T("");
    m_bInitialLoad = FALSE;

    m_pDoc = NULL;
    m_pDlg = NULL;
}

CScriptViewer::~CScriptViewer()
{
    /*
    map<CString,CString> mValues;
    GetAllValues( mValues );
    m_pDlg->UpdateUserEnteredValues( mValues );
    */
    m_trace.Trace( _T("destructor"), FALSE, 0 );
}

void CScriptViewer::DoDataExchange(CDataExchange* pDX)
{
    CHtmlView::DoDataExchange(pDX);
    //{{AFX_DATA_MAP(CScriptViewer)
        // NOTE: the ClassWizard will add DDX and DDV calls here
    //}}AFX_DATA_MAP
}


BEGIN_MESSAGE_MAP(CScriptViewer, CHtmlView)
    //{{AFX_MSG_MAP(CScriptViewer)
        // NOTE - the ClassWizard will add and remove mapping macros here.
    //}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CScriptViewer diagnostics

#ifdef _DEBUG
void CScriptViewer::AssertValid() const
{
    CHtmlView::AssertValid();
}

void CScriptViewer::Dump(CDumpContext& dc) const
{
    CHtmlView::Dump(dc);
}
#endif //_DEBUG

/////////////////////////////////////////////////////////////////////////////
// CScriptViewer message handlers

void CScriptViewer::OnInitialUpdate() 
{
    try
    {
    m_trace.Trace( _T("OnInitialUpdate") );

    ASSERT( m_pDoc );
    ASSERT( m_pDlg );
    }
    catch(...)
    {

    }
}

void CScriptViewer::OnBeforeNavigate2(LPCTSTR lpszURL, DWORD nFlags, LPCTSTR lpszTargetFrameName, CByteArray& baPostedData, LPCTSTR lpszHeaders, BOOL* pbCancel) 
{
    try
    {
    map<CString,CString> mValues;
    GetAllValues( mValues );

    ASSERT( m_pDlg );

// GJS
    if (!m_pDlg) return;
    m_pDlg->UpdateUserEnteredValues( mValues );

    CString strURL = lpszURL;
    int nPosClose = strURL.Find( URL_INSTRUCTION_TO_ADAPTIVE_DESKTOP );
    if ( nPosClose > 0 )
    {
        *pbCancel = TRUE;
        CHtmlView::OnBeforeNavigate2(lpszURL, nFlags, lpszTargetFrameName, baPostedData, lpszHeaders, pbCancel);

        m_pDlg->OnScriptInstructionToDesktop( strURL.Mid( nPosClose + _tcslen(URL_INSTRUCTION_TO_ADAPTIVE_DESKTOP) ), mValues );
    }
    else
    {
        CHtmlView::OnBeforeNavigate2(lpszURL, nFlags, lpszTargetFrameName, baPostedData, lpszHeaders, pbCancel);
    }
    }
    catch(...)
    {

    }
}

void CScriptViewer::OnDocumentComplete(LPCTSTR lpszURL) {
    if (!m_bInitialLoad) {
        //Navigate2(strScriptLocation);
        //m_bInitialLoad = TRUE;
    }
}




///////////////////////////////////////////////////////////////////////////////////
// accessing data values from the HTML pages, after the user has fiddled with them

void CScriptViewer::GetValuesIn( IHTMLDocument2* pHTMLDoc, map<CString,CString>& mValues )
{
    try
    {
    if ( pHTMLDoc != NULL )
    {
        BSTR bsURL;
        VERIFY( SUCCEEDED( pHTMLDoc->get_URL( &bsURL ) ) );
//      TRACE( _T("GetValuesIn(%s)\r\n"), CString(bsURL) );

        IHTMLFramesCollection2* pFrames = NULL;
        if ( SUCCEEDED( pHTMLDoc->get_frames( &pFrames ) ) )
        {
            long lNumFrames = 0;
            VERIFY( SUCCEEDED( pFrames->get_length( &lNumFrames ) ) );
            for( long l = 0; l < lNumFrames; l++ )
            {
                COleVariant v1(l);
                VARIANT vDispFrame;
                if ( SUCCEEDED( pFrames->item( v1, &vDispFrame ) ) )
                {
                    if ( vDispFrame.vt == VT_DISPATCH )
                    {
                        IHTMLWindow2* pWindow = NULL;
                        VERIFY( SUCCEEDED( (vDispFrame.pdispVal)->QueryInterface( IID_IHTMLWindow2, (LPVOID*)&pWindow ) ) );
                        ASSERT( pWindow );
                        IHTMLDocument2* pSubDoc = NULL;
                        if ( SUCCEEDED( pWindow->get_document( &pSubDoc ) ) )
                        {
                            GetValuesIn( pSubDoc, mValues );
                            pSubDoc->Release();
                        }
                        pWindow->Release();
                    }
                }
            }
            pFrames->Release();
        }

        IHTMLElementCollection* pElemColl = NULL;
        HRESULT hr = pHTMLDoc->get_all(&pElemColl);
        if (SUCCEEDED(hr) && pElemColl)
        {
            long lNumElements = 0;
            VERIFY( SUCCEEDED( pElemColl->get_length( &lNumElements ) ) );
            for( long l = 0; l < lNumElements; l++ )
            {
                COleVariant v1(l);
                COleVariant vzero((long)0);
                LPDISPATCH pDispTemp = NULL;
                VERIFY( SUCCEEDED( pElemColl->item( v1, vzero, &pDispTemp ) ) );
                ASSERT( pDispTemp != NULL );
                IHTMLElement* pel = NULL;
                VERIFY( SUCCEEDED( pDispTemp->QueryInterface( IID_IHTMLElement, (LPVOID*)&pel ) ) );

                CString str;
                BSTR bsid;
                pel->get_id( &bsid );
                VARIANT vValue;
                pel->getAttribute( CString("value").AllocSysString(), 0, &vValue );
                CString strID = CString(bsid);
                if ( !strID.IsEmpty() )
                {
                    CString strValue = _T("");
                    if ( vValue.vt == VT_BSTR ) {
                        strValue = CString(vValue.bstrVal);
                    } else if ( vValue.vt == VT_I2  ||  vValue.vt == VT_I4 ) {
                        strValue.Format( _T("%d"), vValue.intVal );
                    }

                    mValues[strID] = strValue;

//                  str.Format( _T("ID %s, value %s\r\n"),
//                              strID, strValue );
//                  strRetval += str;
                }

                pel->Release();
            }
            pElemColl->Release();
        }
        else
            ASSERT(FALSE);
    }
    else
        ASSERT(FALSE);  // passed null object doc
    }
    catch(...)
    {

    }
}

void CScriptViewer::GetAllValues( map<CString,CString>& mValues )
{
    try
    {
    mValues.clear();

    LPDISPATCH pDisp = GetHtmlDocument();
    if ( pDisp )
    {
        IHTMLDocument2* p = NULL;
        if ( SUCCEEDED( pDisp->QueryInterface( IID_IHTMLDocument2, (LPVOID*)&p ) )  &&  p != NULL )
        {
            GetValuesIn( p, mValues );
            p->Release();
        }
        else
            ASSERT(FALSE);  // unable to QI for IHTMLDocument2?

        pDisp->Release();
    }
    }
    catch(...)
    {

    }
}

Вот код, который обрабатывает навигацию:

CString strFilePath = CAMMiscSharedFilePaths::GetFullPathToWindowsTempDir() + _T("\\") + m_call->m_camCampaignSettings.m_scriptView.m_strName+_T("_temp.htm");
        HRESULT hr = WriteStringToTextFile( strFilePath, strRedirect );     //intentionally left for html settings, as it stores data in windows temp 

        if ( SUCCEEDED(hr) ) {
            pView->strScriptLocation = strFilePath;

            CString str = strFilePath;          
            pView->Navigate2(str);


        }

person Raiden616    schedule 19.05.2015    source источник
comment
Опубликуйте свой код производного класса CHtmlView   -  person Andrew Komiagin    schedule 19.05.2015
comment
Ваше здоровье! Добавил соответствующий код.   -  person Raiden616    schedule 20.05.2015
comment
Хорошо, обновление: если я добавлю Sleep (1000) прямо перед вызовом Navigate2 (), это, кажется, исправит это. Или, по крайней мере, обойти это. Это дает какой-либо ключ к кому-либо? Я лучше поправлю нормально...   -  person Raiden616    schedule 20.05.2015
comment
Вы пытались переопределить OnBeforeNavigate2 с помощью пустого метода?   -  person dwo    schedule 20.05.2015
comment
@dwo У меня есть, да. К сожалению никакой разницы.   -  person Raiden616    schedule 21.05.2015


Ответы (1)


Вот мой производный класс CHTMLView. Я загружаю HTML прямо в браузер. Работает для меня, возможно, вы можете использовать это:

#include "stdafx.h"
#include "GMHtmlView.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

IMPLEMENT_DYNCREATE(CGMHtmlView, CHtmlView)

CGMHtmlView::CGMHtmlView(IHtmlEventNotifier* pHEN)
{
    EnableToolTips(FALSE);
    m_pBrowser = NULL;
    m_pBrowserDispatch = NULL;
    m_pHEN = pHEN;
    m_strPrefix = "http://";
}

void CGMHtmlView::DoDataExchange(CDataExchange* pDX)
{
    CHtmlView::DoDataExchange(pDX);
}

BEGIN_MESSAGE_MAP(CGMHtmlView, CHtmlView)
END_MESSAGE_MAP()

BOOL CGMHtmlView::Create(const RECT &rect,CWnd* pParentWnd)
{
    BOOL bRet = CHtmlView::Create(NULL,NULL,WS_VISIBLE,rect,pParentWnd,AFX_IDW_PANE_FIRST);

    // Pointer auf Browser herausfinden
    if(bRet)
    {
        LPUNKNOWN unknown = GetDlgItem(0)->GetControlUnknown();
        HRESULT hr = unknown->QueryInterface(IID_IWebBrowser2,(void **)&m_pBrowser);

        if (SUCCEEDED(hr))
            hr = unknown->QueryInterface(IID_IDispatch,(void **)&m_pBrowserDispatch);
    }

    return bRet;
}

void CGMHtmlView::SetPrefix(const CString& prefix)
{
    m_strPrefix = prefix;
}

void CGMHtmlView::OnBeforeNavigate2(LPCTSTR lpszURL, DWORD nFlags, LPCTSTR lpszTargetFrameName, CByteArray& baPostedData, LPCTSTR lpszHeaders, BOOL* pbCancel)
{
    CString url(lpszURL);
    url.MakeLower();

    // Sperre: alles andere als die leere Seite
    // und unser Inhalt wird gesperrt

    if(url == "about:blank")
    {
        CHtmlView::OnBeforeNavigate2(lpszURL,nFlags,lpszTargetFrameName,baPostedData,lpszHeaders,pbCancel);
        return;
    }

    if(url.Find(m_strPrefix) != 0)
    {
        *pbCancel = TRUE;
        return;
    }

    // jetzt die Adresse nach aussen weiterleiten
    if(m_pHEN)
    {
        url = url.Right(url.GetLength() - m_strPrefix.GetLength());
        m_pHEN->UrlNotify(url);
    }
}

void CGMHtmlView::Clear()
{
    if(!IsWindow(m_hWnd))
        return;

    IHTMLDocument2* pDoc = GetDocument();

    if(!pDoc)
    {
        Navigate2("about:blank");
        return;
    }

    pDoc->close();

    VARIANT open_name;
    VARIANT open_features;
    VARIANT open_replace;
    IDispatch *open_window = NULL;

    ::VariantInit(&open_name);

    open_name.vt      = VT_BSTR;
    open_name.bstrVal = ::SysAllocString(L"_self");

    ::VariantInit(&open_features);
    ::VariantInit(&open_replace);

    HRESULT hr = pDoc->open(::SysAllocString(L"text/html"),open_name,open_features,
        open_replace,&open_window);

    if (hr == S_OK)
        Refresh();

    if (open_window != NULL)
        open_window->Release();

}

void CGMHtmlView::LoadHTML(const CString& html)
{
    if(!IsWindow(m_hWnd))
        return;

    Clear();

    IHTMLDocument2* pDoc = GetDocument();

    if(!pDoc)
        return;

    SAFEARRAY* sa = SafeArrayCreateVector(VT_VARIANT,0,1);
    VARIANT* var;

    SafeArrayAccessData(sa,(LPVOID*) &var);
    var->vt = VT_BSTR;
    var->bstrVal = html.AllocSysString();
    SafeArrayUnaccessData(sa);

    pDoc->write(sa);
    pDoc->Release();
}

IHTMLDocument2* CGMHtmlView::GetDocument()
{
    IHTMLDocument2* document = NULL;

    if (m_pBrowser != NULL)
    {
        IDispatch *document_dispatch = NULL;
        HRESULT hr = m_pBrowser->get_Document(&document_dispatch);

        if (SUCCEEDED(hr) && (document_dispatch != NULL))
        {
            hr = document_dispatch->QueryInterface(IID_IHTMLDocument2,(void **)&document);
            document_dispatch->Release();
        }
    }

    return document;
}

void CGMHtmlView::AssertValid() const
{
    //CHtmlView::AssertValid();
}

void CGMHtmlView::PostNcDestroy()
{
    //CHtmlView::PostNcDestroy();
}
person dwo    schedule 20.05.2015