现在的位置: 首页 > 综合 > 正文

Creating and Using a COM Object by Using Visual Studio 2005

2018年04月05日 ⁄ 综合 ⁄ 共 20675字 ⁄ 字号 评论关闭

Creating and Using a COM Object by Using Visual Studio 2005

In this exercise, you will create a COM object that you will use from within a .NET Compact Framework 2.0 application. This exercise is the starting point for this section of the HOL, in which you will build a complete Pocket PC application through a number of exercises. As you will find out, you can use Visual Studio 2005 to create managed .NET Compact Framework applications and native C++ applications for devices—even with ATL or MFC support.

To open an existing solution and add a new project to it

  1. On the desktop computer, click Start | All Programs | Microsoft Visual Studio 2005 | Microsoft Visual Studio 2005.
  2. In Visual Studio 2005, click File | Open | Project/Solution.
  3. In the Open Project dialog box, browse to C:/Program Files/Windows Mobile Developer Samples/HOLs/MEDC06_HOL301/HOL301Exercise1.
  4. Select HOL301Exercise1.sln, and then click Open. The solution opens.
  5. In Solution Explorer, right-click Solution 'HOL301Exercise1' (1 project), and then select Add | New Project to add a new project to the solution.
  6. In the Add New Project dialog box under Project types, ensure that Other Languages | Visual C++ | Smart Device is selected.

    Note   Depending on your Visual Studio configuration, the Visual C++ project type may be located at the outer-most outline level instead of under Other Languages.

  7. Under Templates, ensure ATL Smart Device Project is selected.
  8. In the Name box, change the name to MyCOMObject, as shown in Figure 1.

     

    Click here for larger image

    Figure 1. Add New Project dialog box. Click the thumbnail for a larger image.

  9. Click OK to start the ATL Smart Device Project Wizard.

    The wizard is going to assist you in creating your COM object. You need to provide some basic information, but you can leave most of the settings as they are.

  10. On the welcome page of the wizard, click Next.
  11. On the Platforms page of the ATL Smart Device Project Wizard, as shown in Figure 2, be sure that only Windows Mobile 5.0 Pocket PC SDK is listed under Selected SDKs. Use the add and remove arrow buttons to move the appropriate SDKs.

     

    Click here for larger image

    Figure 2. Platforms page of the ATL Smart Device Project Wizard. Click the thumbnail for a larger image.

  12. Click Next.
  13. On the Application Settings page of the ATL Smart Device Project Wizard, be sure that Dynamic-link library (DLL) is selected under Server type, and be sure that the additional options boxes are not selected.
  14. Click Finish to exit the wizard.

    The wizard has created a new project called MyCOMObject that contains all of the code to act as a COM component. To turn this project into a meaningful COM object, you have to add functionality for your specific COM object.

To add a new class to the COM object

  1. In Solution Explorer, right-click the MyCOMObject project, point to Add, and then click Class.

    (Alternatively, you can click Project | Add Class from the Visual Studio 2005 menu.)

  2. In the Add Class dialog box, in the Categories tree, select ATL, and be sure that ATL Simple Object is selected in the list of available templates, as shown in Figure 3.

     

    Click here for larger image

    Figure 3. Add Class dialog box. Click the thumbnail for a larger image.

  3. Click the Add button.

    The ATL Simple Object Wizard starts. In this wizard, you will give your new object a name and set some specific object settings.

  4. On the left side of the Welcome to the ATL Simple Object Wizard page, select Names.
  5. In the C++ Short name box, type SimpleCalc. Leave all of the other values as default, as shown in Figure 4.

     

    Click here for larger image

    Figure 4. Names page of the ATL Simple Object Wizard. Click the thumbnail for a larger image.

  6. Click Next.
  7. On the Options page of the ATL Simple Object Wizard, under Threading model, select Free.
  8. Under Interface, select Custom, as shown in Figure 5.

     

    Click here for larger image

    Figure 5. Options page of the ATL Simple Object Wizard. Click the thumbnail for a larger image.

  9. Click Finish to close the wizard and create the new class.

    The ATL Simple Object Wizard has created a number of new files for you, in which you will add methods and interfaces that bring functionality to your COM object. The COM object that you are about to implement contains a few basic math functions, like add, subtract, multiply, and divide. The functionality is straightforward, but it should help you understand how a managed .NET Compact Framework application can interoperate with a COM object.

You will now work on the implementation of SimpleCalc. All methods that you are going to write will be exposed through COM interfaces. A COM client can access the methods and, thanks to COM Interop, a managed client application can access SimpleCalc's methods (as you will see in this HOL).

