2013-01-10 76 views
4

基於這樣一個問題:How can I get HTML source code from TWebBrowser來自TWebBrowser的HTML源代碼 - 如何檢測流編碼?

如果我用Unicode代碼頁中的HTML頁面運行this code,結果是亂碼becouse TStringStream不D7 UNICODE。該頁面可能是UTF8編碼或其他(Ansi)代碼頁面編碼。

如何檢測TStream/IPersistStreamInit是否爲Unicode/UTF8/Ansi?

對於這個功能,我如何總是返回正確的結果爲WideString

function GetWebBrowserHTML(const WebBrowser: TWebBrowser): WideString; 

如果我和內存流代替TStringStream,並節省內存流提交這一切都很好。它可以是Unicode/UTF8/Ansi。但我一直想回到流回來爲WideString的:

function GetWebBrowserHTML(const WebBrowser: TWebBrowser): WideString; 
var 
    // LStream: TStringStream; 
    LStream: TMemoryStream; 
    Stream : IStream; 
    LPersistStreamInit : IPersistStreamInit; 
begin 
    if not Assigned(WebBrowser.Document) then exit; 
    // LStream := TStringStream.Create(''); 
    LStream := TMemoryStream.Create; 
    try 
    LPersistStreamInit := WebBrowser.Document as IPersistStreamInit; 
    Stream := TStreamAdapter.Create(LStream,soReference); 
    LPersistStreamInit.Save(Stream,true); 
    // result := LStream.DataString; 
    LStream.SaveToFile('c:\test\test.txt'); // test only - file is ok 
    Result := ??? // WideString 
    finally 
    LStream.Free(); 
    end; 
end; 

編輯:我發現這篇文章 - How to load and save documents in TWebBrowser in a Delphi-like way

這exactlly什麼,我需要做。但它只適用於Delphi的Unicode編譯器(D2009 +)。閱讀Conclusion部分:

顯然我們可以做更多。立即想起幾件事 。我們將一些Unicode 功能以及對非ANSI編碼的支持修改爲Unicode之前的 編譯器代碼。如果文檔字符集不是ANSI,那麼使用比Delphi 2009早 編譯的當前代碼將不會正確地將文檔內容保存到字符串 。

這個魔法顯然在TEncoding class(TEncoding.GetBufferEncoding)。但D7沒有TEncoding。有任何想法嗎?

+1

也許這將有助於http://msdn.microsoft.com/en-us/library/jj160620(v= vs.85).aspx –

+0

嘗試一些支持Unicode的StringList。 jcl.sf.net庫有'TWideStringList'和'TJclWideStringList',TNT Unicode組件有'TWideStringList',我想還有更多。也許其中一些人還有COM IStringList適配器,這種或那種方式。嘗試這些或嘗試搜索更多的Unicode字符串實現爲Delphi 7,在谷歌或torry.net或其他收藏家 –

+0

MSIE引入到DOM屬性如.outerHTML和.innerHTML 所以實際上我打賭你必須得到HTML DOM樹,獲取HTML標記,然後獲取它的outerHTML屬性作爲BSTR又名WideString,無需中間COM對象。 也許你會爲此一點點JavaScript。 像「如何點擊TWebControl中的按鈕」這樣的搜索主題 - 他們會向您演示如何從Delphi端定位一些標籤作爲JS對象以及如何調用它的方法/屬性。您需要閱讀根HTML標記的outerHTML屬性 –

回答

2

我用GpTextStream處理皈依(應該爲所有的Delphi版本一起使用):

function GetCodePageFromHTMLCharSet(Charset: WideString): Word; 
const 
    WIN_CHARSET = 'windows-'; 
    ISO_CHARSET = 'iso-'; 
var 
    S: string; 
begin 
    Result := 0; 
    if Charset = 'unicode' then 
    Result := CP_UNICODE else 
    if Charset = 'utf-8' then 
    Result := CP_UTF8 else 
    if Pos(WIN_CHARSET, Charset) <> 0 then 
    begin 
    S := Copy(Charset, Length(WIN_CHARSET) + 1, Maxint); 
    Result := StrToIntDef(S, 0); 
    end else 
    if Pos(ISO_CHARSET, Charset) <> 0 then // ISO-8859 (e.g. iso-8859-1: => 28591) 
    begin 
    S := Copy(Charset, Length(ISO_CHARSET) + 1, Maxint); 
    S := Copy(S, Pos('-', S) + 1, 2); 
    if S = '15' then // ISO-8859-15 (Latin 9) 
     Result := 28605 
    else 
     Result := StrToIntDef('2859' + S, 0); 
    end; 
end; 

function GetWebBrowserHTML(WebBrowser: TWebBrowser): WideString; 
var 
    LStream: TMemoryStream; 
    Stream: IStream; 
    LPersistStreamInit: IPersistStreamInit; 
    TextStream: TGpTextStream; 
    Charset: WideString; 
    Buf: WideString; 
    CodePage: Word; 
    N: Integer; 
begin 
    Result := ''; 
    if not Assigned(WebBrowser.Document) then Exit; 
    LStream := TMemoryStream.Create; 
    try 
    LPersistStreamInit := WebBrowser.Document as IPersistStreamInit; 
    Stream := TStreamAdapter.Create(LStream, soReference); 
    if Failed(LPersistStreamInit.Save(Stream, True)) then Exit; 
    Charset := (WebBrowser.Document as IHTMLDocument2).charset; 
    CodePage := GetCodePageFromHTMLCharSet(Charset); 
    N := LStream.Size; 
    SetLength(Buf, N); 
    TextStream := TGpTextStream.Create(LStream, tsaccRead, [], CodePage); 
    try 
     N := TextStream.Read(Buf[1], N * SizeOf(WideChar)) div SizeOf(WideChar); 
     SetLength(Buf, N); 
     Result := Buf; 
    finally 
     TextStream.Free; 
    end; 
    finally 
    LStream.Free(); 
    end; 
end;