如何检测打印命令已在TWebBrowser中完成?

时间:2011-12-04 16:13:46

标签: delphi twebbrowser

procedure TForm1.Button1Click(Sender: TObject);
var 
  vaIn, vaOut: OleVariant;
begin
  WebBrowser1.Navigate('http://www.google.com');
  while WebBrowser1.ReadyState < READYSTATE_COMPLETE do
    Application.ProcessMessages;
  WebBrowser1.ExecWB(OLECMDID_PRINT, OLECMDEXECOPT_PROMPTUSER, vaIn, vaOut);

  // HOWTO: WAIT until print <strike>job</strike> dialog is done or canceled

  // UPDATE (1):
  WebBrowser1.Enabled := False;
  WebBrowser1.OnCommandStateChange := WebBrowser1CommandStateChange;
end;

procedure TForm1.WebBrowser1CommandStateChange(Sender: TObject; Command: Integer; Enable: WordBool);
begin
  Memo1.Lines.Add(Format('%d : %d : %d', [WebBrowser1.QueryStatusWB(OLECMDID_PRINT), Command, Ord(Enable)]));
  // TODO: after LAST event when the print dialog closes:
  // WebBrowser1.OnCommandStateChange := nil;
end;

预览也是如此: WebBrowser1.ExecWB(OLECMDID_PRINTPREVIEW, OLECMDEXECOPT_DODEFAULT, vaIn, vaOut);

我需要等待(或触发事件),直到Print / Print Preview对话框完成,用户选择了打印或取消。

更新(1)

基于this question我测试了OnCommandStateChange。 在“打印”对话框中>打印或取消后触发。但在对话框打开之前,它可以被激活1到2次

更新(2) 找到了一个可以解决问题的解决方法(这是一个基本想法):

procedure TForm1.WaitPrintDialog;
var
  t1, t2: DWORD;
  w, wpd: HWND;
begin
  t1 := GetTickCount();
  t2 := t1;
  wpd := 0;
  while ((wpd = 0) and (t2 - t1 <= 5000)) do // 5 sec timeout
  begin
    w := FindWindowEx(0, 0, 'Internet Explorer_TridentDlgFrame', nil);
    if (w <> 0) and (GetWindow(w, GW_OWNER) = Self.Handle) then
    begin
      wpd := w;
    end;
    Application.ProcessMessages;
    t2 := GetTickCount();
  end;
  if wpd <> 0 then // found and no timeout
    while IsWindow(wpd) and (not Application.Terminated) do
    begin
      Application.HandleMessage; // Application.ProcessMessages;
    end;
end;

用法:

WebBrowser1.ExecWB(OLECMDID_PRINT, OLECMDEXECOPT_PROMPTUSER, vaIn, vaOut);
WaitPrintDialog;
ShowMessage('Print Done!');

适用于OLECMDID_PRINTOLECMDID_PRINTPREVIEW 请告诉我你的想法...

3 个答案:

答案 0 :(得分:3)

当我一直在寻找解决方案时,我几天前找到了PRINT_WAITFORCOMPLETION标志,但无法让它发挥作用。诀窍很简单(参见note nr.4)。我将ExecWB命令的OLECMDID_PRINT方法的第三个参数作为变体类型VT_I4传递但是它已经过载而且PRINT_WAITFORCOMPLETION必须转换为完全错误键入VT_I2,Delphi中的内容表示为smallint

以下是如何使打印对话框模态化(也是偶然回答this)。

procedure TForm1.Button1Click(Sender: TObject);
var
  vaIn: OleVariant;
  vaOut: OleVariant;
const
  PRINT_WAITFORCOMPLETION = $02;
begin
  WebBrowser1.Navigate('http://www.google.com');
  while WebBrowser1.ReadyState < READYSTATE_COMPLETE do
    Application.ProcessMessages;

  vaIn := OleVariant(VarAsType(PRINT_WAITFORCOMPLETION, varSmallint));
  WebBrowser1.ExecWB(OLECMDID_PRINT, OLECMDEXECOPT_PROMPTUSER, vaIn, vaOut);

  ShowMessage('Print dialog has been closed ...');
end;

不幸的是,如果用户将文档发送到打印机队列或取消了对话框,则无法获得任何反馈。 IDM_PRINT没有输出值,这将返回此值。另一件事是,即使用户接受打印对话框,也不意味着文档将被物理打印。为此,您必须像Remy所说的那样监视打印机队列。

答案 1 :(得分:2)

假脱机打印作业并由OS在后台输出到打印机驱动程序。 WebBrowser不会告诉您何时完成。打印作业排队后,ExecWB()退出。您必须直接监视打印机队列以了解它正在做什么。

答案 2 :(得分:0)

以下代码使“打印”对话框成为模式对话框,这样只有在使用“打印”对话框完成后,他才会返回应用程序。

WebBrowser1.ExecWB OLECMDID_PRINT, OLECMDEXECOPT_DODEFAULT, 2, 0