To implement the functionality of SimpleCalc

  1. In Visual Studio 2005, change to Class View by clicking View | Class View or by using the keyboard shortcut CTRL+W+C.
  2. In the Class View pane, expand MyCOMObject, right-click the interface ISimpleCalc, and then select Add | Add Method, as shown in Figure 6.

    The Add Method Wizard appears. In this wizard, you will specify the signature of the method that you are going to add.

     

    Click here for larger image

    Figure 6. Adding a method to ISimpleCalc. Click the thumbnail for a larger image.

  3. In the Add Method Wizard, type Add in the Method name box.
  4. Type int in the Parameter type box.
  5. Type iFirstValue in the Parameter name box.
  6. Select the in check box under Parameter attributes.
  7. Click the Add button.
  8. Type int in the Parameter type box.
  9. Type iSecondValue in the Parameter name box.
  10. Select the in check box under Parameter attributes.
  11. Click the Add button.
  12. Type int* in the Parameter type box.
  13. Type piResult in the Parameter name box.
  14. Select the retval check box under Parameter attributes.
  15. Click the Add button.

    The Add Method Wizard's Names page should now look like Figure 7.

     

    Click here for larger image

    Figure 7. Names page of the Add Method Wizard. Click the thumbnail for a larger image.

  16. Click Finish.

    You have just created a new empty method with a COM interface. You can find the method's interface in the header file SimpleCalc.h, the (still empty) implementation in the source file SimpleCalc.cpp. Next, you will add a few more methods to the component. You will also automatically see the new methods appear in the Class View pane.

  17. In the Class View pane, right-click the interface ISimpleCalc, and then click Add | Add Method.
  18. Type Subtract in the Method name box.
  19. Repeat Steps 4 through 16 to add parameters to the method. You must enter exactly the same parameters.
  20. Repeating the same steps, add a new method called Multiply.
  21. Again, repeating the same steps, add a new method called Divide.

    The only thing left to do to finish your COM component is add functionality.

  22. In Solution Explorer, (View | Solution Explorer View), open the file SimpleCalc.cpp by double-clicking it. You can find this file under Source Files.
  23. Find the method CSimpleCalc::Add, and then add the following statement to the method (prior to the statement return S_OK).
    *piResult = iFirstValue + iSecondValue;
    
  24. Find the method CSimpleCalc::Subtract, and then add the following statement to the method (prior to the statement return S_OK).
    *piResult = iFirstValue - iSecondValue;
    
  25. Find the method CSimpleCalc::Multiply, and then add the following statement to the method (prior to the statement return S_OK).
    *piResult = iFirstValue * iSecondValue;
    
  26. Find the method CSimpleCalc::Divide, and then replace all of its code with the following code example.
    if (iSecondValue != 0)
    {
        *piResult = iFirstValue / iSecondValue;
        return S_OK;
    }
    else
    {
        *piResult = 0;
        return E_FAIL;
    }
    
  27. Compile the COM object by clicking Build | Build Solution or by pressing F6.

    Assuming you didn't get any compilation errors, you are now going to use the COM object inside a managed application.

