逐步解說:使用 WRL 建立基本 Windows 執行階段元件
本文件將示範如何使用 Windows 執行階段 C++ 樣板庫 (WRL) 建立基本的 Windows 執行階段 元件。 當結果質數時,元件將兩個數字相加並引發事件。 文件也會示範如何從使用 JavaScript 的 Windows 市集 應用程式的元件。
必要條件
使用的 Windows 執行階段經驗。
與 COM 的經驗。
建立將兩個數字相加的基本 Windows 執行階段 元件
在 Visual Studio 中,建立 WRLClassLibrary Visual C++ 專案。 此文件 WRL 類別庫專案範本 說明如何下載這個範本。 將專案命名為 Contoso。
在 Contoso.cpp 和 Contoso.idl,以「計算機」取代「WinRTClass」所有執行個體。
在 Contoso.idl,加入 Add 方法加入至 ICalculator 介面。
HRESULT Add([in] int a, [in] int b, [out, retval] int* value);
在 Contoso.cpp,加入 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_ 和其他來源附註 Language (SAL) 附註函式描述如何使用其參數。 SAL 附註也描述傳回值。 SAL 附註與 C/C++ 程式碼分析工具 使用尋找 C 和 C++ 原始程式碼中可能的缺失。 由這個工具所報告的常見程式碼錯誤包括:緩衝區滿溢、未初始化的記憶體、null 指標取值以及記憶體和資源流失。
使用從使用 JavaScript 的 Windows 市集 應用程式的元件
在 Visual Studio 中,將新的 JavaScript 空白應用程式Contoso 專案加入至方案。 將專案命名為 CalculatorJS。
在 CalculatorJS 專案中,加入 Contoso 專案的參考。
在 default.html,請用這些 UI 項目取代 body 區段:
<div> <input id="a" /> <input id="b" /> <p id="result">Result:</p> <button onclick="Add()">Add</button> </div>
在 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,方法名稱的第一個字母變更為小寫以符合標準命名慣例。
加入計算質數時就會觸發的事件
在 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; };
在 ICalculator 介面,定義 PrimeNumberFound 事件。 eventadd 和 eventremove 屬性指定 ICalculator 介面的消費者可以訂閱和從這個事件來取消訂閱。
[eventadd] HRESULT PrimeNumberFound( [in] PrimeNumberEvent* eventHandler, [out, retval] EventRegistrationToken* eventCookie); [eventremove] HRESULT PrimeNumberFound( [in] EventRegistrationToken eventCookie);
在 Contoso.cpp,請將 privateMicrosoft::WRL::EventSource 成員變數處理事件訂閱者和叫用事件處理常式。
EventSource<IPrimeNumberEvent> m_events;
在 Contoso.cpp,請執行 add_PrimeNumberFound 和 remove_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); }
引發事件,當一個質數計算
在 Contoso.cpp,加入 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; }
當一個質數計算時,修改 Calculator 的 Add 方法會呼叫 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 來的事件
在 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>
在 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」以符合標準命名慣例。
下圖顯示基本計算機應用程式。