【问题标题】:How to detect Print command has finished in TWebBrowser?如何在 TWebBrowser 中检测打印命令已完成?
【发布时间】:2011-12-04 16:13:45
【问题描述】:
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 请告诉我你的想法...

【问题讨论】:

    标签: delphi twebbrowser


    【解决方案1】:

    当我一直在寻找解决方案时,我在几天前发现了 PRINT_WAITFORCOMPLETION 标志,但无法让它发挥作用。诀窍很简单(参见note nr. 4)。我将OLECMDID_PRINT 命令的ExecWB 方法的第三个参数作为变体类型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 所说,您必须监控打印机队列。

    【讨论】:

    • PRINT_WAITFORCOMPLETION 标志即使与 OLECMDEXECOPT_DONTPROMPTUSER 命令选项一起使用也可以使用,其中行的处理意味着文档已发送到打印机队列。
    • 似乎完全符合我对OLECMDID_PRINT 的要求,但不适用于OLECMDID_PRINTPREVIEW
    • 是的,IDM_PRINTPREVIEW 没有可选标志。但我发现this post(如果我做对了)使用了一些未记录的东西,即使IDM_PRINTPREVIEW 也是一个包含 5 个元素的数组,但很难说它是否有效。我对安全数组不熟悉,所以试着问另一个问题如何在 TWebBrowser 中检测 PrintPreview 命令是否完成? ;)
    • 我试图重写我之前对 Delphi 的评论中链接的帖子,但它似乎不起作用(或者我在某处犯了错误)。顺便提一句。预览对话框本身是最顶层含义的模态。如果需要,我会让其他人在一个单独的问题中进行进一步调查:)
    • 当您离解决方案如此之近时不要退出;)顺便说一句,我不认为您在上一条评论中发布的代码可以解决问题。他们仍然使用$02 作为数组的第 5 个元素。即:dwFlags = 2;
    【解决方案2】:

    打印作业在后台由操作系统假脱机并输出到打印机驱动程序。 WebBrowser 不会告诉您何时完成。一旦打印作业排队,ExecWB() 就会退出。您必须直接监控打印机队列才能知道它在做什么。

    【讨论】:

    • 我想检测打印对话框何时完成,而不是实际打印作业何时完成。
    【解决方案3】:

    下面的代码使打印对话框成为一个模型对话框,这样只有当打印对话框的使用完成后,他才会回到应用程序。

    WebBrowser1.ExecWB OLECMDID_PRINT, OLECMDEXECOPT_DODEFAULT, 2, 0
    

    【讨论】:

      猜你喜欢
      • 2012-12-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多