To use the COM object inside a managed application

  1. In Solution Explorer, browse to the project ManagedCOMClient, and then expand it (if it is not expanded already).
  2. Open the file Form1.cs in the form designer by double-clicking it in Solution Explorer.

    To save time, the user interface is already created for you, which should look like Figure 8.

     

    Click here for larger image

    Figure 8. User interface for ManagedCOMClient. Click the thumbnail for a larger image.

    The next thing you will do is add functionality to the application to make use of MyCOMObject. Before you can use the COM component, you have to add a reference to it to make it available in the managed application. When you are adding a reference to a COM object, code is automatically generated by Visual Studio 2005 to be able to use your COM object inside a managed application.

    You need a so-called Interop Assembly to be able to call into a COM object. The Interop Assembly contains managed definitions of COM interfaces and types. It can be generated manually by the Type Library Importer (tlbimp.exe), or it can be generated automatically by Visual Studio 2005 when you add a reference to the COM object's Type Library (*.tlb) file, which you will see in a moment. To a managed client application, the COM object looks like a managed type, as shown in Figure 9. The Runtime Callable Wrapper hides all COM details for you.

     

    Click here for larger image

    Figure 9. Calling a COM component from a managed client. Click the thumbnail for a larger image.

    To generate an Interop Assembly to be able to access the COM component from within managed code, you need to add a reference to MyCOMObject.tlb.

  3. In Solution Explorer, right-click References, and then click Add Reference to add a reference to the ManagedCOMClient project.
  4. In the Add Reference dialog box, click the Browse tab, and then browse to MyCOMObject.tlb in C:/Program Files/Windows Mobile Developer Samples/HOLs/MEDC06_HOL301/HOL301Exercise1/MyCOMObject/Windows Mobile 5.0 Pocket PC SDK (ARMV4I)/Debug.

    Note   You can easily browse to the type library file by clicking the Up One Level button on the toolbar of the Add Reference dialog box, after which you can browse through the MyCOMObject project tree to reach the MyCOMObject.tlb file.

  5. Click OK to add the selected reference to the project.

    You can now use the methods from MyCOMObject as if it were a managed object, as you will see when you are adding functionality to the button click event handlers of the ManagedCOMClient application.

  6. In Solution Explorer, right-click Form1.cs, and then click View Code.
  7. Create an alias for the "System.Runtime.InteropServices" namespace by adding the following statement immediately under the other using statements at the beginning of the Form1.cs file (this is the file into which all other code will be added as well).
    using System.Runtime.InteropServices;
    
  8. Create an alias for your COM component by adding the following statement.
    using MyCOMObjectLib;
    
  9. Add the following instance variable to the Form1 class.
    private ISimpleCalc calculator = new SimpleCalc();
    

    You now have declared an interface variable of type ISimpleCalc and instantiated it with a SimpleCalc object. This is, in fact, an instantiation of your COM component.

  10. Add the following code to the btnAdd_Click event handler.
    int firstValue = Convert.ToInt32(tbValue1.Text);
    int secondValue = Convert.ToInt32(tbValue2.Text);
    int result = calculator.Add(firstValue, secondValue);
    tbResult.Text = result.ToString();
    

    As you saw when entering the Add method for the calculator, it looks like a managed object and even has full Microsoft IntelliSense support. If you compare the managed call to the Add method as defined in the COM component, you will see a remarkable difference.

    The signature of the managed Add method looks like the following.

     int Add (int iFirstValue, int iSecondValue);
    

    The signature of the COM Add method looks like the following.

      HRESULT Add ([in]int iFirstValue,
                                            [in]int iSecondValue, 
                                            [out, retval]int* piResult);
    

    The translation of the COM method to the managed method happened automatically when you added a reference to the Type Library file.

  11. Add the following code to the btnSubtract_Click event handler.
    int firstValue = Convert.ToInt32(tbValue1.Text);
    int secondValue = Convert.ToInt32(tbValue2.Text);
    int result = calculator.Subtract(firstValue, secondValue);
    tbResult.Text = result.ToString();
    
  12. Add the following code to the btnMultiply_Click event handler.
    int firstValue = Convert.ToInt32(tbValue1.Text);
    int secondValue = Convert.ToInt32(tbValue2.Text);
    int result = calculator.Multiply(firstValue, secondValue);
    tbResult.Text = result.ToString();
    
  13. Add the following code to the btnDivide_Click event handler.
    int firstValue = Convert.ToInt32(tbValue1.Text);
    int secondValue = Convert.ToInt32(tbValue2.Text);
    int result = calculator.Divide(firstValue, secondValue);
    tbResult.Text = result.ToString();
    
  14. Compile the entire solution, including the code that you just entered by clicking Build | Build Solution or by pressing F6.

    Assuming you didn't get compilation errors, you can now test the ManagedCOMClient application in the Windows Mobile 5.0 Pocket PC emulator.

