Click here to Skip to main content
Click here to Skip to main content

Automation of COM Dialogs in a DLL

, 28 Apr 2004
Rate this:
Please Sign up or sign in to vote.
Automation of COM Dialogs in a DLL

Introduction

Long have I wanted to reuse dialogs without having to worry about resource ids, DLLs, headers and libraries. I hoped MFC and COM would take care of that but never found a good article explaining how to do it. There are several books and articles about COM, MFC, ATL, components but I could never find one that would just show me how to put a COM dialog in a COM DLL and let me manage it through automation. I've finally figured out a simple process and share the process here.

I could see that you could create dialog resources, new classes for them, and enable the Automation for them, but you couldn’t create instances of them. I’m not sure why, since they derive from CCmdTarget. This article describes how to create a COM Automated dialog that you can bring up from any COM client (i.e VB or VC++) and control it.

Below is a UML diagram showing the component and test application architecture of this simple prototype and the relevant operations involved.

Creating the MFC COM DLL that holds the component

Create a new MFC DLL project:

Make sure it is an Regular DLL using shared MFC DLL and make sure “Automation” is checked. This creates the necessary entry points for the DLL to be registered.

Create the Dialog that will be automated

Now, add a dialog resource to the project. Add a button and double click it. Tell the Class Wizard to create a new class.

Create the dialog and make sure the “Automation” radio button is selected. Note that you cannot enable the “Createable by type ID”. This caused me lots of problems and we’ll see how to get around it later.

Add an event handler to the button press, for example:

void CMyComDlg::OnPressMe() 
{
     // TODO: Add your control notification handler code here
     AfxMessageBox("Pressed");
}

Now, you can add automation controls to the dialog. Using the Class Wizard is easiest. Choose “Add Method

Add some implementation to the automation handler to call the same button handler, for example:

void CMyComDlg::PressMe() 
{
     // TODO: Add your dispatch handler code here
     OnPressMe();
}

Creating the COM Dialog factory

At this point, this COM dialog can be seen outside the dialog, but you cannot create an instance of it. To fix that, we add an object that can be created dynamically. For example, use the Class Wizard to add a new class, derived from CCmdTarget. Make sure the Createable by type ID is checked.

Click OK. I’ve noticed a bug in Dev Studio, that sometimes, the interface doesn’t show up. To get it to appear, just close the project and reopen it. That should fix it.

Otherwise, use the class wizard to add a new Automation interface for the new factory.

Note the return type is of LPDISPATCH. That is the key to passing the dialog out of the DLL to COM Automation clients. In the implementation, you return the dispatch interface pointer through COM to the client.

//////////////////////////////////////////////////////////
// CComDialogFactory message handlers

#include "MyComDlg.h"

LPDISPATCH CComDialogFactory::GetDialog() 
{
     // Yes this is a leak, the *dlg would be a member of the class.
     CMyComDlg *dlg = new CMyComDlg();
     // Set the argument as true to increase the ref count
     return dlg->GetIDispatch(TRUE);
}

Build the project.

Run the regsvr32.exe on the DLL to register the component.

Visual Basic Client

You can now create a VB project to use this dialog and control it easily.

Create a VB Exe project, Choose Project References and browse to the newly compiled type library (TLB file).

Add a button and a handler to the VB form. The code below creates the factory, then creates the dialog. Note the dialog doesn’t appear, you would have to add a “DoModal” or show dialog automation method to get that to happen.

Private Sub Command1_Click()
    ' create the factory
    Dim factory As ComDlgInDll.ComDialogFactory
    Set factory = New ComDlgInDll.ComDialogFactory
    ' allocate the dialog
    Dim dlg As ComDlgInDll.MyComDlg
    ' let the factory make it
    Set dlg = factory.GetDialog
    ' press the dialog button.
    dlg.PressMe
End Sub

Visual C++ Client

The VC++ client isn’t quite as simple. Create a new MFC project (Doc/view, dialog, whatever) add a menu or button and a handler. You have to make sure you initialize the COM libraries if the MFC project doesn’t do it for you in OnInitDialog or InitInstance:

     HRESULT hrx;
     hrx = CoInitialize(NULL);
     ASSERT( SUCCEEDED( hrx ) );

