Hook IE commands (Print, Copy, etc.) from ActiveX

I've written an ActiveX viewer control, similar to Adobe's PDF viewer control, for my own file format (call it ".xyz" format).  So a URL like http://server/file.xyz shows file.xyz within IE, just like the PDF viewer shows you http://server/file.pdf within IE.

What I need to do now is redirect IE commands like Print, Page Setup, Select All and Copy to my control.  The PDF viewer does this - when you're looking at a PDF, File/Print launches Adobe's own Print dialog.  Likewise, Edit/Select All (or Ctrl+A) selects all the text within the PDF, and Edit/Copy (or Ctrl+C) copies the selected text.

Adobe install a BHO as well as their viewer control, and I could do the same, but I can't find how to hook these commands from a BHO either.
LVL 14
Who is Participating?
Microsoft has a standard difinition for IE events, such as Save, print, Edit/Copy, etc. You just hook your BHO into IE by following BHO programming rules. Then dispatch different event to your different function.

You can find some sample code from www.codeproject.com( search BHO). Following their samples, I succed in several DLL/BHO program.

IE BHO is difficult in programming.

Good Luck!
RichieHindleAuthor Commented:
RanjeetRain: Thanks for the reference, but I've read that document and it doesn't mention any of the commands I need to hook.

lukeblu: The CodeProject PopupBlocker project (http://www.codeproject.com/atl/popupblocker.asp) looks to have what I need - thanks!

Everything I'd seen on BHOs (including the article that RanjeetRain cited) had talked only about DWebBrowserEvents2, which doesn't include the commands I'm interested in.  The PopupBlocker article talks also about IOleCommandTarget, which you can use to handle these commands: OLECMDID_PRINT, OLECMDID_PAGESETUP, OLECMDID_SELECTALL and OLECMDID_COPY (plus a host of others).

I'll have a go with this tomorrow and post the results.

Assuming this works, I then need a way for my BHO to communicate with my ActiveX viewer control, to pass on the commands to it.  Any hints on that?  I'm sure I can figure it out, but any pointers to relevant documentation or sample code would be very welcome!
Ultimate Tool Kit for Technology Solution Provider

Broken down into practical pointers and step-by-step instructions, the IT Service Excellence Tool Kit delivers expert advice for technology solution providers. Get your free copy now.

RichieHindleAuthor Commented:
Re. "I then need a way for my BHO to communicate with my ActiveX viewer control": the second version of the PopupBlocker project (http://www.codeproject.com/atl/popupblocker2.asp) solves a similar problem using a DOM extension, which seems like a rather heavyweight solution.  I'm also not convinced that it'll work for me, because I potentially have multiple simultaneous viewer objects (eg. in different frames) and I need to communicate with the right one...
RichieHindleAuthor Commented:
More info: I've just found KB article 167956 (http://support.microsoft.com/default.aspx?scid=kb;EN-US;167956) which implies that an ActiveX control can implement IOleCommandTarget directly, without needing a BHO.  If that's true, it's the perfect solution.  I'll try it tomorrow and post the results.  (lukeblu will still get the points, for leading me to IOleCommandTarget.)
RichieHindleAuthor Commented:
Making the ActiveX control implement IOleCommandTarget doesn't work.  It only receives a small subset of the commands (OLECMDID_STOP is the only one I could find that worked; none of the ones I'm interested in worked).

I've discovered that installing a BHO needs admin privileges, which is no good for me - ordinary users need to install this stuff (and it'll be used in the corporate world, where the majority of users don't have admin privileges).

I've disabled the Adobe BHO and their ActiveX PDF viewer *still* hooks File/Print, Edit/Select All and Edit/Copy, so there must be a way of doing it that doesn't rely on a BHO.  It does it rather badly - for instance, if you put a PDF and an HTML document together as two frames of a frameset, give the focus to the HTML frame, and go Edit/Select All, the PDF steals the Select All away from the HTML page.

I believe they're subclassing the IE main window to do their hooking, rather than using an official COM technique.  The Window Proc of the main IE window changes when you first visit a PDF - that's a bit of a giveaway!  Their OCX imports SetWindowsHookEx from user32 as well, so they must be using Windows hooks for something (based on some playing with Spy++, I think they're using a keyboard hook to capture accelerator keys like Ctrl+P that would normally be handled by IE).

Using subclassing and Windows hooks makes me cringe, but it looks like the only way to go, given the non-admin requirement (when I originally asked the question I didn't know that BHOs required admin rights to install).
I think, IOleCommandTarget is not good in compatibilities with future IE even if it works with current IE. If a user doesn't have the permission to install BHO, the only solution is JavaApplet. But Applet never use Menu of IE although it can show PDF or other formats of docs. So BHO still is your best solution.

BHO can be loaded dynamicly, not static registred in Win registry file. This situation needs lower permission, maybe.

About multi-IE instances, I still look for a solution too. In fact, I am not an expert in BHO. I just did BHO 5 months ago, only before you. So very happy to discuss with you.

I believe too, Adobe use some special tech. to hook their functions. I ever read a article about replacing a function in current class. This way can hook more powerful function into IE. But I forget the url. I will continue to look for that article. If I get it again, I tell you. Maybe it is helpful to you.

RichieHindleAuthor Commented:
"I think, IOleCommandTarget is not good in compatibilities with future IE": http://support.microsoft.com/default.aspx?scid=kb;EN-US;167956 implies that it's safe for hooking the Stop command, but I think that's the only command for which it's safe.

"BHO can be loaded dynamicly, not static registred in Win registry file.":  Interesting - how?  Everything I've read says that BHOs are loaded from HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Browser Helper Objects

"I will continue to look for that article. If I get it again, I tell you.":  Yes please!  It sounds very useful.

I have another couple of ideas that I'm trying out - I'll post the results here when I know whether they might work or not.
RichieHindleAuthor Commented:
I've now achieved what I want through a series of slightly hacky mechanisms:

To hook the menu commands, I subclass the main IE window using SetWindowLong(GWL_WNDPROC).
To hook the toolbar command, I subclass the parent window of IE's rebar, which is called WorkerW or WorkerA.
To hook the keyboard accelerators, I use a WH_GETMESSAGE hook.

In all cases, I'm careful to only register my hooks when my control is displayed full-screen within IE (which I test by checking that there's only one "Internet Explorer_Server" window between my control and the main frame, and that my control covers the whole of that window).  In the case of some of the keyboard accelerators (eg. Ctrl+C for Copy) I only hook them when my control has the focus.  In other cases I only hook them when the containing Internet Explorer is the active window (in case there are multiple top-level IE windows owned by the same thread).

So my ActiveX control now successfully hooks Print, Save, Select All, Copy and Find, and it does it as a plain old ActiveX control, without needing a BHO and without needing to be installed as an administrator.  I'm both glad (from the point of view of meeting my users' needs) and dismayed (from the point of view of IE security) that this is possible.

lukeblu: Had I needed a BHO, your posts would have been very helpful - thanks!
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.