To test the ManagedCOMClient application in the emulator

  1. In Visual Studio 2005, press F5 or select Debug | Start Debugging to start the application in debugging mode.
  2. In the Deploy ManagedCOMClient dialog box, be sure that the Windows Mobile 5.0 Pocket PC Emulator is selected, and then click the Deploy button.

    Note   If you receive an error during deployment that indicates that the process or file is in use, this means that the program is still running on the emulator and must be closed before a new copy can be deployed and run. This error may appear anytime in the lab that you deploy the emulator. See Appendix A in this HOL for instructions about exiting a running application.

  3. Be sure that the emulator is visible by clicking its button in the Windows taskbar.

    After a while, you will see the application running inside the Windows Mobile 5.0 Pocket PC emulator. Now it is time to test the application. It may take some time to deploy the application for the first time. The first time you are using the emulator, prior to deploying the application, the .NET Compact Framework 2.0 will be deployed to the emulator as well. When the .NET Compact Framework 2.0 is already found on the emulator, this step is skipped.

  4. Enter different numbers in the text boxes for Value1 and for Value2.
  5. Click all four buttons one after another, and examine the result. Every time a button is clicked, a method in the COM object is called. The running application should look like Figure 10.

    Figure 10. ManagedCOMClient application running in the emulator

  6. Enter the number 0 in the Value2 box, and then click the divide button. You will see an exception being thrown, as shown in Figure 11.

     

    Click here for larger image

    Figure 11. Exception that is thrown from the divide method call. Click the thumbnail for a larger image.

    This is the default behavior when a method call of a COM object returns a value other than S_OK as HRESULT. Therefore, it is always advisable to add exception handling when calling into COM objects.

  7. Stop the debugger by clicking Debug | Stop Debugging.
  8. Change the code for the btnDivide_Click event handler in source file Form1.cs to the following.
    int firstValue = Convert.ToInt32(tbValue1.Text);
    int secondValue = Convert.ToInt32(tbValue2.Text);
    try
    {
        int result = calculator.Divide(firstValue, secondValue);
        tbResult.Text = result.ToString();
    }
    catch
    {
        tbResult.Text = "Undefined";
    }
    
  9. In Visual Studio, press F5 or click Debug | Start Debugging to start the application in debugging mode.
  10. In the Deploy ManagedCOMClient dialog box, be sure that the Windows Mobile 5.0 Pocket PC Emulator is selected, and then click the Deploy button.
  11. Watch what happens if you enter the number 0 in the Value2 box and then click the divide button (at least the behavior is now much more acceptable, simply by adding an exception handler), as shown in Figure 12.

    Figure 12. The application continues to run when attempting to divide by zero

  12. Close the application by clicking the ok button in the upper-right corner of the application.

In the .NET Compact Framework 2.0, it is not only possible to call methods on COM components without the need to write your own wrapper. It is also possible to call back from the COM object into the managed client, thanks to the fact that the .NET Compact Framework 2.0 also allows calling from native to managed code.

You will now extend MyCOMObject by adding a new interface and implementing callback functionality. The callback functionality that you are implementing simply displays a message passed from the COM component to a managed message box. Note that even though callbacks are supported, activation of .NET types from COM is not supported.

