我使用 MFC CHtmlView 类视图打开了目标网页,里面有个div如下图,该div内容是通过ajax动态获取的,html源文件是没有内容的。
Navigate2后,OnDocumentComplete 和 OnNavigateComplete2 消息回调时 div 内容还没有显示出来了。若人工检测,完全加载完页面后,再执行函数,采用 IDispatch IHTMLDocument3 IHTMLElementCollection IHTMLElement 等结合,是可以获取到 div 的 innerHTML
请教如何判断目标网页的完全加载,或者准确的说,是判断目标 div 已经ajax动态加载完毕?
或者谁能给段有效的代码,使用 IHTMLElement getAttribute 获取div class属性值
该回答引用ChatGPT
遇到问题可以回复我
您可以通过以下几种方式来判断目标 div 是否已经ajax动态加载完毕:
1、使用JavaScript:您可以在页面加载时通过JavaScript监听目标 div 的加载事件,当该 div 加载完成后触发回调函数,以此来判断目标 div 是否已经加载完成。例如,您可以使用以下代码来监听目标 div 的加载事件:
var targetDiv = document.querySelector('.blockcontent');
targetDiv.addEventListener('load', function() {
// 目标 div 加载完成后的处理逻辑
});
2、监听XMLHttpRequest的onreadystatechange事件:如果目标 div 是通过ajax动态获取的,那么可以通过监听XMLHttpRequest对象的onreadystatechange事件来判断目标 div 是否已经加载完成。当XMLHttpRequest对象的readyState属性为4时,表示请求已完成,可以通过XMLHttpRequest对象的responseText属性获取返回的HTML代码,从而判断目标 div 是否已经加载完成。例如,您可以使用以下代码来监听XMLHttpRequest对象的onreadystatechange事件:
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function() {
if (xhr.readyState === 4) {
var html = xhr.responseText;
// 在返回的HTML代码中查找目标 div,判断其是否已经加载完成
}
};
xhr.open('GET', 'http://example.com/ajax_request', true);
xhr.send();
3、使用jQuery的load方法:如果您的应用中使用了jQuery库,您可以使用jQuery的load方法来加载目标 div,并通过load方法的回调函数来判断目标 div 是否已经加载完成。例如,您可以使用以下代码来加载目标 div 并判断其是否已经加载完成:
$('.blockcontent').load('http://example.com/ajax_request', function() {
// 目标 div 加载完成后的处理逻辑
});
该回答内容部分引用GPT,GPT_Pro更好的解决问题
CHtmlView 加载完成消息获取
要判断目标网页是否完全加载,我们可以使用MFC 的CHtmlView 类视图来实现。CHtmlView 类视图提供了多个消息回调函数,如OnDocumentComplete 和 OnNavigateComplete2,当页面加载完成时,这两个函数就会被调用。
在这两个函数中,我们可以通过IDispatch、IHTMLDocument3、IHTMLEIlementCollection 和 IHTMLElement 等结合,来获取div的innerHTML。IHTMLElementCollection 是一种DOM 元素的集合,可以通过item 函数来获取某一个元素;通过innerHTML 属性可以获取元素的内容。
//声明 HTML 文档对象
CComPtr<IHTMLDocument2> m_spHtmlDoc;
//声明元素集合对象
CComPtr<IHTMLElementCollection> m_spEleCol;
//声明元素对象
CComPtr<IHTMLElement> m_spEle;
//声明内部 HTML 字符串
CComBSTR sHtml;
//声明内部文本字符串
CComBSTR sText;
// 定义元素 ID 字符串
CComBSTR sId = "block_content";
// 获取 HTML 文档对象
m_spHtmlDoc = m_pBrowser->GetHtmlDocument();
// 获取元素集合对象
m_spHtmlDoc->get_all(&m_spEleCol);
// 通过 ID 获取某一个元素
m_spEleCol->item(CComVariant(sId), CComVariant(0), &m_spEle);
// 获取元素的 innerHTML
m_spEle->get_innerHTML(&sHtml);
// 获取元素的 innerText
m_spEle->get_innerText(&sText);
通过上面的代码,我们就能够判断目标div是否已经ajax动态加载完毕,从而达到判断目标页面是否完全加载的目的。
如果回答有帮助,望采纳。
该回答引用GPTᴼᴾᴱᴺᴬᴵ
您可以通过在 MFC CHtmlView 类中覆盖 OnDownloadComplete 或者 OnQuit 方法来获取网页加载完成的消息。在 OnDownloadComplete 方法中,您可以检查是否存在目标 div,以判断它是否已经动态加载完毕。下面是一个简单的示例代码:
class CMyHtmlView : public CHtmlView
{
public:
virtual void OnDownloadComplete();
};
void CMyHtmlView::OnDownloadComplete()
{
CHtmlView::OnDownloadComplete();
// 获取 HTML 文档对象
CComPtr<IHTMLDocument2> spDoc = GetHtmlDocument();
// 获取目标 div
CComPtr<IHTMLElement> spElement;
spDoc->getElementById(L"myDiv", &spElement);
if (spElement)
{
// 目标 div 存在,表示已经加载完毕
// 在这里获取 div 的 innerHTML
CString strHtml;
spElement->get_innerHTML(strHtml.GetBufferSetLength(1024), 1024);
strHtml.ReleaseBuffer();
}
}
需要注意的是,上面的代码中假定目标 div 的 id 是 "myDiv"。如果您的目标 div 的 id 不同,需要相应地修改代码。另外,由于这个方法是在加载完成后立即执行的,因此如果目标 div 是通过 JavaScript 动态加载的,可能还需要等待一段时间才能获取到它。在这种情况下,您可能需要使用定时器或者其他技术来等待目标 div 加载完成。
可以通过在 CHtmlView 类中重写 OnDownloadComplete() 函数来判断页面是否已经完全加载。当页面上所有资源都被下载完成时,OnDownloadComplete() 函数会被调用。但是这个函数只能检测到页面所有资源是否加载完成,而无法判断特定的 div 是否已经加载完毕,以下是示例代码:
// 在 CHtmlView 类中添加以下代码
LRESULT CHtmlView::OnDivLoaded(WPARAM wParam, LPARAM lParam)
{
// 在这里处理 div 加载完成后的逻辑
return 0;
}
void CHtmlView::OnDocumentComplete(LPCTSTR lpszURL)
{
// 在文档加载完成后注册 div 加载事件监听器
CString strJavaScript;
strJavaScript.Format(_T("document.getElementById('div_id').addEventListener('load', function() { \
window.external.NotifyDivLoaded(); \
});"));
GetHtmlDocument()->parentWindow->execScript(strJavaScript, _T("JavaScript"));
CHtmlView::OnDocumentComplete(lpszURL);
}
BEGIN_DHTML_EVENT_MAP(CHtmlView)
DHTML_EVENT_ONCLICK(_T("a"), OnClickAnchor)
DHTML_EVENT_ONCLICK(DISPID_HTMLELEMENTEVENTS_ONCLICK, OnClick)
DHTML_EVENT_ONSUBMIT(_T("form"), OnSubmitForm)
DHTML_EVENT_ONCHANGE(_T("input"), OnChangeInput)
DHTML_EVENT_ONKEYPRESS(_T("body"), OnKeyPress)
END_DHTML_EVENT_MAP()
// 在 DHTML 事件映射中添加以下代码
DHTML_EVENT_ONCALL(_T("NotifyDivLoaded"), OnDivLoaded)
若对你有所帮助,望采纳。
参考GPT和自己的思路,您可以通过检查目标 div 是否存在来判断它是否已经动态加载完毕。在 MFC CHtmlView 中,您可以在 OnDocumentComplete 或 OnNavigateComplete2 中使用 IHTMLDocument3 接口访问文档的元素,并使用 IHTMLElementCollection 接口查找具有特定 ID 的元素。
以下是一个示例代码片段,它使用 IHTMLElementCollection 接口在文档中查找 ID 为“target_div”的元素:
void CMyHtmlView::OnDocumentComplete(LPCTSTR lpszURL) {
CHTMLView::OnDocumentComplete(lpszURL);
// Get the document's IHTMLDocument3 interface
CComPtr<IHTMLDocument3> spDocument;
if (SUCCEEDED(GetHtmlDocument()->QueryInterface(IID_IHTMLDocument3, (void**)&spDocument))) {
// Find the target div element by ID
CComBSTR bstrId(L"target_div");
CComPtr<IHTMLElementCollection> spElements;
spDocument->getElementsByName(bstrId, &spElements);
long nCount = 0;
if (SUCCEEDED(spElements->get_length(&nCount)) && nCount > 0) {
// The target div element exists
// Do something with its inner HTML
CComPtr<IHTMLElement> spElement;
spElements->item(0, 0, &spElement);
CComBSTR bstrHtml;
spElement->get_innerHTML(&bstrHtml);
CString strHtml = bstrHtml;
// ...
}
else {
// The target div element does not exist yet
// Wait for it to be loaded
// ...
}
}
}
如果在 OnDocumentComplete 中找不到目标 div 元素,则可以等待一段时间后再次检查,直到元素出现为止。您可以使用定时器、线程等机制实现此等待。但是请注意,等待时间过长可能会导致界面不流畅或卡死,应根据具体情况适当调整等待时间。
在 MFC 的 CHtmlView 类中,可以通过重载 OnDownloadComplete 函数来捕捉 AJAX 动态加载完成的事件。当 AJAX 请求完成后,该函数会被调用,可以在该函数中获取 div 的内容。
以下是一个示例代码,其中在 OnDownloadComplete 函数中获取了 div 的 class 属性值:
class CMyHtmlView : public CHtmlView
{
public:
CMyHtmlView() {}
DECLARE_DYNCREATE(CMyHtmlView)
virtual void OnDownloadComplete() override
{
// 基类函数需要调用,确保完成后视图正常显示
CHtmlView::OnDownloadComplete();
// 获取 div 元素
IHTMLDocument2* pDoc = GetHtmlDocument();
if (pDoc)
{
CComPtr<IHTMLElement> pDiv;
pDoc->getElementById(L"block_content", &pDiv);
if (pDiv)
{
// 获取 class 属性值
CComBSTR bstrClass;
pDiv->getAttribute(L"class", 0, &bstrClass);
CString strClass = bstrClass;
AfxMessageBox(strClass);
}
}
}
// 省略其他代码...
};
在 OnDownloadComplete 函数中,首先调用了基类函数确保视图能够正常显示,然后获取了 div 元素,并通过 IHTMLElement 的 getAttribute 函数获取了其 class 属性值。可以根据实际需求修改获取元素的方式,比如根据 class 名称或标签名称等方式获取元素。
需要注意的是,OnDownloadComplete 只能在页面完全加载完成后才会被调用,如果 div 的内容是通过多个 AJAX 请求加载的,可能需要等待多个 OnDownloadComplete 函数被调用才能确保内容全部加载完成。
分两种情况考虑:
1、如果是你可以修改的div,可以在div加载完毕后主动发送消息给CHtmlViewer;
2、如果不能修改div和js。需要动态获取div状态判断是否加载完成再进行你想的操作,可能需要你定时轮询来实现。
有帮助请采纳,谢谢!