演练:使用 WRL 创建基本 Windows 运行时组件

演示如何使用Windows 运行时 C++ 模板库 (WRL)创建基本Windows 运行时 组件。 结果,当第,组件添加两个数字并引发事件。 此文档还会演示如何引发事件,以及如何使用来自使用 JavaScript 的 Windows 应用商店应用的组件。

系统必备

创建将两个数相加的基本的 Windows 运行时 组件。

  1. 在 Visual Studio 中,创建 WRLClassLibrary 项目。Visual C++ WRL 类库项目模板 文档描述如何下载此模板。 将项目命名为 Contoso。

  2. 在 Contoso.cpp 和 Contoso.idl,用“计算器”替换“WinRTClass”的所有实例。

  3. 在 Contoso.idl,将 Add 方法添加到 ICalculator 接口。

    HRESULT Add([in] int a, [in] int b, [out, retval] int* value);
    
  4. Add 方法添加到Calculator类的 public 节中。

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

    重要

    由于您创建 COM 组件,确保使用 __stdcall 调用约定。

    建议您改用 _Out_ 和其他源代码注释语言 (SAL) 注释说明如何使用函数参数。 SAL 注释还描述返回值。 SAL 注释以 C/C++ 代码分析工具 使用发现可能存在的缺陷的 C# 和 C++ 源代码。 工具报告的常见编码错误包括缓冲区溢出、内存未初始化、null 指针取消引用以及内存和资源泄漏。

使用 JavaScript 从使用的 Windows 应用商店 应用的组件

  1. 在 Visual Studio 中,添加新 JavaScript 空白应用程序 项目添加到 Contoso 解决方案中。 将该项目命名为 CalculatorJS。

  2. 在CalculatorJS 测试项目中,添加对所测试 Contoso 项目的引用。

  3. 在 default.html,请使用这些 UI 元素替换 body 部分:

    <div>
        <input id="a" />
        <input id="b" />
        <p id="result">Result:</p>
        <button onclick="Add()">Add</button>
    </div>
    
  4. 在 default.js,请实现 OnClick 函数。

    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);
    }
    

    备注

    在 JavaScript,方法名称的首字母小写更改为与标准命名约定。

添加该事件触发,当一个质数计算

  1. 在 Contoso.idl,在 ICalculator的声明之前,请定义 PrimeNumberEvent,委托类型,提供 int 参数。

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

    当使用 delegate 关键字时,MIDL 编译器创建一个包含 Invoke 方法与委托签名的接口。 在此示例中,生成的文件 Contoso_h.h 定义 IPrimeNumberEvent 接口,此过程稍后使用。

    MIDL_INTERFACE("3FBED04F-EFA7-4D92-B04D-59BD8B1B055E")
    IPrimeNumberEvent : public IUnknown
    {
    public:
        virtual HRESULT STDMETHODCALLTYPE Invoke( 
            int primeNumber) = 0;
    
    };
    
  2. ICalculator 接口,请定义 PrimeNumberFound 事件。 eventaddeventremove 特性指定 ICalculator 接口的使用者可以订阅以及从此事件取消订阅。

    [eventadd]
    HRESULT PrimeNumberFound(
        [in] PrimeNumberEvent* eventHandler, 
        [out, retval] EventRegistrationToken* eventCookie);
    [eventremove] 
    HRESULT PrimeNumberFound(
        [in] EventRegistrationToken eventCookie);
    
  3. 在 Contoso.cpp,添加 private Microsoft::WRL::EventSource 成员变量管理事件订阅方和调用事件处理程序。

    EventSource<IPrimeNumberEvent> m_events;
    
  4. 在 Contoso.cpp 中,执行add_PrimeNumberFoundremove_PrimeNumberFound和 方法。

    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);
    }
    

引发事件,当一个质数计算

  1. IsPrime 方法添加到Calculator类的 private 节中。

    // 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. 当一个质数计算时,请修改 CalculatorAdd 方法以调用 Microsoft::WRL::EventSource::InvokeAll 方法。

    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;
    }
    

处理从 JavaScript 的事件

  1. 在 default.html,请修改 body 节以包含质数的主体。

    <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. 在 default.js,请修改 Add 函数处理 PrimeNumberFound 事件。 事件处理程序附加质数为由前面步骤定义的主体。

    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);
    }
    

    备注

    在 JavaScript 事件名称更改为小写和前预置" on "与标准命名约定。

下面的插图演示基本的计算器应用。

使用 JavaScript 的基本计算器应用程序

请参见

概念

Windows 运行时 C++ 模板库 (WRL)

WRL 类库项目模板

代码分析工具