To callback from COM into the managed client

  1. In Solution Explorer, double-click the MyCOMObject.idl to open it. You can find the file in the tree view by clicking MyComObject | Source Files.
  2. In the MyCOMObject.idl file, look for the definition of the line import atliface.idl, and then manually add a new interface immediately below it. Enter the following code for the new interface.
    [
      object,
      uuid(),
      helpstring("ISimpleCalcCallBack Interface"),
      pointer_default(unique)
    ]
    interface ISimpleCalcCallBack : IUnknown{
      [, helpstring("method ShowMsg")] HRESULT ShowMsg([in] LPTSTR 
    pMsg); };
  3. Add a new universally unique identifier (UUID) to the interface to distinguish it from other interfaces. (You can generate a UUID in Visual Studio 2005 by clicking Tools | Create GUID.)
  4. In the Create GUID dialog box, be sure that the Registry Format option is selected, as shown in Figure 13.

    Figure 13. Generating a new GUID to identify the newly created interface

  5. Click New GUID, and then immediately click Copy.
  6. Click Exit to close the Create GUID dialog box.
  7. In MyCOMObject.idl, place the cursor between the brackets behind the UUID attribute in the code that you just entered, and then paste the created GUID in there. Be sure to remove the braces that were copied as part of the GUID.
  8. Verify that the interface you added in the MyCOMObject.idl file, including the GUID you pasted in it, looks like the following.
    [
      object,
      uuid(54BE93A8-84F3-424a-AE3F-04A6EA833BD5),
      helpstring("ISimpleCalcCallBack Interface"),
      pointer_default(unique)
    ]
    interface ISimpleCalcCallBack : IUnknown{
       [, helpstring("method ShowMsg")] HRESULT ShowMsg([in] LPTSTR 
    pMsg); };

    Note   The value of the GUID that you pasted in differs from the value that you see in this example. You have just created a new interface for your COM component, and this interface contains only one method called ShowMsg. This is the only method that the ISimpleCalcCallBack interface exposes. This method acts as the callback from managed code, so you will write the implementation for this particular interface later in managed code. First, however, you need to do something else. To store the callback function in the COM object, you have to pass a reference to it from managed code. Therefore, you will add another method to the ISimpleCalc interface.

  9. In the Class View pane, right-click the interface ISimpleCalc, and then select Add | Add Method.

    This step displays the Add Method Wizard, in which you will specify the signature of the method you are going to add.

  10. Type Initialize in the Method name box.
  11. Type ISimpleCalcCallBack* as the Parameter type.
  12. Type callbackInterface in the Parameter name box.
  13. Select the in check box under Parameter attributes.
  14. Click the Add button, and then click the Finish button.

    You have now created all interfaces, but to be able to use the callback function, you also have to implement the Initialize method.

  15. In Visual Studio 2005, in Solution Explorer, double-click SimpleCalc.cpp to open it. You can find this file under Source Files.
  16. Find the CSimpleCalc::Initialize method, and then add the following code to the method (prior to the statement return S_OK).
    pClientCallback = callbackInterface;
    
    // Because you are using a new interface for the first time, be
    // sure to increment its reference count.
    pClientCallback->AddRef();
    
    // and callback into managed code for the first time
    pClientCallback->ShowMsg(_T("Managed Callback installed!"));
    
  17. Find the CSimpleCalc::Divide method, and then add the following code to the method to give the user an error message. Add the code prior to the statement return E_FAIL.
    if (pClientCallback)
        pClientCallback->ShowMsg(_T("Oops, you should not divide by 
    zero!"));

    As you can see in the code for the Initialize method, the callback method is stored locally. However, you still need to declare a variable to store the callback method into. Finally, you are also providing some code to release the interface after you finish with the object.

  18. In Solution Explorer, double-click SimpleCalc.h to open it. You can find this file under Header Files.
  19. Add the following code toward the end of the CSimpleCalc class.
    private:
        ISimpleCalcCallBack* pClientCallback;
    
  20. In the SimpleCalc.h header file, look for the FinalRelease method inside the CSimpleCalc class, and then add the following code to the method.
    if (pClientCallback)
        pClientCallback->Release();
    
  21. Compile the COM component that you just extended by clicking Build | Build Solution, or by pressing F6.

    Before you can use the callback functionality that you just have implemented, you need to provide the COM component with a managed function that can act as a callback. You will create the callback method as part of a new class that you will now add to the ManagedCOMClient project.

  22. In Solution Explorer, right-click the project ManagedCOMClient, and then select Add | Class.
  23. In the Add New Item dialog box, be sure that Class is selected in the Templates list.
  24. Change the name of the class to NewMsgNotification.cs, and then click the Add button.
  25. Replace all of the code in the NewMsgNotification.cs source file that you just created with the following code.
    using System;
    using System.Collections.Generic;
    using System.Text;
    using System.Windows.Forms;
    using System.Runtime.InteropServices;
    using MyCOMObjectLib;
    
    namespace ManagedCOMClient
    {
        public class NewMsgNotification : ISimpleCalcCallBack
        {
            public void ShowMsg(string message)
            {
                MessageBox.Show(message);
            }
        }
    }
    

    As you can see, the NewMsgNotification class derives from the ISimpleCalcCallBack interface, which is the interface that you created in the COM component. The interface expects one function, called ShowMsg, that is defined in the class as well. Finally, you need to connect the callback function to the COM component.

  26. In Code view, open the Form1.cs source file in Visual Studio 2005.
  27. Add an instance variable for the new class that you just created by adding the following code.
    private NewMsgNotification newMsg = new NewMsgNotification();
    
  28. Find the constructor of the Form1 class, and then add a call to the Initialize method of the calculator COM object to tell the COM object what callback function to use (add the following statement immediately under InitializeComponent()):
    calculator.Initialize((ISimpleCalcCallBack)newMsg);
    
  29. In Visual Studio, press F5 or click Debug | Start Debugging to start the application in debugging mode.
  30. In the Deploy ManagedCOMClient dialog box, be sure that the Windows Mobile 5.0 Pocket PC Emulator is selected, and then click the Deploy button.

    After a while, you will see the application running inside the Windows Mobile 5.0 Pocket PC emulator. Immediately, you will notice that a message appears and informs you that the managed callback is installed, as shown in Figure 14.

     

    Click here for larger image

    Figure 14. Managed callback installation dialog box. Click the thumbnail for a larger image.

    This message box resides inside managed code (in the newly created class), but it is called from inside the COM component. Now, watch what happens if you divide by zero.

  31. Click ok to close the message.
  32. Type 1 in the Value1 box, and then type 0 for Value2.
  33. Click the divide button, and verify that another message appears, as shown in Figure 15.

    Figure 15. The divide by zero message

  34. Click ok to close the message, and then close the application by clicking the ok button in the upper-right corner of the application.

This step concludes the first exercise. You have created a COM component by using ATL and used that component inside a managed client application. Not only is it possible to call methods in the COM component from inside managed code, but it is also possible to register a managed callback function in the COM component. As you just have seen, it is very simple to access COM components from within managed code—without the need to write your own wrapper—as was the case in the .NET Compact Framework version 1.0. In the next exercise, you will use a popular, existing COM component inside a managed application.

抱歉!评论已关闭.