在我的C ++应用程序中,使用CHTMLView将一些HTML加载到网页中。它的工作原理是将HTML写入临时文件,然后在CHTMLView上调用Navigate2()以导航到文件位置。
我们发现的是导航发生,文件被写入,页面的内容完全正确,但随后它很快消失并变为空白。但这是一个视觉的东西;右键单击并说“查看源代码”显示正确的源,并将鼠标悬停在页面上对悬停做出反应的元素会使它们再次出现(但其他所有内容都保持白色)。调整窗口大小或滚动是使所有内容都显示的唯一方法。
我尝试先导航到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);
}
答案 0 :(得分:0)
这是我的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();
}