Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Beginner's Tutorial: Calling Visual Basic ActiveX DLLs from Visual C++

0.00/5 (No votes)
18 Nov 1999 1  
  • Download source - 8 Kb
  • This tutorial is based off of the MSDN Article #ID: Q194873. But, for a beginner, following these MSDN articles can be intimidating to say the least. One of the most often asked questions I see as a Visual C++ and Visual Basic programmer is how to call a VB DLL from VC++. Well, I am hoping to show you exactly that today. I am not going to go over the basic details of COM as this would take too long, so I am assuming you have an understanding of VB, VC++ and a little COM knowledge. It's not too hard to learn; just takes a little time. So let's get started.

    The first thing you need to do is fire up Visual Basic 6 (VB 5 should work as well). With VB running, create a new "ActiveX DLL" project. Rename the project to "vbTestCOM" and the class to "clsTestClass". You can do this by clicking in the VB Project Explorer Window on the Project1 item (Step 1), then clicking in the Properties window and selecting the name property (Step 2). Do the same for the Class. Click on the class (Step 3), then the name property and enter the name mentioned above (Step 4). Your project so far should look like the folowing right hand side picture:

    Naming the Project

    Ok, now we are ready to add some code to the VB Class. Click on the "Tools" menu, then select the "Add Procedure" menu item. The Add Procedure window will open up. In this window we need to add some information. First (Step 1) make sure the type is set to Function. Second (Step 2) enter a Function name called "CountStringLength". Finally hit the Ok button and VB will generate the new function in the class.

    Add Procedure Window

    You should have an empty function with which to work. The first thing we will do is specify a return type and an input parameter. Edit your code to look like this:

    Public Function CountStringLength(ByVal strValue As String) As Long
    
    End Function
    

    What are we doing here? We are taking one parameter, as a String type in this case, then returning the length through the return type, which is a Long. We specify the input parameter as ByVal, meaning VB will make a copy of this variable and use the copy in the function, rather than the default ByRef, which passes the variable by reference. This way we can be sure that we do not modify the string by accident that was passed to us by the calling program. Let's add the code now.

    Public Function CountStringLength(ByVal strValue As String) As Long
    	If strValue = vbNullString Then
            	CountStringLength = 0
        	Else
            	CountStringLength = Len(strValue)
        	End If
    End Function
    

    In the first line of code we are checking to see if the calling program passed us an empty, or NULL, string. If so we return 0 as the length. If the user did pass something other than an empty string, then we count it's length and return the length back to the calling program.

    Now would be a good time to save your project. Accept the default names and put it in a safe directory. We need to compile this project now. Go to the File menu and select the "Make vbCOMTest.dll..." menu item.

    Compiling the ActiveX DLL

    The compiler will produce a file called surprisingly enough: vbCOMTest.dll. The compiler will also do us the favor of entering this new DLL into the system registry. We have finished the VB side of this project, so let's start the VC++ side of it. Fire up a copy of VC++, then select from the menu, "New Project". The New Project window should appear. Select a "Win32 Console Application" (Step 1), then give it a name of "TestVBCOM" (Step 2). Finally, enter a directory you want to build this project in (Step 3 - your directory will vary from what I have entered).

    VC++ New Project Window

    Click on the "OK" button and the "Win32 Console Application - Step 1 of 1" window will appear. Leave everything on this page as the default, and click the "Finish" button. One final window will appear after this titled "New Project Information". Simply click the "Ok" button here. You should now have an empty Win32 Console project. Press the "Ctrl" and hit the "N" key. Another window titled "New" will appear. Select the "C++ Source File" (Step 1), then enter the new name for this file called, "TestVBCOM.cpp" (Step 2 - make sure the Add to Project checkbox is checked and the correct project name is in the drop down combo box), then click the "Ok" button to finish.

    Adding a New C++ Source File

    Now we are going to get fancy! You need to go to your Start Menu in Windows and navigate to the "Visual Studio 6" menu and go into the "Microsoft Visual Studio 6.0 Tools" sub-menu. In here you will see an icon with the name "OLE View". Click on it.

    Starting OLE View

    The OLE View tool will open up. You will see a window similar to this one:

    Starting OLE View

    Collapse all the trees, if they are not already. This will make it easier to navigate to where we want to go. Highlight the "Type Libraries" (Step 1) and expand it. You should see a fairly massive listing. We need to locate our VB DLL. Now, remember what we named the project? Right, we need to look for vbTestCOM. Scroll down until you find this. Once you have found it, double click on it. A new window should appear - the "ITypeLib Viewer" window. We are only interested in the IDL (Interface Definition Language) code on the right side of the window. Select the entire IDL text and hit the "Ctrl" and "C" buttons to copy it to the clipboard.

    Copying the IDL file

    You can close this window and the OLE View window now as we are done with the tool. We need to add the contents of the IDL file into our VC++ project folder. Go to the folder you told VC++ to create your project in and create a new text file there (If you are in Windows Explorer, you can right click in the directory and select "New" then scroll over following the arrow and select "Text Document"). Rename the text document to "vbCOMTEST.idl". Then double click on the new IDL file (VC++ should open it if you named it correctly with an IDL extension). Now paste the code in the file by pressing the "Ctrl" and "V" keys. The IDL text should be pasted into the file. So far, so good. Now, this IDL file is not going to do us much good until we compile it. That way, VC++ can use the files it generates to talk to the VB DLL. Let's do that now. Open a DOS window and navigate to the directory you created your VC++ project in. Once in that directory, at the prompt you need to type the following to invoke the MIDL compiler:

    E:\VCSource\TestVBCOM\TestVBCOM\midl vbTestCOM.idl /h vbTestCOM.h
    

    Hit the "Enter" key and let MIDL do its magic. You should see results similar to the following:

    Compiling the IDL file with the MIDL compiler

    Close the DOS window and head back into VC++. We need to add the newly generated vbTestCOM.h and vbTestCOM_i.c files to the project. You can do this by going to the "Project" menu, then selecting the "Add to Project" item, and scrolling over to the "Files" menu item and clicking on it. A window titled, "Insert Files into Project" will open. Select the two files highlighted in the next picture, then select the "Ok" button.

    Adding the files generated by MIDL

    These two files were generated by MIDL for us, and VC++ needs them in order to talk to the VB DLL (actually VC++ does not need the "vbCOMTest_i.c" file in the project, but it is handy have in the project to review). We are going to add the following code to the "TestVBCOM.cpp" file now, so navigate to that file in VC++ using the "Workspace" window. Open the file by double clicking it and VC++ will display the empty file for editing.

    Updated Workspace Window

    Now add the following code to the "TestVBCOM.cpp" file:

    #include <iostream.h>
    
    #include <comdef.h>
    
    #include "vbTestCOM.h"
    
    
    void main()
    {
       	// Declare an HRESULT and a pointer to the clsVBTestClass interface
    
       	HRESULT		hr;
    	_clsVBTestClass	*IVBTestClass = NULL;
    	
    	// Now we will intilize COM
    
    	hr = CoInitialize(0);
    
    	// Use the SUCCEEDED macro and see if we can get a pointer 
    
    	// to the interface
    
    	if(SUCCEEDED(hr))
    	{
    		hr = CoCreateInstance( CLSID_clsVBTestClass,
    					NULL,
    					CLSCTX_INPROC_SERVER,
    					IID__clsVBTestClass, 
    					(void**) &IVBTestClass);
    		
    		// If we succeeded then call the CountStringLength method, 
    
    		// if it failed then display an appropriate message to the user.
    
    		if(SUCCEEDED(hr))
    		{
    			long		ReturnValue;
    			_bstr_t		bstrValue("Hello World");
    			
    			// We can test this HR as well if we wanted to
    
    			hr = IVBTestClass->CountStringLength(bstrValue,
    							&ReturnValue);
    
    			cout << "The string is: " << ReturnValue << " characters in
    							length." << endl;
    			// We can test this HR as well if we wanted to
    
    			hr = IVBTestClass->Release();
    		}
    		else
    		{
    			// Something went wrong
    
    			cout << "CoCreateInstance Failed." << endl;
    		}
    	}
    	// Uninitialize COM
    
    	CoUninitialize();
    }
    

    If all the code is entered in correctly, then press the "F7" key to compile this project. Once the project has compiled cleanly, then press the "Ctrl" and the "F5" keys to run it. In the C++ code, we include the MIDL created "vbTestCOM.h" file, the "Comdef.h" file for the _bstr_t class support and the "iostream.h" file for the "cout" support. The rest of the comments should speak for themselves as to what's occurring. This simple tutorial shows how well a person can integrate VB and VC++ apps together using COM. Not too tough actually.

    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