Reputation: 8312
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
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