Click here to Skip to main content
15,884,388 members
Articles / Desktop Programming / MFC
Article

Using ActiveX controls in MFC more efficiently

Rate me:
Please Sign up or sign in to vote.
3.60/5 (10 votes)
10 Aug 2004CPOL4 min read 65.1K   26   5
Augmenting the interface access level provided by automatic code generation.

Introduction

Hello people, and welcome to this article. It's been a while since I've written one, so if there are bad spelling or other errors, please do notify me so I can fix them.

Background

There are already several articles here on Code Project that show the basic usage of ActiveX controls in MFC programs. If you are unfamiliar on how to add an ActiveX control to your MFC project, I recommend the article Using ActiveX Controls Example: Insert Internet Explorer into your Dialogs by Hazem Nasereddin.

As for the reasons of this article, we will come back to them soon.

The problem of wrapping ActiveX controls

By following the up-mentioned article, you can easily add a control to your program, and utilize its basic functionality. However, many controls also sport other interfaces that offer advanced functionality or settings. Some of these interfaces may be hidden, or be non-creatable, so basic querying of them won't work.

For a ground up example, let's continue on where Mr. Nasereddin left off. We have the web browser control in our dialog, and it's working well. We also have the member variable in our dialog class, and the IDispatch wrapper class for methods available through IWebBrowser2 and its bases. This interface offers a huge amount of things you can do with the control.

However, after navigating to a certain multi-framed web page, we now have an arbitrary need to find our the names of the frames on this page. There would be two ways to do this: either we use the IWebBrowser2 interface to get the document, and search it through there, or we somehow get access to the ITargetFrame2 interface of the browser.

The problem that arises now is that the wrapper class that was automatically generated for us does not offer a method that could be used for getting the ITargetFrame2 interface. So, how should we proceed?

Getting into the depths of IUnknown

Luckily, the wrapper class is derived from CWnd base class. This class is designed for holding ActiveX controls, and as such, it happens to provide us with a method called CWnd::GetControlUnknown. This method gives us a copy of the pointer to the created ActiveX object's IUnknown interface.

MC++
// Assuming that m_ctrlBrowser is the added member variable

// First, here is the IUnknown pointer
IUnknown* pUnk;

// Let's get the object's interface
pUnk = m_ctrlBrowser.GetControlUnknown();

Now, the pointer returned by GetControlUnknown is a copy of a pointer to the IUnknown. This same pointer is constantly being used by the MFC Framework to upkeep the control on your dialog. Needless to say, if you release this interface pointer, MFC ceases to be able to operate on the control, and if it happens to be that it is the last interface pointer on the object, the object will even shut itself down (self-destroy when all interfaces are released).

So, this interface pointer must NOT be released. When you no longer need the pointer, set it to NULL and forget about it.

The way up from the deep

So, what all nifty things can we do with this pointer, then? Easy enough: we now have complete access to every interface the object contains, whether they were creatable or not. We are operating on a level that was opened for us by the MFC Framework, and putting it short, we have complete access to the object.

Let's start by accessing the ITargetFrame2 interface. Following basic COM function calls, this happens by issuing the following:

MC++
// The interface pointer
ITargetFrame2* pFrame;

// Query for it
HRESULT hr = pUnk->QueryInterface( __uuidof( ITargetFrame2), (void**) &pFrame );

Hey! What is that __uuidof() call? This nifty function allows you to search all included modules for the GUID of an interface to which you know the name. Most type libraries (or headers generated from type libraries) grant you a short-cut by defining IID_* variables to identify the interface GUIDs. But not all of them. This function is for those 'not this time' -situations.

Final steps, conclusion

Here we are. We have a valid, working interface pointer that can be used to wreak havoc on our web browser control. The choices on what to do now are up to you. You can use the ITargetFrame2 interface pointer, or you can query for another interface on the browser control that you need.

The key issues of this article were to bring out the steps required in accessing the IUnknown interface, and through it, all other interfaces of the object. The biggest advantage of this approach is that the IUnknown pointer returned is not a newly created pointer, but a copy of an existing one. Thus, all interfaces that the object has become available, whether they were creatable or not. Just remember that all other interface pointers you query from the IUnknown one should be released normally.

For an example of accessing non-creatable interfaces, add a Microsoft RDP Client Control into your dialog. This control offers, by default, a very limited access to its interfaces, and by following this approach, all of its interfaces are available for us. Even the difficult process of automatically logging on to a Terminal Services server.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer (Senior) Cybercom Finland Oy
Finland Finland
I live in the Frozen North, in Finland. Although the opportunities for good jobs or sunny days are scarce here, I still like it here. But at some point I'll move abroad.. Oh, and yes, there ARE polar bears in here Smile | :)

I graduated as a B.Sc in Computer Science in 2006, and currently I'm employed by Cybercom Finland Oy, a world-wide software house. I mainly develop Windows Desktop software using Qt, .Net Framework and other relevant technologies.

When I'm not knee-depth in the code, I play computer games, Go or go to the gym. I love music, in all it's forms, and dancing is close to my heart. Or then I spend time with my friends. I like friends. You can never have enough of them Smile | :)

I'm a keen player of games. Simulations and RPG are the key words. Old-time games such as Mega Man are good as well, not forgetting the block-buster hits either.

Comments and Discussions

 
Newshello Pin
yangckw29-Dec-10 15:08
yangckw29-Dec-10 15:08 
QuestionFile operation & stock event Pin
ankea23-Jul-06 16:44
ankea23-Jul-06 16:44 
AnswerRe: File operation & stock event Pin
Antti Keskinen24-Jul-06 0:07
Antti Keskinen24-Jul-06 0:07 
GeneralDetails for the Very Big Problem Pin
Ahmed Charfeddine11-Jul-06 0:32
Ahmed Charfeddine11-Jul-06 0:32 
GeneralVery Big Problem Pin
Ahmed Charfeddine10-Jul-06 2:18
Ahmed Charfeddine10-Jul-06 2:18 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.