LRESULT CWebOCWindow::OnPrint(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled) {
SAFEARRAYBOUND psabBounds[1];
SAFEARRAY *psaHeadFoot;
HRESULT hr = S_OK;
// Variables needed to send IStream header to print operation.
HGLOBAL hG = 0;
IStream *pStream= NULL;
IUnknown *pUnk = NULL;
ULONG lWrote = 0;
LPSTR sMem = NULL;
if (!webOC) {
ATLTRACE(_T("DoPrint: Cannot print - WebBrowser control not ready\n"));
goto cleanup;
}
// Initialize header and footer parameters to send to ExecWB().
psabBounds[0].lLbound = 0;
psabBounds[0].cElements = 3;
psaHeadFoot = SafeArrayCreate(VT_VARIANT, 1, psabBounds);
if (NULL == psaHeadFoot) {
// Error handling goes here.
goto cleanup;
}
VARIANT vHeadStr, vFootStr, vHeadTxtStream;
long rgIndices;
VariantInit(&vHeadStr);
VariantInit(&vFootStr);
VariantInit(&vHeadTxtStream);
// Argument 1: Header
vHeadStr.vt = VT_BSTR;
vHeadStr.bstrVal = SysAllocString(L"This is my header string.");
if (vHeadStr.bstrVal == NULL) {
goto cleanup;
}
// Argument 2: Footer
vFootStr.vt = VT_BSTR;
vFootStr.bstrVal = SysAllocString(L"This is my footer string.");
if (vFootStr.bstrVal == NULL) {
ATLTRACE(_T("DoPrint: Could not allocate memory in %s: Line %d\n"), __FILE__, __LINE__);
goto cleanup;
}
// Argument 3: IStream containing header text. Outlook and Outlook
// Express use this to print out the mail header.
if ((sMem = (LPSTR)CoTaskMemAlloc(512)) == NULL) {
ATLTRACE(_T("DoPrint: Could not allocate memory in %s: Line %d\n"), __FILE__, __LINE__);
goto cleanup;
}
// We must pass in a full HTML file here, otherwise this
// becomes corrupted when we print.
sprintf(sMem, "<html><body><strong>Printed By:</strong> Custom WebBrowser Host 1.0<p></body></html>\0");
// Allocate an IStream for the LPSTR that we just created.
hG = GlobalAlloc(GMEM_FIXED | GMEM_ZEROINIT, strlen(sMem));
if (hG == NULL) {
ATLTRACE(_T("DoPrint: Could not allocate memory in %s: Line %d\n"), __FILE__, __LINE__);
goto cleanup;
}
hr = CreateStreamOnHGlobal(hG, TRUE, &pStream);
if (FAILED(hr)) {
ATLTRACE(_T("OnPrint::Failed to create stream from HGlobal: %lX\n"), hr);
goto cleanup;
}
hr = pStream->Write(sMem, strlen(sMem), &lWrote);
if (SUCCEEDED(hr)) {
// Set the stream back to its starting position.
LARGE_INTEGER pos;
pos.QuadPart = 0;
pStream->Seek((LARGE_INTEGER)pos, STREAM_SEEK_SET, NULL);
hr = pStream->QueryInterface(IID_IUnknown, reinterpret_cast<void **>(&pUnk));
vHeadTxtStream.vt = VT_UNKNOWN;
vHeadTxtStream.punkVal = pUnk;
}
rgIndices = 0;
SafeArrayPutElement(psaHeadFoot, &rgIndices, static_cast<void *>(&vHeadStr));
rgIndices = 1;
SafeArrayPutElement(psaHeadFoot, &rgIndices, static_cast<void *>(&vFootStr));
rgIndices = 2;
SafeArrayPutElement(psaHeadFoot, &rgIndices, static_cast<void *>(&vHeadTxtStream));
//NOTE: Currently, the SAFEARRAY variant must be passed by using
// the VT_BYREF vartype when you call the ExecWeb method.
VARIANT vArg;
VariantInit(&vArg);
vArg.vt = VT_ARRAY | VT_BYREF;
vArg.parray = psaHeadFoot;
hr = webOC->ExecWB(OLECMDID_PRINT, OLECMDEXECOPT_DONTPROMPTUSER, &vArg, NULL);
if (FAILED(hr)) {
ATLTRACE(_T("DoPrint: Call to WebBrowser's ExecWB failed: %lX\n"), hr);
goto cleanup;
}
return 1;
//WebBrowser control will clean up the SAFEARRAY after printing.
cleanup:
VariantClear(&vHeadStr);
VariantClear(&vFootStr);
VariantClear(&vHeadTxtStream);
if (psaHeadFoot) {
SafeArrayDestroy(psaHeadFoot);
}
if (sMem) {
CoTaskMemFree(sMem);
}
if (hG != NULL) {
GlobalFree(hG);
}
if (pStream != NULL) {
pStream->Release();
pStream = NULL;
}
bHandled = TRUE;
return 0;
}