Compartilhar via


Walkthrough: Creating a Basic Windows Runtime Component Using WRL

 

The new home for Visual Studio documentation is Visual Studio 2017 Documentation on docs.microsoft.com.

The latest version of this topic can be found at Walkthrough: Creating a Basic Windows Runtime Component Using WRL.

This document shows how to use the Windows Runtime C++ Template Library (WRL) to create a basic Windows Runtime component. The component adds two numbers and raises an event when the result is prime. This document also demonstrates how to use the component from a Windows 8.x Store app that uses JavaScript.

Prerequisites

To create a basic Windows Runtime component that adds two numbers

  1. In Visual Studio, create a Visual C++ WRLClassLibrary project. The document Class Library Project Template describes how to download this template. Name the project Contoso.

  2. In Contoso.cpp and Contoso.idl, replace all instances of "WinRTClass" with "Calculator".

  3. In Contoso.idl, add the Add method to the ICalculator interface.

            HRESULT Add([in] int a, [in] int b, [out, retval] int* value);
    
  4. In Contoso.cpp, add the Add method to the public section of the Calculator class.

                HRESULT __stdcall Add(_In_ int a, _In_ int b, _Out_ int* value)
                {
                    if (value == nullptr)
                    {
                        return E_POINTER;
                    }
                    *value = a + b;
                    return S_OK;
                }
    

    Important

    Because you’re creating a COM component, remember to use the __stdcall calling convention.

    We recommend that you use _Out_ and other source annotation language (SAL) annotations to describe how a function uses its parameters. SAL annotations also describe return values. SAL annotations work with the C/C++ Code Analysis tool to discover possible defects in C and C++ source code. Common coding errors that are reported by the tool include buffer overruns, uninitialized memory, null pointer dereferences, and memory and resource leaks.

To use the component from a Windows 8.x Store app that uses JavaScript

  1. In Visual Studio, add a new JavaScript Blank App project to the Contoso solution. Name the project CalculatorJS.

  2. In the CalculatorJS project, add a reference to the Contoso project.

  3. In default.html, replace the body section with these UI elements:

        <div>
            <input id="a" />
            <input id="b" />
            <p id="result">Result:</p>
            <button onclick="Add()">Add</button>
        </div>
    
  4. In default.js, implement the OnClick function.

    function Add() {
        "use strict";
    
        var calculator = new Contoso.Calculator();
    
        var a = document.getElementById("a");
        var b = document.getElementById("b");
    
        document.getElementById("result").innerHTML = "Result: " + calculator.add(a.value, b.value);
    }
    

    Note

    In JavaScript, the first letter of a method name is changed to lowercase to match the standard naming conventions.

To add an event that fires when a prime number is calculated

  1. In Contoso.idl, before the declaration of ICalculator, define the delegate type, PrimeNumberEvent, which provides an int argument.

        [uuid(3FBED04F-EFA7-4D92-B04D-59BD8B1B055E), version(COMPONENT_VERSION)]
        delegate HRESULT PrimeNumberEvent(int primeNumber);
    

    When you use the delegate keyword, the MIDL compiler creates an interface that contains an Invoke method that matches that delegate's signature. In this example, the generated file Contoso_h.h defines the IPrimeNumberEvent interface, which is used later in this procedure.

    MIDL_INTERFACE("3FBED04F-EFA7-4D92-B04D-59BD8B1B055E")
    IPrimeNumberEvent : public IUnknown
    {
    public:
        virtual HRESULT STDMETHODCALLTYPE Invoke( 
            int primeNumber) = 0;
    
    };
    
  2. In the ICalculator interface, define the PrimeNumberFound event. The eventadd and eventremove attributes specify that the consumer of the ICalculator interface can both subscribe to and unsubscribe from this event.

            [eventadd]
            HRESULT PrimeNumberFound(
                [in] PrimeNumberEvent* eventHandler, 
                [out, retval] EventRegistrationToken* eventCookie);
            [eventremove] 
            HRESULT PrimeNumberFound(
                [in] EventRegistrationToken eventCookie);
    
  3. In Contoso.cpp, add a private Microsoft::WRL::EventSource member variable to manage the event subscribers and invoke the event handler.

                EventSource<IPrimeNumberEvent> m_events;
    
  4. In Contoso.cpp, implement the add_PrimeNumberFound and remove_PrimeNumberFound methods.

                HRESULT __stdcall add_PrimeNumberFound(_In_ IPrimeNumberEvent* event, _Out_ EventRegistrationToken* eventCookie)
                {
                    return m_events.Add(event, eventCookie);
                }
    
                HRESULT __stdcall remove_PrimeNumberFound(_In_ EventRegistrationToken eventCookie)
                {
                    return m_events.Remove(eventCookie);
                }
    

To raise the event when a prime number is calculated

  1. In Contoso.cpp, add the IsPrime method to the private section of the Calculator class.

                // Determines whether the input value is prime.
                bool IsPrime(int n)
                {
                    if (n < 2)
                    {
                        return false;
                    }
                    for (int i = 2; i < n; ++i)
                    {
                        if ((n % i) == 0)
                        {
                            return false;
                        }
                    }
                    return true;
                }
    
  2. Modify the Calculator’s Add method to call the Microsoft::WRL::EventSource::InvokeAll method when a prime number is calculated.

                HRESULT __stdcall Add(_In_ int a, _In_ int b, _Out_ int* value)
                {
                    if (value == nullptr)
                    {
                        return E_POINTER;
                    }
                    int c = a + b;
                    if (IsPrime(c))
                    {
                        m_events.InvokeAll(c);
                    }
                    *value = c;
                    return S_OK;
                }
    

To handle the event from JavaScript

  1. In default.html, modify the body section to include a text area that contains prime numbers.

        <div>
            <input id="a" />
            <input id="b" />
            <p id="result">Result:</p>
            <p id="primes" style="color:#808080">Primes found:</p>
            <button onclick="Add()">Add</button>
        </div>
    
  2. In default.js, modify the Add function to handle the PrimeNumberFound event. The event handler appends the prime number to the text area that was defined by the previous step.

    function Add() {
        "use strict";
    
        var calculator = new Contoso.Calculator();
        calculator.onprimenumberfound = function (ev) {
            document.getElementById("primes").innerHTML += " " + ev.target;
        };
    
        var a = document.getElementById("a");
        var b = document.getElementById("b");
    
        document.getElementById("result").innerHTML = "Result: " + calculator.add(a.value, b.value);
    }
    

    Note

    In JavaScript, the event names are changed to lower-case and are prepended with "on" to match the standard naming conventions.

The following illustration shows the basic Calculator app.

Basic calculator app using JavaScript

Next Steps

See Also

Windows Runtime C++ Template Library (WRL)
Class Library Project Template
C/C++ Code Analysis tool