And a similar call to close the libraries OnDestory or ExitInstance:

     CoUninitialize();

To use the component, you do this:

// Import the COM type library
#import "..\Debug\ComDlgInDll.tlb" no_namespace
void CTestAppDlg::OnButton1() 
{
     // TODO: Add your control notification handler code here
     HRESULT hrx;
     // Use smart pointers to create an instance of the factory
     IComDialogFactoryPtr pFactory;
     hrx = pFactory.CreateInstance( __uuidof(ComDialogFactory) );
     ASSERT( SUCCEEDED( hrx ) );
     if ( SUCCEEDED( hrx ) )
     {
          // Get the factory to show the dialog
          IMyComDlgPtr pDlg;
          pDlg = pFactory->GetDialog();
          // And activate the button through COM
          pDlg->PressMe();
     }
}

Conclusion

At this point you have a truly reusable dialog component, with defined interfaces that you can access through any COM client. There is no worrying about copying headers and cpp files around, making sure your resource ID’s don’t overlap and merging or managing of resource files. Just the DLL and the type library.

The code in this article has minimal error checking, and is meant for illustrative purposes only. The code has been tested on VC++ 6.0 SP5, Win 2K SP4

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here

Share

About the Author

intensely_radioactive
Software Developer
Canada Canada
No Biography provided

Comments and Discussions

 
QuestionYour code don't work! :( Pinmembersun mi Kang23-Sep-13 21:34 
QuestionEvent Sink in Client PinmemberSharjith22-Apr-11 9:30 
QuestionCom client of your Dll PinmemberInbal Dror KA19-Apr-07 3:28 
AnswerRe: Com client of your Dll Pinmemberintensely_radioactive22-Apr-07 15:50 
QuestionRe: Com client of your Dll PinmemberInbal Dror KA25-Apr-07 21:37 
GeneralRe: Com client of your Dll PinmemberInbal Dror KA29-Apr-07 4:30 
AnswerRe: Com client of your Dll Pinmemberintensely_radioactive2-May-07 16:59 
GeneralRe: Com client of your Dll PinmemberRalph_L27-Nov-07 10:30 
GeneralEnter key killing the dialog PinmemberGer Hayden2-Oct-06 10:07 
AnswerRe: Enter key killing the dialog Pinmemberintensely_radioactive2-Oct-06 10:51 
QuestionWhy Can Not DoModal() PinmemberJason Tian8-Feb-06 16:17 
AnswerRe: Why Can Not DoModal() Pinmemberintensely_radioactive8-Feb-06 18:53 
GeneralRe: Why Can Not DoModal() PinmemberJason Tian11-Feb-06 18:42 
GeneralDialog Object Is Never Deleted Pinmemberhobiedave26-Jan-06 17:45 
GeneralRe: Dialog Object Is Never Deleted Pinmemberintensely_radioactive31-Jan-06 11:53 
GeneralExcellent Pinmembersenproin13-Dec-05 19:51 
GeneralRe: Excellent Pinmemberintensely_radioactive31-Jan-06 11:55 
GeneralIn static Lib , or collection of Dlg´s PinmemberFriendOfAsherah19-Aug-05 20:17 
GeneralRe: In static Lib , or collection of Dlg´s Pinmemberintensely_radioactive20-Aug-05 8:01 
GeneralHelp PinmemberShamanYoung23-Jun-05 17:33 
GeneralRe: Help Pinmemberintensely_radioactive23-Jun-05 19:00 
GeneralExcellent Pinmemberwaxie21-Dec-04 23:07 
GeneralCall back functions Pinmembercrazydave2227-Oct-04 3:10 
GeneralRe: Call back functions Pinmemberintensely_radioactive25-Nov-04 3:52 
GeneralModeless Dialogs Pinmemberyfnl7-May-04 11:55 

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

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

| Advertise | Privacy | Terms of Use | Mobile
Web04 | 2.8.141220.1 | Last Updated 29 Apr 2004
Article Copyright 2004 by intensely_radioactive
Everything else Copyright © CodeProject, 1999-2014
Layout: fixed | fluid