Componentes de Windows Runtime con C++/CXWindows Runtime components with C++/CX

Nota

Este tema le ayudará a mantener su aplicación de C++/CX.This topic exists to help you maintain your C++/CX application. Pero se recomienda usar C++/WinRT para las nuevas aplicaciones.But we recommend that you use C++/WinRT for new applications. C++/WinRT es una moderna proyección de lenguaje C++17 totalmente estándar para las API de Windows Runtime (WinRT), implementada como una biblioteca basada en archivos de encabezado y diseñada para darte acceso de primera clase a la API moderna de Windows.C++/WinRT is an entirely standard modern C++17 language projection for Windows Runtime (WinRT) APIs, implemented as a header-file-based library, and designed to provide you with first-class access to the modern Windows API. Para obtener información sobre cómo crear un componente de Windows Runtime con C++/WinRT, consulte Componentes de Windows Runtime con C++/WinRT.To learn how to create a Windows Runtime component using C++/WinRT, see Windows Runtime components with C++/WinRT.

En este tema se muestra cómo usar C++/CX para crear un componente de Windows Runtime — un componente al que se puede llamar desde una aplicación universal de Windows compilada con cualquier lenguaje de Windows Runtime (C#, Visual Basic, C++ o JavaScript).This topic shows how to use C++/CX to create a Windows Runtime component—a component that's callable from a Universal Windows app built using any Windows Runtime language (C#, Visual Basic, C++, or Javascript).

Hay varias razones para compilar un componente de Windows Runtime en C++.There are several reasons for building a Windows Runtime component in C++.

  • Para obtener la ventaja de rendimiento de C++ en operaciones complejas o de computación intensivas.To get the performance advantage of C++ in complex or computationally intensive operations.
  • Reutilizar el código que ya se ha escrito y probado.To reuse code that's already written and tested.

Al compilar una solución que contiene un proyecto de JavaScript o. NET y un proyecto de componente de Windows Runtime, los archivos de proyecto de JavaScript y la DLL compilada se combinan en un paquete que se puede depurar localmente en el simulador o remotamente en un dispositivo amarrado.When you build a solution that contains a JavaScript or .NET project, and a Windows Runtime component project, the JavaScript project files and the compiled DLL are merged into one package, which you can debug locally in the simulator or remotely on a tethered device. También puedes distribuir solo el proyecto del componente como un SDK de extensión.You can also distribute just the component project as an Extension SDK. Para más información, vea Crear un Kit de desarrollo de Software.For more information, see Creating a Software Development Kit.

En general, al codificar el componente de C++/CX, use la biblioteca normal de C++ y los tipos integrados, excepto en el límite de la interfaz binaria abstracta (ABI) donde se pasan los datos hacia y desde el código en otro paquete. winmd.In general, when you code your C++/CX component, use the regular C++ library and built-in types, except at the abstract binary interface (ABI) boundary where you are passing data to and from code in another .winmd package. Allí, use tipos de Windows Runtime y la sintaxis especial que C++/CX admite para crear y manipular esos tipos.There, use Windows Runtime types and the special syntax that C++/CX supports for creating and manipulating those types. Además, en el código de C++/CX, use tipos como Delegate y Event para implementar eventos que se puedan generar desde su componente y que se controlen en JavaScript, Visual Basic, C++ o C#.In addition, in your C++/CX code, use types such as delegate and event to implement events that can be raised from your component and handled in JavaScript, Visual Basic, C++, or C#. Para obtener más información sobre la sintaxis de C++/CX, vea Referencia del lenguaje Visual C++ (C++/CX).For more information about the C++/CX syntax, see Visual C++ Language Reference (C++/CX).

Reglas de nomenclatura y del uso de mayúsculas y minúsculasCasing and naming rules

JavaScriptJavaScript

JavaScript distingue mayúsculas de minúsculas.JavaScript is case-sensitive. Por lo tanto, debes seguir estas convenciones sobre el uso de mayúsculas y minúsculas:Therefore, you must follow these casing conventions:

  • Cuando hagas referencia a las clases y espacios de nombres de C++, usa las mayúsculas y minúsculas del mismo modo que en el lado de C++.When you reference C++ namespaces and classes, use the same casing that's used on the C++ side.
  • Al llamar a métodos, usa la convención Camel de mayúsculas y minúsculas incluso si el nombre del método está en mayúsculas en el lado de C++.When you call methods, use camel casing even if the method name is capitalized on the C++ side. Por ejemplo, "GetDate()" del método de C++ debe llamarse desde JavaScript como "getDate()".For example, a C++ method GetDate() must be called from JavaScript as getDate().
  • Un nombre de clase activable y un nombre de espacio de nombres no pueden contener caracteres UNICODE.An activatable class name and namespace name can't contain UNICODE characters.

.NET.NET

Los lenguajes .NET siguen las reglas normales del uso de mayúsculas y minúsculas.The .NET languages follow their normal casing rules.

Crear una instancia del objetoInstantiating the object

Solo los tipos de Windows Runtime pueden pasarse a través del límite de la ABI.Only Windows Runtime types can be passed across the ABI boundary. El compilador generará un error si el componente tiene un tipo como std::wstring como un parámetro o tipo devuelto en un método público.The compiler will raise an error if the component has a type like std::wstring as a return type or parameter in a public method. Los tipos integrados de las extensiones de componentes de Visual C++ (C++/CX) incluyen los valores escalares habituales, como int y Double, y también sus equivalentes de definición de tipo Int32, float64, etc.The Visual C++ component extensions (C++/CX) built-in types include the usual scalars such as int and double, and also their typedef equivalents int32, float64, and so on. Para obtener más información, consulta Sistema de tipos (C++/CX).For more information, see Type System (C++/CX).

// ref class definition in C++
public ref class SampleRefClass sealed
{
    // Class members...

    // #include <valarray>
public:
    double LogCalc(double input)
    {
        // Use C++ standard library as usual.
        return std::log(input);
    }

};
//Instantiation in JavaScript (requires "Add reference > Project reference")
var nativeObject = new CppComponent.SampleRefClass();
//Call a method and display result in a XAML TextBlock
var num = nativeObject.LogCalc(21.5);
ResultText.Text = num.ToString();

Tipos integrados de C++/CX, tipos de biblioteca y tipos de Windows RuntimeC++/CX built-in types, library types, and Windows Runtime types

Una clase activable (también conocida como "clase de referencia") es una clase en torno a la cual se pueden crear instancias desde otro lenguaje, como JavaScript, C# o Visual Basic.An activatable class (also known as a ref class) is one that can be instantiated from another language such as JavaScript, C# or Visual Basic. Para ser consumible en otro idioma, un componente debe contener al menos una clase activable.To be consumable from another language, a component must contain at least one activatable class.

Un componente de Windows Runtime puede contener varias clases activables públicas, así como clases adicionales conocidas solo internamente por el componente.A Windows Runtime component can contain multiple public activatable classes as well as additional classes that are known only internally to the component. Aplique el atributo WebHostHidden a los tipos de C++/CX que no están diseñados para ser visibles para JavaScript.Apply the WebHostHidden attribute to C++/CX types that are not intended to be visible to JavaScript.

Todas las clases públicas deben residir en el mismo espacio de nombres de raíz con el mismo nombre que el archivo de metadatos del componente.All public classes must reside in the same root namespace which has the same name as the component metadata file. Por ejemplo, se pueden crear instancias de una clase denominada A.B.C.MyClass solo si está definida en un archivo de metadatos denominado A.winmd, A.B.winmd o A.B.C.winmd.For example, a class that's named A.B.C.MyClass can be instantiated only if it's defined in a metadata file that's named A.winmd or A.B.winmd or A.B.C.winmd. El nombre de la DLL no tiene que coincidir con el nombre del archivo .winmd.The name of the DLL is not required to match the .winmd file name.

El código de cliente crea una instancia del componente con la palabra clave new (New en Visual Basic) del mismo modo que para cualquier otra clase.Client code creates an instance of the component by using the new (New in Visual Basic) keyword just as for any class.

Una clase activable debe declararse como public ref class sealed.An activatable class must be declared as public ref class sealed. La palabra clave ref class indica al compilador que cree la clase como tipo compatible de Windows Runtime, y la palabra clave sealed especifica que la clase no puede heredarse.The ref class keyword tells the compiler to create the class as a Windows Runtime compatible type, and the sealed keyword specifies that the class cannot be inherited. Windows Runtime actualmente no es compatible con un modelo de herencia generalizada; un modelo de herencia limitado es compatible con la creación de controles de XAML personalizados.The Windows Runtime does not currently support a generalized inheritance model; a limited inheritance model supports creation of custom XAML controls. Para obtener más información, consulta Clases y estructuras de referencia (C++/CX).For more information, see Ref classes and structs (C++/CX).

En C++/CX, todos los primitivos numéricos se definen en el espacio de nombres predeterminado.For C++/CX, all the numeric primitives are defined in the default namespace. El espacio de nombres Platform contiene clases de C++/CX que son específicas del sistema de tipos Windows Runtime.The Platform namespace contains C++/CX classes that are specific to the Windows Runtime type system. Estos incluyen las clases Platform::String y Platform::Object.These include Platform::String class and Platform::Object class. Los tipos de colección concreta, como las clases Platform::Collections::Map y Platform::Collections::Vector, se definen en el espacio de nombres Platform::Collections.The concrete collection types such as Platform::Collections::Map class and Platform::Collections::Vector class are defined in the Platform::Collections namespace. Las interfaces públicas que implementan estos tipos se definen en Windows::Foundation::Collections Namespace (C++/CX).The public interfaces that these types implement are defined in Windows::Foundation::Collections Namespace (C++/CX). Estos son los tipos de interfaz consumidos por JavaScript, C# y Visual Basic.It is these interface types that are consumed by JavaScript, C# and Visual Basic. Para obtener más información, consulta Sistema de tipos (C++/CX).For more information, see Type System (C++/CX).

Método que devuelve un valor de tipo integradoMethod that returns a value of built-in type

    // #include <valarray>
public:
    double LogCalc(double input)
    {
        // Use C++ standard library as usual.
        return std::log(input);
    }
//Call a method
var nativeObject = new CppComponent.SampleRefClass;
var num = nativeObject.logCalc(21.5);
document.getElementById('P2').innerHTML = num;

Método que devuelve una estructura de valor personalizadaMethod that returns a custom value struct

namespace CppComponent
{
    // Custom struct
    public value struct PlayerData
    {
        Platform::String^ Name;
        int Number;
        double ScoringAverage;
    };

    public ref class Player sealed
    {
    private:
        PlayerData m_player;
    public:
        property PlayerData PlayerStats
        {
            PlayerData get(){ return m_player; }
            void set(PlayerData data) {m_player = data;}
        }
    };
}

Para pasar los Structs de valor definidos por el usuario a través de la ABI, defina un objeto de JavaScript que tenga los mismos miembros que el struct de valor que se define en C++/CX.To pass user-defined value structs across the ABI, define a JavaScript object that has the same members as the value struct that's defined in C++/CX. Después, puede pasar ese objeto como un argumento a un método de C++/CX para que el objeto se convierta implícitamente al tipo de C++/CX.You can then pass that object as an argument to a C++/CX method so that the object is implicitly converted to the C++/CX type.

// Get and set the value struct
function GetAndSetPlayerData() {
    // Create an object to pass to C++
    var myData =
        { name: "Bob Homer", number: 12, scoringAverage: .357 };
    var nativeObject = new CppComponent.Player();
    nativeObject.playerStats = myData;

    // Retrieve C++ value struct into new JavaScript object
    var myData2 = nativeObject.playerStats;
    document.getElementById('P3').innerHTML = myData.name + " , " + myData.number + " , " + myData.scoringAverage.toPrecision(3);
}

Otro enfoque es definir una clase que implemente IPropertySet (no se muestra).Another approach is to define a class that implements IPropertySet (not shown).

En los lenguajes de .NET, solo tiene que crear una variable del tipo que se define en el componente de C++/CX.In the .NET languages, you just create a variable of the type that's defined in the C++/CX component.

private void GetAndSetPlayerData()
{
    // Create a ref class
    var player = new CppComponent.Player();

    // Create a variable of a value struct
    // type that is defined in C++
    CppComponent.PlayerData myPlayer;
    myPlayer.Name = "Babe Ruth";
    myPlayer.Number = 12;
    myPlayer.ScoringAverage = .398;

    // Set the property
    player.PlayerStats = myPlayer;

    // Get the property and store it in a new variable
    CppComponent.PlayerData myPlayer2 = player.PlayerStats;
    ResultText.Text += myPlayer.Name + " , " + myPlayer.Number.ToString() +
        " , " + myPlayer.ScoringAverage.ToString();
}

Métodos sobrecargadosOverloaded Methods

Una clase Ref pública de C++/CX puede contener métodos sobrecargados, pero JavaScript tiene una capacidad limitada para diferenciar los métodos sobrecargados.A C++/CX public ref class can contain overloaded methods, but JavaScript has limited ability to differentiate overloaded methods. Por ejemplo, puede distinguir entre estas firmas:For example, it can tell the difference between these signatures:

public ref class NumberClass sealed
{
public:
    int GetNumber(int i);
    int GetNumber(int i, Platform::String^ str);
    double GetNumber(int i, MyData^ d);
};

Pero no puede distinguir entre estas:But it can’t tell the difference between these:

int GetNumber(int i);
double GetNumber(double d);

En casos ambiguos, puedes asegurarte de que JavaScript llame siempre a una sobrecarga específica aplicando el atributo Windows::Foundation::Metadata::DefaultOverload a la firma del método en el archivo de encabezado.In ambiguous cases, you can ensure that JavaScript always calls a specific overload by applying the Windows::Foundation::Metadata::DefaultOverload attribute to the method signature in the header file.

Este código JavaScript siempre llama a la sobrecarga atribuida:This JavaScript always calls the attributed overload:

var nativeObject = new CppComponent.NumberClass();
var num = nativeObject.getNumber(9);
document.getElementById('P4').innerHTML = num;

.NET.NET

Los lenguajes de .NET reconocen las sobrecargas en una clase Ref de C++/CX como en cualquier clase .NET.The .NET languages recognize overloads in a C++/CX ref class just as in any .NET class.

DateTimeDateTime

En Windows Runtime, un objeto Windows::Foundation::DateTime es simplemente un entero firmado de 64 bits que representa el número de intervalos de 100 nanosegundos o bien antes o bien después del 1 de enero de 1601.In the Windows Runtime, a Windows::Foundation::DateTime object is just a 64-bit signed integer that represents the number of 100-nanosecond intervals either before or after January 1, 1601. No hay métodos en un objeto de Windows:Foundation::DateTime.There are no methods on a Windows:Foundation::DateTime object. En su lugar, cada idioma proyecta la fecha y hora de forma nativa para ese lenguaje: el objeto Date en JavaScript y los tipos System. DateTime y System. DateTimeOffset en .NET.Instead, each language projects the DateTime in the way that is native to that language: the Date object in JavaScript and the System.DateTime and System.DateTimeOffset types in .NET.

public  ref class MyDateClass sealed
{
public:
    property Windows::Foundation::DateTime TimeStamp;
    void SetTime(Windows::Foundation::DateTime dt)
    {
        auto cal = ref new Windows::Globalization::Calendar();
        cal->SetDateTime(dt);
        TimeStamp = cal->GetDateTime(); // or TimeStamp = dt;
    }
};

Cuando se pasa un valor DateTime de C++/CX a JavaScript, JavaScript lo acepta como un objeto de fecha y lo muestra de forma predeterminada como una cadena de fecha de formato largo.When you pass a DateTime value from C++/CX to JavaScript, JavaScript accepts it as a Date object and displays it by default as a long-form date string.

function SetAndGetDate() {
    var nativeObject = new CppComponent.MyDateClass();

    var myDate = new Date(1956, 4, 21);
    nativeObject.setTime(myDate);

    var myDate2 = nativeObject.timeStamp;

    //prints long form date string
    document.getElementById('P5').innerHTML = myDate2;

}

Cuando un lenguaje .NET pasa un System. DateTime a un componente de C++/CX, el método lo acepta como Windows:: Foundation::D ateTime.When a .NET language passes a System.DateTime to a C++/CX component, the method accepts it as a Windows::Foundation::DateTime. Cuando el componente pasa un elemento Windows:: Foundation::D ateTime a un método .NET, el método Framework lo acepta como DateTimeOffset.When the component passes a Windows::Foundation::DateTime to a .NET method, the Framework method accepts it as a DateTimeOffset.

private void DateTimeExample()
{
    // Pass a System.DateTime to a C++ method
    // that takes a Windows::Foundation::DateTime
    DateTime dt = DateTime.Now;
    var nativeObject = new CppComponent.MyDateClass();
    nativeObject.SetTime(dt);

    // Retrieve a Windows::Foundation::DateTime as a
    // System.DateTimeOffset
    DateTimeOffset myDate = nativeObject.TimeStamp;

    // Print the long-form date string
    ResultText.Text += myDate.ToString();
}

Colecciones y matricesCollections and arrays

Las colecciones siempre se pasan a través del límite de la ABI como controladores para los tipos de Windows Runtime como Windows::Foundation::Collections::IVector^ y Windows::Foundation::Collections::IMap^.Collections are always passed across the ABI boundary as handles to Windows Runtime types such as Windows::Foundation::Collections::IVector^ and Windows::Foundation::Collections::IMap^. Por ejemplo, si devuelves un controlador a Platform::Collections::Map, este lo convierte implícitamente a Windows::Foundation::Collections::IMap^.For example, if you return a handle to a Platform::Collections::Map, it implicitly converts to a Windows::Foundation::Collections::IMap^. Las interfaces de colección se definen en un espacio de nombres que es independiente de las clases de C++/CX que proporcionan las implementaciones concretas.The collection interfaces are defined in a namespace that's separate from the C++/CX classes that provide the concrete implementations. Los lenguajes de JavaScript y .NET consumen las interfaces.JavaScript and .NET languages consume the interfaces. Para obtener más información, consulta Colecciones (C++/CX) y Matriz y WriteOnlyArray (C++/CX).For more information, see Collections (C++/CX) and Array and WriteOnlyArray (C++/CX).

Pasar el IVectorPassing IVector

// Windows::Foundation::Collections::IVector across the ABI.
//#include <algorithm>
//#include <collection.h>
Windows::Foundation::Collections::IVector<int>^ SortVector(Windows::Foundation::Collections::IVector<int>^ vec)
{
    std::sort(begin(vec), end(vec));
    return vec;
}
var nativeObject = new CppComponent.CollectionExample();
// Call the method to sort an integer array
var inVector = [14, 12, 45, 89, 23];
var outVector = nativeObject.sortVector(inVector);
var result = "Sorted vector to array:";
for (var i = 0; i < outVector.length; i++)
{
    outVector[i];
    result += outVector[i].toString() + ",";
}
document.getElementById('P6').innerHTML = result;

Los lenguajes .NET ven IVector<T> como IList<T>.The .NET languages see IVector<T> as IList<T>.

private void SortListItems()
{
    IList<int> myList = new List<int>();
    myList.Add(5);
    myList.Add(9);
    myList.Add(17);
    myList.Add(2);

    var nativeObject = new CppComponent.CollectionExample();
    IList<int> mySortedList = nativeObject.SortVector(myList);

    foreach (var item in mySortedList)
    {
        ResultText.Text += " " + item.ToString();
    }
}

Pasar IMapPassing IMap

// #include <map>
//#include <collection.h>
Windows::Foundation::Collections::IMap<int, Platform::String^> ^GetMap(void)
{    
    Windows::Foundation::Collections::IMap<int, Platform::String^> ^ret =
        ref new Platform::Collections::Map<int, Platform::String^>;
    ret->Insert(1, "One ");
    ret->Insert(2, "Two ");
    ret->Insert(3, "Three ");
    ret->Insert(4, "Four ");
    ret->Insert(5, "Five ");
    return ret;
}
// Call the method to get the map
var outputMap = nativeObject.getMap();
var mStr = "Map result:" + outputMap.lookup(1) + outputMap.lookup(2)
    + outputMap.lookup(3) + outputMap.lookup(4) + outputMap.lookup(5);
document.getElementById('P7').innerHTML = mStr;

Los lenguajes .NET ven IMap e IDictionary<K, V>.The .NET languages see IMap and IDictionary<K, V>.

private void GetDictionary()
{
    var nativeObject = new CppComponent.CollectionExample();
    IDictionary<int, string> d = nativeObject.GetMap();
    ResultText.Text += d[2].ToString();
}

PropiedadesProperties

Una clase Ref pública en las extensiones de componentes de C++/CX expone los miembros de datos públicos como propiedades, mediante la palabra clave Property.A public ref class in C++/CX component extensions exposes public data members as properties, by using the property keyword. El concepto es idéntico a las propiedades de .NET.The concept is identical to .NET properties. Una propiedad trivial es similar a un miembro de datos porque su funcionalidad es implícita.A trivial property resembles a data member because its functionality is implicit. Una propiedad no trivial tiene descriptores de acceso get y set explícitos y una variable privada con nombre que es la "memoria auxiliar" para el valor.A non-trivial property has explicit get and set accessors and a named private variable that's the "backing store" for the value. En este ejemplo, la variable de miembro privado _ propertyAValue es la memoria auxiliar de la propiedada.In this example, the private member variable _propertyAValue is the backing store for PropertyA. Una propiedad puede generar un evento cuando cambia su valor, y una aplicación cliente puede registrarse para recibir ese evento.A property can fire an event when its value changes, and a client app can register to receive that event.

//Properties
public delegate void PropertyChangedHandler(Platform::Object^ sender, int arg);
public ref class PropertyExample  sealed
{
public:
    PropertyExample(){}

    // Event that is fired when PropertyA changes
    event PropertyChangedHandler^ PropertyChangedEvent;

    // Property that has custom setter/getter
    property int PropertyA
    {
        int get() { return m_propertyAValue; }
        void set(int propertyAValue)
        {
            if (propertyAValue != m_propertyAValue)
            {
                m_propertyAValue = propertyAValue;
                // Fire event. (See event example below.)
                PropertyChangedEvent(this, propertyAValue);
            }
        }
    }

    // Trivial get/set property that has a compiler-generated backing store.
    property Platform::String^ PropertyB;

private:
    // Backing store for propertyA.
    int m_propertyAValue;
};
var nativeObject = new CppComponent.PropertyExample();
var propValue = nativeObject.propertyA;
document.getElementById('P8').innerHTML = propValue;

//Set the string property
nativeObject.propertyB = "What is the meaning of the universe?";
document.getElementById('P9').innerHTML += nativeObject.propertyB;

Los lenguajes .NET tienen acceso a las propiedades de un objeto nativo de C++/CX tal como lo harían en un objeto .NET.The .NET languages access properties on a native C++/CX object just as they would on a .NET object.

private void GetAProperty()
{
    // Get the value of the integer property
    // Instantiate the C++ object
    var obj = new CppComponent.PropertyExample();

    // Get an integer property
    var propValue = obj.PropertyA;
    ResultText.Text += propValue.ToString();

    // Set a string property
    obj.PropertyB = " What is the meaning of the universe?";
    ResultText.Text += obj.PropertyB;

}

Delegados y eventosDelegates and events

Un delegado es un tipo de Windows Runtime que representa un objeto de función.A delegate is a Windows Runtime type that represents a function object. Puedes usar delegados en relación con eventos, devoluciones de llamada y llamadas a métodos asincrónicos para especificar una acción que debe realizarse más tarde.You can use delegates in connection with events, callbacks, and asynchronous method calls to specify an action to be performed later. Del mismo modo que un objeto de función, el delegado proporciona seguridad de tipos mediante la habilitación del compilador para verificar el tipo devuelto y los tipos de parámetros de la función.Like a function object, the delegate provides type-safety by enabling the compiler to verify the return type and parameter types of the function. La declaración de un delegado es similar a una firma de función, la implementación es similar a una definición de clase y la invocación es similar a una invocación de función.The declaration of a delegate resembles a function signature, the implementation resembles a class definition, and the invocation resembles a function invocation.

Agregar una escucha de eventosAdding an event listener

Puedes usar la palabra clave de evento para declarar a un miembro público de un tipo de delegado especificado.You can use the event keyword to declare a public member of a specified delegate type. El código de cliente se suscribe al evento mediante los mecanismos estándar que se proporcionan en el lenguaje en particular.Client code subscribes to the event by using the standard mechanisms that are provided in the particular language.

public:
    event SomeHandler^ someEvent;

En este ejemplo se usa el mismo código de C++ que para la sección de propiedades anterior.This example uses the same C++ code as for the previous properties section.

function Button_Click() {
    var nativeObj = new CppComponent.PropertyExample();
    // Define an event handler method
    var singlecasthandler = function (ev) {
        document.getElementById('P10').innerHTML = "The button was clicked and the value is " + ev;
    };

    // Subscribe to the event
    nativeObj.onpropertychangedevent = singlecasthandler;

    // Set the value of the property and fire the event
    var propValue = 21;
    nativeObj.propertyA = 2 * propValue;

}

En los lenguajes .NET, la suscripción a un evento en un componente de C++ es la misma que la suscripción a un evento en una clase .NET:In the .NET languages, subscribing to an event in a C++ component is the same as subscribing to an event in a .NET class:

//Subscribe to event and call method that causes it to be fired.
private void TestMethod()
{
    var objWithEvent = new CppComponent.PropertyExample();
    objWithEvent.PropertyChangedEvent += objWithEvent_PropertyChangedEvent;

    objWithEvent.PropertyA = 42;
}

//Event handler method
private void objWithEvent_PropertyChangedEvent(object __param0, int __param1)
{
    ResultText.Text = "the event was fired and the result is " +
         __param1.ToString();
}

Agregar varias escuchas de eventos para un eventoAdding multiple event listeners for one event

JavaScript tiene un método de addEventListener que permite que varios controladores se suscriban a un solo evento.JavaScript has an addEventListener method that enables multiple handlers to subscribe to a single event.

public delegate void SomeHandler(Platform::String^ str);

public ref class LangSample sealed
{
public:
    event SomeHandler^ someEvent;
    property Platform::String^ PropertyA;

    // Method that fires an event
    void FireEvent(Platform::String^ str)
    {
        someEvent(Platform::String::Concat(str, PropertyA->ToString()));
    }
    //...
};
// Add two event handlers
var multicast1 = function (ev) {
    document.getElementById('P11').innerHTML = "Handler 1: " + ev.target;
};
var multicast2 = function (ev) {
    document.getElementById('P12').innerHTML = "Handler 2: " + ev.target;
};

var nativeObject = new CppComponent.LangSample();
//Subscribe to the same event
nativeObject.addEventListener("someevent", multicast1);
nativeObject.addEventListener("someevent", multicast2);

nativeObject.propertyA = "42";

// This method should fire an event
nativeObject.fireEvent("The answer is ");

En C#, cualquier número de controladores de eventos puede suscribirse al evento mediante el operador +=, como se muestra en el ejemplo anterior.In C#, any number of event handlers can subscribe to the event by using the += operator as shown in the previous example.

EnumeracionesEnums

Una enumeración de Windows Runtime en C++/CX se declara mediante la enumeración de clase pública; se parece a una enumeración con ámbito en C++ estándar.A Windows Runtime enum in C++/CX is declared by using public class enum; it resembles a scoped enum in standard C++.

public enum class Direction {North, South, East, West};

public ref class EnumExampleClass sealed
{
public:
    property Direction CurrentDirection
    {
        Direction  get(){return m_direction; }
    }

private:
    Direction m_direction;
};

Los valores de enumeración se pasan entre C++/CX y JavaScript como enteros.Enum values are passed between C++/CX and JavaScript as integers. Opcionalmente, puede declarar un objeto de JavaScript que contenga los mismos valores con nombre que la enumeración de C++/CX y usarlo como se indica a continuación.You can optionally declare a JavaScript object that contains the same named values as the C++/CX enum and use it as follows.

var Direction = { 0: "North", 1: "South", 2: "East", 3: "West" };
//. . .

var nativeObject = new CppComponent.EnumExampleClass();
var curDirection = nativeObject.currentDirection;
document.getElementById('P13').innerHTML =
Direction[curDirection];

Tanto C# como Visual Basic tienen son compatibles con el lenguaje para las enumeraciones.Both C# and Visual Basic have language support for enums. Estos lenguajes ven una clase de enumeración pública de C++ tal como verán una enumeración .NET.These languages see a C++ public enum class just as they would see a .NET enum.

Métodos asincrónicosAsynchronous methods

Para consumir métodos asincrónicos expuestos por otros objetos de Windows Runtime, usa la Clase de tarea (Runtime de simultaneidad).To consume asynchronous methods that are exposed by other Windows Runtime objects, use the task Class (Concurrency Runtime). Para obtener más información, consulta Paralelismo de tareas (Runtime de simultaneidad).For more information, see and Task Parallelism (Concurrency Runtime).

Para implementar métodos asincrónicos en C++/CX, use la función Create _ Async que se define en ppltasks. h.To implement asynchronous methods in C++/CX, use the create_async function that's defined in ppltasks.h. Para obtener más información, consulte crear operaciones asincrónicas en C++/CX para aplicaciones para UWP.For more information, see Creating Asynchronous Operations in C++/CX for UWP apps. Para obtener un ejemplo, vea tutorial sobre cómo crear un componente de Windows Runtime de C++/CX y llamarlo desde JavaScript o C#.For an example, see Walkthrough of creating a C++/CX Windows Runtime component, and calling it from JavaScript or C#. Los lenguajes .NET consumen métodos asincrónicos de C++/CX del mismo modo que cualquier método asincrónico definido en .NET.The .NET languages consume C++/CX asynchronous methods just as they would any asynchronous method that's defined in .NET.

ExcepcionesExceptions

Puedes iniciar cualquier tipo de excepción definido por Windows Runtime.You can throw any exception type that's defined by the Windows Runtime. No puedes derivar tipos personalizados de ningún tipo de excepción de Windows Runtime.You cannot derive custom types from any Windows Runtime exception type. Sin embargo, puedes iniciar COMException y proporcionar un HRESULT personalizado al que se pueda acceder mediante el código que captura la excepción.However, you can throw COMException and provide a custom HRESULT that can be accessed by the code that catches the exception. No hay ninguna manera de especificar un mensaje personalizado en una COMException.There's no way to specify a custom Message in a COMException.

Sugerencias de depuraciónDebugging tips

Cuando se depura una solución de JavaScript que tiene un archivo DLL del componente, puedes configurar el depurador para habilitar o bien la ejecución paso a paso a través del script, o bien del código nativo en el componente, pero no ambas opciones al mismo tiempo.When you debug a JavaScript solution that has a component DLL, you can set the debugger to enable either stepping through script, or stepping through native code in the component, but not both at the same time. Para cambiar la configuración, selecciona el nodo del proyecto de JavaScript en el Explorador de soluciones y, a continuación, elige Propiedades, Depuración, Tipo de depurador.To change the setting, select the JavaScript project node in Solution Explorer and then choose Properties, Debugging, Debugger Type.

Asegúrate de seleccionar las funcionalidades adecuadas en el diseñador de paquetes.Be sure to select appropriate capabilities in the package designer. Por ejemplo, si estás intentando abrir un archivo de imagen en la biblioteca de imágenes del usuario mediante las API de Windows Runtime, asegúrate de seleccionar la casilla de la biblioteca de imágenes en el panel de capacidades del diseñador de manifiestos.For example, if you are attempting to open an image file in the user's Pictures library by using the Windows Runtime APIs, be sure to select the Pictures Library check box in the Capabilities pane of the manifest designer.

Si tu código JavaScript aparentemente no reconoce las propiedades o métodos públicos en el componente, asegúrate de que estás usando la convención Camel de mayúsculas y minúsculas en JavaScript.If your JavaScript code doesn't seem to be recognizing the public properties or methods in the component, make sure that in JavaScript you are using camel casing. Por ejemplo, se debe hacer referencia al método LogCalc de C++/CX como logCalc en JavaScript.For example, the LogCalc C++/CX method must be referenced as logCalc in JavaScript.

Si quita de una solución un proyecto de componente de Windows Runtime de C++/CX, también debe quitar manualmente la referencia de proyecto del proyecto de JavaScript.If you remove a C++/CX Windows Runtime component project from a solution, you must also manually remove the project reference from the JavaScript project. De lo contrario, no se efectuará la depuración o las operaciones de compilación posteriores.Failure to do so prevents subsequent debug or build operations. Si es necesario, a continuación puedes agregar una referencia de ensamblado a la DLL.If necessary, you can then add an assembly reference to the DLL.