2013-03-29 86 views
2

我正在使用以下單元通過顯示在非模式對話框中的TWebBrowser顯示 - 和打印 - HTML代碼。在我的生產程序中,以下代碼在Windows-XP下運行,但在Windows-7下運行失敗(錯誤消息總是外部異常C015D00F)。爲了解決這個問題,我編寫了一個簡單的測試程序,它也有一個非模態對話框,其中包含一個TWebBrowser;就其本身而言,這個測試程序可以與Windows-7正常工作,但是當我將測試程序中的非模態對話框插入生產程序時,我會得到外部異常。從TWebBrowser打印

這大概表明調用程序有問題,而不是被調用單元,但我看不出有什麼問題。 HTML代碼是手工製作的,但顯示正確。

可能是什麼問題?打印代碼來自Embarcadero公司site

unit Test4; 

interface 
uses 
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, 
Dialogs, OleCtrls, SHDocVw, MSHTML; 

type 
THTMLPreview = class(TForm) 
    web: TWebBrowser; 
    procedure FormClose(Sender: TObject; var Action: TCloseAction); 
    procedure webDocumentComplete(Sender: TObject; const pDisp: IDispatch; 
           var URL: OleVariant); 
    private 
    options: word; 
    fn: string; 
    procedure DoPrint; 
    public 
    Constructor Create (const afn, acapt: string; opts: word); 
    end; 

implementation 

{$R *.dfm} 

constructor THTMLPreview.Create (const afn, acapt: string; opts: word);     
begin 
inherited create (nil); 
caption:= acapt; 
fn:= afn; 
options:= opts; 
web.Navigate (fn); 
end; 

procedure THTMLPreview.webDocumentComplete(Sender: TObject; 
       const pDisp: IDispatch; var URL: OleVariant); 
begin 
DoPrint 
end; 

procedure THTMLPreview.DoPrint; 
var 
HTMLDoc: IHTMLDocument2; 
HTMLWnd: IHTMLWindow2; 
HTMLWindow3: IHTMLWindow3; 

begin 
if options and 4 = 4 then 
    begin 
    HTMLDoc:= web.Document as IHTMLDocument2; 
    if HTMLDoc <> nil then 
    begin 
    HTMLWnd:= HTMLDoc.parentWindow; 
    HTMLWindow3:= HTMLWnd as IHTMLWindow3; 
    HTMLWindow3.print; 
    end 
    end 
end; 

procedure THTMLPreview.FormClose(Sender: TObject; var Action: TCloseAction); 
begin 
if options and 1 = 1 then deletefile (fn); 
action:= caFree 
end; 

end. 

使用聲明Web.ControlInterface.ExecWB (OLECMDID_PRINT, OLECMDEXECOPT_PROMPTUSER, vaIn, vaOut)給出了同樣的錯誤。從後來幾天


編輯:

我嘗試了完全不同的方法解決問題。在HTML代碼中,我添加了一個顯示「打印」按鈕並添加了「onprint」事件的JavaScript片段。再一次,這在我的開發機器(XP)上可以正常工作,但在我的客戶機器(Win7)上卻不能正常工作,程序因聲明外部異常C015D00F(與以前地址相同)而凍結。


谷歌搜索不小的量之後,我發現了異常代碼C015000F由 造成「被停用的激活上下文不是最近激活之一。」這對窮人的Delphi程序員意味着什麼?

+1

什麼行觸發異常?你如何關閉表格?手動? – kobik

+0

爲什麼downvotes? –

+0

@Noam,我不是低調的選民,但你仍然沒有提供足夠的信息。請寫下我的評論。 – kobik

回答

2

如果我沒有記錯,IHTMLWindow3.print方法彈出默認的「發送到打印機」系統對話框。你想要這個嗎?對於我曾經搜索過的一種避免這種情況的應用,然後找到了這個代碼。

var 
    r:TRect; 
    sh,ph:HDC; 
