1. 程式人生 > >【MFC】CHtmlView::GetSource中文亂碼的問題

【MFC】CHtmlView::GetSource中文亂碼的問題

需要 style spp creates let clas document amp LG

在MFC的SDI中,使用CHtmlView::GetSource來獲取網頁源碼,保存到本地,發現中文中的一部分亂碼,有些中文正常。自己先試著轉碼等各種嘗試,發現一無所獲。網上也沒有正確的解決方案。

自己跟蹤CHtmlView::GetSource函數內,在ViewHtml.cpp文件的1083行處,有如下代碼:

bRetVal = TRUE;
TRY
{
    refString = CString(pstr, statStg.cbSize.LowPart);
}
CATCH_ALL(e)
{
    bRetVal = FALSE;
    DELETE_EXCEPTION(e);
}

關鍵處在:refString = CString(pstr, statStg.cbSize.LowPart);

其實就是在UNICODE情況下,CString在構造時,使用了LPCSTR或者char*來構造CString時的構造函數。但是在構造這個CString內部,會調用到如下函數:

static void __cdecl ConvertToBaseType(
        _Out_writes_(nDestLength) LPWSTR pszDest,
        _In_ int nDestLength,
        _In_ LPCSTR pszSrc,
        _In_ int nSrcLength = -1) throw()
{
    // nLen is in wchar_ts
::MultiByteToWideChar( _AtlGetConversionACP(), 0, pszSrc, nSrcLength, pszDest, nDestLength ); }

內部有對LPCSTR或char*進行字符轉換。

中文的一部分亂碼,正是由這個地方產生的。

別奢望用CStringA str(strHtml)來轉換回來,轉了之後的內容,依然有一部分的中文亂碼。

我的解決辦法是,將CHtmlView::GetSource的代碼Copy出來,直接返回CStringA的內容,並用CStringA的內容,來保存文件。結果就正常了。

我的代碼如下:

BOOL CMFCBrowserView::GetMySource(CStringA& strRef)
{
    BOOL bRetVal 
= FALSE; CComPtr<IDispatch> spDisp; m_pBrowserApp->get_Document(&spDisp); if ( spDisp == NULL ) { return bRetVal; } HGLOBAL hMemory; hMemory = GlobalAlloc(GMEM_MOVEABLE, 0); if ( hMemory == NULL ) { return bRetVal; } CComQIPtr<IPersistStreamInit> spPersistStream = spDisp; if ( spPersistStream == NULL ) { GlobalFree(hMemory); return bRetVal; } CComPtr<IStream> spStream; HRESULT hRes = CreateStreamOnHGlobal(hMemory, TRUE, &spStream); if ( FAILED(hRes) ) { GlobalFree(hMemory); return bRetVal; } spPersistStream->Save(spStream, FALSE); STATSTG statStg; spStream->Stat(&statStg, STATFLAG_NONAME); LPCSTR pstr = static_cast<LPCSTR>(GlobalLock(hMemory)); if ( pstr == NULL ) { GlobalFree(hMemory); return bRetVal; } // Stream is expected to be ANSI (CP-ACP). CString constructor // will convert implicitly, and truncate to correct length. bRetVal = TRUE; CStringA strV(pstr, statStg.cbSize.LowPart); strRef = strV; GlobalUnlock(hMemory); GlobalFree(hMemory); return bRetVal; }

主要問題:就出在CString內部構造時,對字符串的轉換。如果需要CString的字符串,可能需要自己來轉換成寬字符,然後賦值給CString。這個只是猜測,沒有進行測試。

【MFC】CHtmlView::GetSource中文亂碼的問題