Jessica Brown
Jessica Brown

Reputation: 8312

How to use OleVariant parameters to TWebBrowser Print dialog?

I'm trying to implement custom headers and footers when printing from a TWebBrowser, as per the information in this Microsoft knowledge base question (KB267240). The knowledgebase article is quite helpful and even includes a lengthy code example, however, the code example is in C++ not Delphi, so I've had to attempt to convert the necessary data structure into Delphi code myself. I'm not terribly confident I've correctly converted the part of the code I need.

Here's probably the most important part of that article, where it explains what is supposed to go in my paramater vaIn in my code below:

When you use an OLECMDID enumeration of the OLECMDID_PRINT element together with the ExecWB method, you can specify extended printing information by passing in the SAFEARRAY structure through the VARIANT argument pvaIn. This SAFEARRAY data type takes a maximum of five items:

1) A string (BSTR) that contains a custom header.
2) A string (BSTR) that contains a custom footer.
3) ...

When I run the code I've written, it successfully removes the original header and footer, but does not replace it with my new header and footer strings, so I'm wondering if my code is incorrect in some way (or several ways), or if I simply shouldn't expect it to work since I'm using IE 9 and not a version in the 4-6 range that was current at the time the knowledgebase article was written.

var
  vaIn, vaOut: OleVariant;
begin
    vaIn := VarArrayCreate([0,1], varOleStr); 
    vaIn[0] := VarAsType('new header', VarOleStr); //header
    vaIn[1] := VarAsType('new footer', VarOleStr); //footer

    // Show print-preview dialog 
    WebBrowser1.ControlInterface.ExecWB(OLECMDID_PRINTPREVIEW,
      OLECMDEXECOPT_DONTPROMPTUSER, vaIn, vaOut);
end;

Upvotes: 3

Views: 1688

Answers (1)

Coder12345
Coder12345

Reputation: 3753

This prints with custom header/footer. Custom headers don't for OLECMDID_PRINTPREVIEW, but they do work for OLECMDID_PRINT. The key is to use VT_ARRAY or VT_BYREF as the TVariantArg has to be passed by reference.

Code credit: TEmbeddedWB at https://github.com/7even11/Delphi-EmbeddedWB

procedure PrintWithHeaderFooter(ControlInterface: IWebBrowser2; Header, Footer: PWideChar; Options: OLECMDEXECOPT);
var
  saBound: TSafeArrayBound;
  psaHeadFoot: PSafeArray;
  vaIn, vaOut: TVariantArg;
  vHeadStr, vFootStr: TVariantArg;
  rgIndex: LongInt;
begin
  try
    saBound.lLbound := 0;
    saBound.cElements := 2;
    psaHeadFoot := SafeArrayCreate(VT_VARIANT, 1, saBound);
    vHeadStr.vt := VT_BSTR;
    vHeadStr.bstrVal := SysAllocString(Header);
    vFootStr.vt := VT_BSTR;
    vFootStr.bstrVal := SysAllocString(Footer);
    rgIndex := 0;
    OleCheck(SafeArrayPutElement(psaHeadFoot, rgIndex, vHeadStr));
    rgIndex := 1;
    OleCheck(SafeArrayPutElement(psaHeadFoot, rgIndex, vFootStr));
    vaIn.vt := VT_ARRAY or VT_BYREF;
    vaIn.parray := psaHeadFoot;
    ControlInterFace.ExecWB(OLECMDID_PRINT, Options,
      OleVariant(vaIn), OleVariant(vaOut));
    if vHeadStr.bstrVal <> nil then
      SysFreeString(vHeadStr.bstrVal);
    if vFootStr.bstrVal <> nil then
      SysFreeString(vFootStr.bstrVal);
  except
  end;
end;

procedure Print(ControlInterface: IWebBrowser2; bHideSetup: Boolean = False; bCustomHeaderFooter: Boolean = False; Header: string = ''; Footer: string = '');
var
  vaIn, vaOut: OleVariant;
begin
  if DocumentLoaded(ControlInterface.Document) then
  begin
    if bCustomHeaderFooter then
    begin
      if bHideSetup then
        PrintWithHeaderFooter(ControlInterface, TaskAllocWideString(Header), TaskAllocWideString(Footer), OLECMDEXECOPT_DONTPROMPTUSER)
      else
        PrintWithHeaderFooter(ControlInterface, TaskAllocWideString(Header), TaskAllocWideString(Footer), OLECMDEXECOPT_PROMPTUSER);
    end
    else
      if bHideSetup then
        ControlInterface.ExecWB(OLECMDID_PRINT, OLECMDEXECOPT_DONTPROMPTUSER, vaIn, vaOut)
      else
        ControlInterface.ExecWB(OLECMDID_PRINT, OLECMDEXECOPT_PROMPTUSER, vaIn, vaOut)
  end;
end;

Upvotes: 0

Related Questions