使用方式:
if (m_pBrowserApp != NULL)
{
HRESULT hr;
LPDISPATCH lpDisp = GetHtmlDocument();
if (lpDisp != NULL)
{
CComPtr<IHTMLDocument2> spDocument;
hr = lpDisp->QueryInterface(IID_IHTMLDocument2, (void**) &spDocument);
hr = CopySelection2Clipbord(spDocument,m_hWnd);
lpDisp->Release();
}
}
//拷贝实现方式,共【三种遍历FRAME】方式:
HRESULT CopySelection2Clipbord(CComPtr<IHTMLDocument2>& spDocument, HWND hWnd)
{
HRESULT hr, hResult = MAKE_HRESULT(1,FACILITY_NULL,0);
long i = 0, j = 0;
CComQIPtr<IHTMLSelectionObject> spSelection;
hr = spDocument->get_selection(&spSelection);
if (SUCCEEDED(hr))
{
CComBSTR bstrType;
hr = spSelection->get_type(&bstrType);
if(SUCCEEDED(hr))
{
CString strType = _T("text");
if(!strType.CompareNoCase(bstrType))
{
CComQIPtr<IHTMLTxtRange> spRange;
hr = spSelection->createRange((IDispatch **)&spRange);
if(SUCCEEDED(hr))
{
CComQIPtr<IHTMLTxtRange> spTextRange;
hr = spRange->QueryInterface(IID_IHTMLTxtRange, (void**)&spTextRange);
if (SUCCEEDED(hr))
{
CComBSTR bstrHtml, bstrText;
spTextRange->get_htmlText(&bstrHtml);
spTextRange->get_text(&bstrText);
//写入剪贴板
CString cliphtml = bstrHtml;
CString cliptext = bstrText;
CopyHtmlToClip(cliphtml, cliptext, hWnd);
hResult = S_OK;
}
}
}
}
}
//iframe 跨域访问(cross frame), 由于安全性限制, 为防止跨域脚本攻击, 当frames 跨域的时候, IHTMLWindow2::get_document 调用将返回 E_ACCESSDENIED .
//对于跨域的frame 通过 IHTMLWindow2 -> IID_IWebBrowserApp -> IHTMLWindow2 绕过了限制.
/*//这种遍历不能跨域访问
if(!SUCCEEDED(hResult))
{
CComQIPtr<IHTMLFramesCollection2> spCollection;
HRESULT hr= spDocument->get_frames(&spCollection);
if(SUCCEEDED(hr))
{
long i = 0, j = 0;
VARIANT varindex,varresult;
varresult.vt = VT_DISPATCH;
varindex.vt = VT_I4;
hr = spCollection->get_length(&j);
if (SUCCEEDED(hr))
{
for (i= 0; i < j; i++)
{
varindex.lVal = i;
hr = spCollection->item(&varindex, &varresult);
if (SUCCEEDED(hr))
{
CComQIPtr<IHTMLWindow2> spWindow;
CComQIPtr<IHTMLDocument2> spDocument2;
CComQIPtr<IDispatch> spDispatch((LPDISPATCH)varresult.ppdispVal);
if (SUCCEEDED(spDispatch->QueryInterface(IID_IHTMLWindow2,(LPVOID *)&spWindow)))
{
if(SUCCEEDED(spWindow->get_document(&spDocument2)))
{
hResult = CopySelection2Clipbord(spDocument2, hWnd);
if(SUCCEEDED(hResult))
{
break;
}
}
}
}
}
}
}
}*/
if(!SUCCEEDED(hResult))
{
CComQIPtr<IOleContainer> spContainer(spDocument);
if(spContainer)
{
CComPtr<IEnumUnknown> spEnumerator;
hr = spContainer->EnumObjects(OLECONTF_EMBEDDINGS, &spEnumerator);
if(SUCCEEDED(hr))
{
ULONG uFetched = 0;
CComPtr<IUnknown> spUnk;
while (spEnumerator->Next(1, &spUnk, &uFetched) == S_OK)
{
CComQIPtr<IWebBrowser2, &IID_IWebBrowser2> spWB(spUnk);
if(spWB)
{
#if 1
CComPtr<IDispatch> spDisp;
hr = spWB->get_Document(&spDisp);
CComPtr<IHTMLDocument2> spDocument2;
hr = spDisp->QueryInterface(IID_IHTMLDocument2, (void**) &spDocument2);
hResult = CopySelection2Clipbord(spDocument2, hWnd);
#else
hResult = spWB->ExecWB(OLECMDID_COPY, OLECMDEXECOPT_SHOWHELP, NULL, NULL);
#endif//
if(SUCCEEDED(hResult))
{
break;
}
}
spUnk.Release();
}
}
}
}
/*if(!SUCCEEDED(hResult))
{
CComPtr<IHTMLElementCollection> spElementCollection;
hr = spDocument->get_all(&spElementCollection);
if(SUCCEEDED(hr))
{
spElementCollection->get_length(&j);
for(i = 0; i < j; i++)
{
VARIANT id, index;
V_VT(&id) = VT_I4;
V_I4(&id) = i;
V_VT(&index) = VT_I4;
V_I4(&index) = 0;
CComPtr<IDispatch> spDispatch;
hr = spElementCollection->item(id, index, &spDispatch);
if(spDispatch)
{
CComQIPtr<IHTMLElement> spElement(spDispatch);
if(spElement)
{
CComBSTR bstrTagName;
spElement->get_tagName(&bstrTagName);
if (lstrcmpiW(L"IFRAME", bstrTagName) == 0 || lstrcmpiW(L"FRAME", bstrTagName) == 0)
{
CComQIPtr<IHTMLFrameBase2> spFrameBase(spElement);
if(spFrameBase)
{
CComPtr<IHTMLWindow2> spFrameWindow;
hr = spFrameBase->get_contentWindow(&spFrameWindow);
if(spFrameWindow)
{
CComPtr<IHTMLDocument2> spFrameDocument;
hr = spFrameWindow->get_document(&spFrameDocument);
if(!spFrameDocument)
{
CComQIPtr<IServiceProvider> spServiceProvider(spFrameWindow);
if (spServiceProvider)
{
CComPtr<IWebBrowser2> spWebBrowser;
hr = spServiceProvider->QueryService(IID_IWebBrowserApp, IID_IWebBrowser2, (void**)&spWebBrowser);
if(spWebBrowser)
{
CComQIPtr<IDispatch> spDispDocument;
hr = spWebBrowser->get_Document(&spDispDocument);
spFrameDocument = spDispDocument;
//hr = spWebBrowser->ExecWB(OLECMDID_COPY, OLECMDEXECOPT_SHOWHELP, NULL, NULL);
}
}
}
if(spFrameDocument)
{
hResult = CopySelection2Clipbord(spFrameDocument,hWnd);
if(SUCCEEDED(hResult))
{
break;
}
}
}
}
}
}
}
}
}
}*/
return hResult;
}
//拷贝实现:
BOOL CopyHtmlToClip(const CString &strHtml, const CString &strText, HWND hWnd)
{
// 1)转换成UTF-8
int len = strHtml.GetLength();
if(len <= 0)
{
return FALSE;
}
char* pszU8 = new char[len * 3 + 1];
T2C(LPCTSTR(strHtml), pszU8, len * 3 + 1, CP_UTF8);
int nHtmlSrcLen = strlen(pszU8);
// 2)组成剪贴板片段
char* strHtmlClip = new char[nHtmlSrcLen + 512];
sprintf(strHtmlClip,
"Version:0.9\r\n"
"StartHTML:%08u\r\n"
"EndHTML:%08u\r\n"
"StartFragment:%08u\r\n"
"EndFragment:%08u\r\n"
"<html><body>\r\n"
"<!--StartFragment -->\r\n"
"%s\r\n"
"<!--EndFragment-->\r\n"
"</body></html>",
97, 172 + nHtmlSrcLen, 111, 136 + nHtmlSrcLen, pszU8);
// 3)剪贴板操作
static int cfid = 0;
if(!cfid)
{
cfid = RegisterClipboardFormat(_T("HTML Format"));
}
if (!OpenClipboard(hWnd))
{
return false;
}
if (!EmptyClipboard())
{
CloseClipboard();
return false;
}
len = strlen(strHtmlClip);
HGLOBAL hClipBuffer = GlobalAlloc(GMEM_DDESHARE, len + 1);
if (hClipBuffer == NULL)
{
CloseClipboard();
return false;
}
char *lpExpBuffer = (char *)GlobalLock(hClipBuffer);
if (lpExpBuffer == NULL)
{
GlobalFree(hClipBuffer);
CloseClipboard();
return false;
}
memcpy(lpExpBuffer, strHtmlClip, len);
lpExpBuffer[len] = '\0';
GlobalUnlock(hClipBuffer);
SetClipboardData(cfid, hClipBuffer);
CloseClipboard();
delete []pszU8;
delete []strHtmlClip;
CopyTextToClip(strText, hWnd, false);
return TRUE;
}
BOOL CopyTextToClip(const CString &strText, HWND hWnd, bool bEmpty)
{
if (OpenClipboard(hWnd))
{
HGLOBAL clipBuffer;
if(bEmpty)
{
EmptyClipboard();
}
#ifdef _UNICODE //复制Unicode字符串到剪贴板
wchar_t * buffer;
clipBuffer = GlobalAlloc(GMEM_DDESHARE, 2 * lstrlen(strText) + sizeof(wchar_t));
buffer = (wchar_t*)GlobalLock(clipBuffer);
wcscpy(buffer,LPCWSTR(strText));
GlobalUnlock(clipBuffer);
SetClipboardData(CF_UNICODETEXT,clipBuffer);
#else //复制ANSI字符串到剪贴板
char *pbuff;
clipBuffer = GlobalAlloc(GMEM_DDESHARE,strText.GetLength()+1);
pbuff = (char*)GlobalLock(clipBuffer);
strcpy(pbuff,LPCSTR(strText));
GlobalUnlock(clipBuffer);
SetClipboardData(CF_TEXT,clipBuffer);
#endif
CloseClipboard();
return TRUE;
}
return FALSE;
}