2

I have a two-part question. I need to add supporting for printing to an existing dialog-based MFC project. The document being printed is composed using HTML. I know that I can add HTML-based dialog but how do you add a capability for printing to it?

PS. I need this to be able to set the print page size according to a program's needs.

c00000fd
  • 20,994
  • 29
  • 177
  • 400
  • Perhaps telling us what you have tried and what went wrong would be a good starting point? – Ed Heal Sep 20 '13 at 22:29
  • @EdHeal: I was able to find how to add print and print view support to a view-based MFC app, but I can't figure out how to port it to a dialog based app. – c00000fd Sep 20 '13 at 22:33
  • Why not post the code – Ed Heal Sep 20 '13 at 22:37
  • 1
    [This](http://marc.durdin.net/2011/07/demystifying-printing-with-the-microsoft-webbrowser-control-and-showhtmldialogex-2/) might be a good starting point. – noseratio Sep 22 '13 at 01:24
  • 1
    @Noseratio: Very nice. Thanks. I need to decipher it from Delphi now... man, that's one ugly language :) – c00000fd Sep 22 '13 at 08:15

1 Answers1

1

Inspired by the excellent Marc's Durdin's article, I've done some more spelunking. There actually appears to be an easier way to supply custom DEVMODE and DEVNAMES and print without using an HTML dialog or a custom IE print template. That, in turn, should allow to set custom printer, paper size, orientation, etc.

I have a playground WebBrowser ActiveX host project in C++, similar to this. I implement IOleCommandTarget interface on my OLE site object (IOleClientSite). Now here's the interesting part, when printing gets invoked (via Ctrl-P or via IDM_PRINT), the browser control calls back the site object as IOleCommandTarget::Exec(&CGID_DocHostCommandHandler, OLECMDID_PRINT2, &VARIANT(VT_UNKNOWN), NULL). The 3rd parameter contains an object which is passed as IUnknown, but when queried for IDispatch it supports all the same __IE_* properties, available via IDispatch::Invoke:

__IE_TemplateUrl (VT_EMPTY)
__IE_ParentHWND (VT_UINT)
__IE_HeaderString (VT_BSTR)
__IE_FooterString (VT_BSTR)
__IE_OutlookHeader (VT_UNKNOWN)
__IE_BaseLineScale (VT_INT)
__IE_uPrintFlags (VT_UINT)
__IE_ContentDocumentUrl (VT_BSTR)
__IE_ContentSelectionUrl (VT_BSTR)
__IE_PrinterCMD_Printer (VT_BSTR)
__IE_PrinterCMD_Device (VT_BSTR)
__IE_PrinterCMD_Port (VT_BSTR)
__IE_BrowseDocument (VT_UNKNOWN)
__IE_TemporaryFiles (VT_ARRAY)
__IE_PrinterCMD_DevNames (VT_I4)
__IE_PrinterCMD_DevMode (VT_I4)
__IE_PrintType (VT_BSTR)

I haven't taken this further yet, but I think it should be possible to alter any of the them and return S_OK from IOleCommandTarget::Exec, and expect the browser control to take in the changes.

I expect it to work in a similar way for IDM_PRINTPREVIEW / OLECMDID_PRINTPREVIEW2, but I haven't verified that yet. I'll play with this a bit more, as time allows. Meanwhile, you're welcome to try it out and share your results.

noseratio
  • 59,932
  • 34
  • 208
  • 486
  • 1
    Thanks again. I need to catch up on reading those articles you linked to and I'll post an update... – c00000fd Sep 22 '13 at 21:28
  • A quick follow-up. I'm struggling to find a C++ sample that can illustrate how to use those IE print templates. This article has a lot of verbal info but no source code: http://msdn.microsoft.com/en-us/library/bb250434(VS.85).aspx Am I missing something? – c00000fd Sep 23 '13 at 00:15
  • The MSDN article contains the [link](http://download.microsoft.com/download/6/8/3/683DB9FE-8D61-4A3C-B7B8-3169FF70AE9F/printtemplates.exe). There's an app inside, it has [Template Source] button to show the sample print template sources. They did not provide the C++ sources though. – noseratio Sep 23 '13 at 00:39
  • Yeah. I discovered that. Unfortunately it is too ambiguous without a C++ code. I started looking into it because the `printtemplates.exe` app itself doesn't seem to print anything on my Windows 8 desktop with IE10. So I'm now looking into using a direct Win32 printing into a DeviceContext: http://read.pudn.com/downloads76/sourcecode/windows/system/289362/hwprint.cpp__.htm What do you think about such approach? – c00000fd Sep 23 '13 at 01:29
  • Using DC is classic, but I'm not sure how it can help here. There used to be [IHTMLElementRender::DrawToDC](http://msdn.microsoft.com/en-us/library/aa752273(v=vs.85).aspx), but it's deprecated (and crashing) since Microsoft has implemented GPU rendering with IE9. – noseratio Sep 23 '13 at 02:01
  • Yes, I saw that. I was able to find `OleDraw` instead that seems to be supported. I'm currently stuck though at determining the size of the HTML document -- width & height in pixels. – c00000fd Sep 23 '13 at 02:30
  • That should not be a problem, if `OleDraw` does what you need, check [this](http://stackoverflow.com/a/18907279/1768303). Are you going to print a one-page document, anyway? The whole thing about IE print templates is they allow to properly paginate an HTML document, using `DEVICERECT` and `LAYOUTRECT` elements. – noseratio Sep 23 '13 at 02:35
  • Thanks. I thought to bypass the multiple page printing issue by finding out the size of a page from a printer and then by splitting the document onto pages manually once its in the DeviceContext (provided that I can find out the size of an HTML document loaded in my web control.) I may go back to using IE print templates if this approach fails. Again, the reason I went away from IE print templates is a very sketchy documentation, plus that Microsoft sample I quoted above didn't really work for me... – c00000fd Sep 23 '13 at 02:43
  • Here's the production IE print template: `res://C:\Windows\System32\en-US\ieframe.dll.mui/preview.dlg`, if you're brave enough to study it :) – noseratio Sep 23 '13 at 02:54
  • I should admit, you were right about printing to DC. It prints the IE window's client area and not the document :) In other words, it's useless. So I went back to using IE print templates but that didn't go far either. For some reason my test app randomly crashes when I use them. Do you know of any compilable C++ project that can show how to use those IE print templates? – c00000fd Sep 24 '13 at 04:46
  • Right out of my head, I don't. [This](http://resources.webappearance.com/res/appdev/IEPrintTemplates.aspx) looks relevant, but they actually take the-other-way-round approach, by invoking the printing with an hosted by the page itself. – noseratio Sep 24 '13 at 04:57
  • I might have gotten closer to make it work with print templates. If you read the docs for `IDM_PRINT`: http://msdn.microsoft.com/en-us/library/aa769937(v=vs.85).aspx it has the `PRINT_WAITFORCOMPLETION` flag that seems to resolve the crashing issue. What I can't figure out is how to use it alongside the print template path. Any ideas? – c00000fd Sep 24 '13 at 09:49
  • It appears there is no documented way of doing it, check [this](http://microsoft.public.windows.inetexplorer.ie5.programming.components.webbrowser-ctl.narkive.com/rrYevX7f/waiting-for-custom-ie-print-templates-to-complete-how). – noseratio Sep 24 '13 at 10:35
  • Thanks. It's funny I just came off studying that same page :) You don't happen to know where IE's default print template stored, do you? – c00000fd Sep 25 '13 at 07:44
  • I do, check a few comments above :) Enable script debugging in IE options and navigate to `res://ieframe.dll/preview.dlg`. – noseratio Sep 25 '13 at 08:04
  • @noseratio, do you have a working sample code to illustrate the calling of PRINT2 or PRINTPREVIEW2? If possible, would you mind take a look at my question: https://stackoverflow.com/questions/60419546/mfc-how-to-set-header-and-footer-for-print-preview-programmatically. Thanks. – user180574 Feb 28 '20 at 20:24
  • @user180574, sorry I don't. We've stopped using the legacy IE-specific stuff long ago. – noseratio Mar 02 '20 at 00:21