Click here to Skip to main content
15,867,594 members
Articles / Programming Languages / Visual Basic
Article

Automation of COM Dialogs in a DLL

Rate me:
Please Sign up or sign in to vote.
4.79/5 (20 votes)
28 Apr 20044 min read 110.9K   2.2K   47   27
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.

Image 1

Creating the MFC COM DLL that holds the component

Create a new MFC DLL project:

Image 2

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.

Image 3

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.

Image 4

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.

Image 5

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

Image 6

Image 7

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.

Image 8

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.

Image 9

Image 10

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.

VB.NET
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


Written By
Software Developer
Canada Canada
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
QuestionThanks for sharing your great job, it works fine !!! Pin
Alan040714-Nov-16 23:35
Alan040714-Nov-16 23:35 
QuestionYour code don't work! :( Pin
Sun-Mi Kang23-Sep-13 20:34
Sun-Mi Kang23-Sep-13 20:34 
I try to use your code but ..

This statemens can't read class..
Is there any solution to fix?

hrx = pFactory.CreateInstance( __uuidof(ComDialogFactory) );

C++
void CTestAppDlg::OnButton1() 
{
	// TODO: Add your control notification handler code here

	HRESULT hrx;

	IComDialogFactoryPtr pFactory;
	hrx = pFactory.CreateInstance( __uuidof(ComDialogFactory) );
	ASSERT( SUCCEEDED( hrx ) );   // --> Cant read class..

	if ( SUCCEEDED( hrx ) )
	{
		IMyComDlgPtr pDlg;
		pDlg = pFactory->GetDialog();
		pDlg->PressMe();
		TRACE( "::createInstance Success to initialize" );
	}
	else
	{
		TRACE( "::createInstance Failed to CreateInstance" );
	}
}

QuestionEvent Sink in Client Pin
Sharjith22-Apr-11 8:30
professionalSharjith22-Apr-11 8:30 
QuestionCom client of your Dll Pin
Inbal Dror KA19-Apr-07 2:28
Inbal Dror KA19-Apr-07 2:28 
AnswerRe: Com client of your Dll Pin
intensely_radioactive22-Apr-07 14:50
intensely_radioactive22-Apr-07 14:50 
QuestionRe: Com client of your Dll Pin
Inbal Dror KA25-Apr-07 20:37
Inbal Dror KA25-Apr-07 20:37 
GeneralRe: Com client of your Dll Pin
Inbal Dror KA29-Apr-07 3:30
Inbal Dror KA29-Apr-07 3:30 
AnswerRe: Com client of your Dll Pin
intensely_radioactive2-May-07 15:59
intensely_radioactive2-May-07 15:59 
GeneralRe: Com client of your Dll Pin
Ralph_L27-Nov-07 9:30
Ralph_L27-Nov-07 9:30 
GeneralEnter key killing the dialog Pin
Ger Hayden2-Oct-06 9:07
Ger Hayden2-Oct-06 9:07 
AnswerRe: Enter key killing the dialog Pin
intensely_radioactive2-Oct-06 9:51
intensely_radioactive2-Oct-06 9:51 
QuestionWhy Can Not DoModal() Pin
Jason Tian8-Feb-06 15:17
Jason Tian8-Feb-06 15:17 
AnswerRe: Why Can Not DoModal() Pin
intensely_radioactive8-Feb-06 17:53
intensely_radioactive8-Feb-06 17:53 
GeneralRe: Why Can Not DoModal() Pin
Jason Tian11-Feb-06 17:42
Jason Tian11-Feb-06 17:42 
GeneralDialog Object Is Never Deleted Pin
hobiedave26-Jan-06 16:45
hobiedave26-Jan-06 16:45 
GeneralRe: Dialog Object Is Never Deleted Pin
intensely_radioactive31-Jan-06 10:53
intensely_radioactive31-Jan-06 10:53 
GeneralExcellent Pin
senproin13-Dec-05 18:51
senproin13-Dec-05 18:51 
GeneralRe: Excellent Pin
intensely_radioactive31-Jan-06 10:55
intensely_radioactive31-Jan-06 10:55 
GeneralIn static Lib , or collection of Dlg´s Pin
FriendOfAsherah19-Aug-05 19:17
FriendOfAsherah19-Aug-05 19:17 
GeneralRe: In static Lib , or collection of Dlg´s Pin
intensely_radioactive20-Aug-05 7:01
intensely_radioactive20-Aug-05 7:01 
GeneralHelp Pin
ShamanYoung23-Jun-05 16:33
ShamanYoung23-Jun-05 16:33 
GeneralRe: Help Pin
intensely_radioactive23-Jun-05 18:00
intensely_radioactive23-Jun-05 18:00 
GeneralExcellent Pin
adrian cooper21-Dec-04 22:07
adrian cooper21-Dec-04 22:07 
GeneralCall back functions Pin
crazydave2227-Oct-04 2:10
crazydave2227-Oct-04 2:10 
GeneralRe: Call back functions Pin
intensely_radioactive25-Nov-04 2:52
intensely_radioactive25-Nov-04 2:52 

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.