begin 
    OleInitialize(nil); 
    WebBrowser1.Navigate('file://'+HtmlFilePath); 
    while WebBrowser1.ReadyState<>READYSTATE_COMPLETE do Application.HandleMessage; 

    //Printer.PrinterIndex:=//set selected printer here 
    Printer.BeginDoc; 
    try 
    Printer.Canvas.Lock; 
    try 
     sh:=GetDC(0); 
     ph:=Printer.Canvas.Handle; 

     //TODO: make rect a bit smaller for a page margin 
     //TODO: get page size from printer settings, assume A4 here (210x297mm) 
     r.Left:=0; 
     r.Top:=0; 
     r.Right:=2100 * GetDeviceCaps(sh,LOGPIXELSX) div 254; 
     r.Bottom:=2970 * GetDeviceCaps(sh,LOGPIXELSY) div 254; 
     WebBrowser1.BoundsRect:=r; 

     SetMapMode(ph,MM_ISOTROPIC); 
     SetWindowExtEx(ph,r.Right,r.Bottom,nil); 
     SetViewportExtEx(ph,r.Right,r.Bottom,nil); 
     r.Right:=GetDeviceCaps(ph,HORZRES)-1; 
     r.Bottom:=GetDeviceCaps(ph,VERTRES)-1; 

     (WebBrowser1.ControlInterface as IViewObject).Draw(
     DVASPECT_CONTENT, 
     1, 
     nil,nil,0,ph,@r,nil,nil,0); 
    finally 
     Printer.Canvas.Unlock; 
    end; 
    Printer.EndDoc; 
    except 
    Printer.Abort; 
    raise; 
    end; 

的SetWindowExtEx和SetViewportExtEx設置縮放正確的,所以你可以使用的HTML/CSS單位「毫米」。

+0

'和1和1'位是一個錯字 - 應該是'選項和1 = 1然後' - 更正。 –

+0

網頁瀏覽器包含一些文本,一個表格(包含一些文本),然後包含表格下方的一些文本。所有的文本都是以希伯來語編碼的UTF-8編碼。使用上面的代碼,只有一個空的HTML表格出現在輸出中;沒有任何文字。 –

+0

此代碼會導致程序使用Windows-7使計算機崩潰。它適用於XP,但正如我在上面指出的那樣,文本丟失了。所以這不是一個可行的解決方案。 –

0

試試這個。

var 
    vIn, vOut: OleVariant; 
begin 
    WebBrowser_mail.ControlInterface.ExecWB(OLECMDID_PRINT, 
        OLECMDEXECOPT_PROMPTUSER, vIn, vOut) ; 
+0

我在我的發帖中確實包含了這個變體 - 讀到最後。我放棄了在Windows7下從webbrowser打印的想法,直到有人能夠解釋如何避免外部異常C015D00F。 –

0

每當我有問題,WB它有兩方面的原因:1)文件沒有完全裝B)WB部件不是「完全註冊」,因爲它是隱藏的表單等

對於上)我用了很多年的這段代碼:

var 
    CurDispatch: IDispatch; 
    DocLoaded: boolean; 


procedure TForm3.WebBrowser1DocumentComplete(ASender: TObject; 
    const pDisp: IDispatch; const URL: OleVariant); 
begin 
    if (pDisp = CurDispatch) then begin 
    CurDispatch := nil; {clear the global variable } 
    DocLoaded:=true; 
    end; 
end; 

procedure TForm3.WebBrowser1NavigateComplete2(ASender: TObject; 
    const pDisp: IDispatch; const URL: OleVariant); 
begin 
    if CurDispatch = nil then 
    CurDispatch := pDisp; { save for comparison } 
end; 

procedure TForm3.Button1Click(Sender: TObject); 
var 
    vIn, vOut: OleVariant; 

begin 
    DocLoaded:=false; 
    WebBrowser1.Navigate(EdLink.Text); 
    repeat 
    Application.ProcessMessages; 
    until DocLoaded; 

    WebBrowser1.ControlInterface.ExecWB(OLECMDID_PRINT, OLECMDEXECOPT_PROMPTUSER, vIn, vOut) 
end; 

如果問題仍然存在,嘗試把這個FormShow - 它解決了b):

WebBrowser1.HandleNeeded; 

WB再也沒有問題了。

不要忘記設置WebBrowser1.Silent:= true以在頁面中隱藏JavaScript錯誤。