Componenti Windows Runtime con C++/CXWindows Runtime components with C++/CX

Nota

Questo argomento è utile per gestire l'applicazione C++/CX.This topic exists to help you maintain your C++/CX application. È tuttavia consigliabile utilizzare C++/WinRT per le nuove applicazioni.But we recommend that you use C++/WinRT for new applications. C++/WinRT è una proiezione del linguaggio C++ 17 interamente standard e moderna per le API di Windows Runtime (WinRT), implementata come libreria basata su file di intestazione e progettata per fornirti accesso privilegiato alla moderna API di 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. Per informazioni su come creare un componente Windows Runtime con C++/WinRT, vedere Componenti Windows Runtime con C++/WinRT.To learn how to create a Windows Runtime component using C++/WinRT, see Windows Runtime components with C++/WinRT.

Questo argomento illustra come usare C++/CX per creare un componente Windows Runtime — un componente che è possibile chiamare da un'app di Windows universale compilata usando qualsiasi linguaggio 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).

Esistono diversi motivi per la compilazione di un componente Windows Runtime in C++.There are several reasons for building a Windows Runtime component in C++.

  • Per ottenere i vantaggi in termini di prestazioni offerti da C++ nelle operazioni complesse o con uso intensivo delle risorse di calcolo.To get the performance advantage of C++ in complex or computationally intensive operations.
  • Per riutilizzare codice già scritto e testato.To reuse code that's already written and tested.

Quando crei una soluzione che contiene un progetto JavaScript o .NET e un progetto di componente Windows Runtime, i file di progetto JavaScript e la DLL compilata vengono uniti in un unico pacchetto, di cui puoi eseguire il debug localmente nel simulatore o in remoto su un dispositivo con tethering.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. Puoi anche distribuire solo il progetto di componente come SDK di estensione.You can also distribute just the component project as an Extension SDK. Per altre informazioni, vedere Creating a Software Development Kit (Creazione di un Software Development Kit).For more information, see Creating a Software Development Kit.

In generale, quando si codifica il componente C++/CX, usare la normale libreria C++ e i tipi incorporati, ad eccezione del limite ABI (abstract Binary Interface) in cui si passano i dati da e verso il codice in un altro pacchetto. 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. Usare Windows Runtime tipi e la sintassi speciale supportata da C++/CX per la creazione e la modifica di tali tipi.There, use Windows Runtime types and the special syntax that C++/CX supports for creating and manipulating those types. Inoltre, nel codice C++/CX, usare i tipi come delegato ed evento per implementare eventi che possono essere generati dal componente e gestiti in 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#. Per ulteriori informazioni sulla sintassi C++/CX, vedere riferimenti al linguaggio Visual C++ (c++/CX).For more information about the C++/CX syntax, see Visual C++ Language Reference (C++/CX).

Uso di maiuscole e minuscole e regole di denominazioneCasing and naming rules

JavaScriptJavaScript

JavaScript fa distinzione tra maiuscole e minuscole.JavaScript is case-sensitive. Devi quindi seguire queste convenzioni di uso di maiuscole e minuscole:Therefore, you must follow these casing conventions:

  • Quando fai riferimento a spazi dei nomi e classi C++, usa maiuscole e minuscole nello stesso modo in cui vengono usate sul lato C++.When you reference C++ namespaces and classes, use the same casing that's used on the C++ side.
  • Quando chiami i metodi, usa la notazione camel anche se il nome del metodo ha l'iniziale maiuscola sul lato C++.When you call methods, use camel casing even if the method name is capitalized on the C++ side. Ad esempio, un metodo C++ GetDate() deve essere chiamato da JavaScript come getDate().For example, a C++ method GetDate() must be called from JavaScript as getDate().
  • Un nome di classe attivabile e un nome di spazio dei nomi non possono contenere caratteri UNICODE.An activatable class name and namespace name can't contain UNICODE characters.

.NET.NET

I linguaggi .NET seguono le regole standard per l'uso di maiuscole e minuscole.The .NET languages follow their normal casing rules.

Creazione di un'istanza dell'oggettoInstantiating the object

Solo i tipi di Windows Runtime possono essere passati attraverso il limite ABI.Only Windows Runtime types can be passed across the ABI boundary. Il compilatore genera un errore se il componente include un tipo come std::wstring come tipo restituito o parametro in un metodo pubblico.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. I tipi incorporati di Visual C++ Component Extensions (C++/CX) includono i consueti scalari, ad esempio int e Double, e i relativi equivalenti typedef Int32, float64 e così via.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. Per altre informazioni, vedi Sistema di tipi (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();

Tipi incorporati, tipi di librerie e tipi di Windows Runtime C++/CXC++/CX built-in types, library types, and Windows Runtime types

Una classe attivabile (nota anche come classe di riferimento) è una classe di cui è possibile creare un'istanza da un altro linguaggio, come 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. Per poter essere utilizzato da un altro linguaggio, un componente deve contenere almeno una classe attivabile.To be consumable from another language, a component must contain at least one activatable class.

Un componente Windows Runtime può contenere più classi attivabili pubbliche, nonché classi aggiuntive note solo internamente al componente.A Windows Runtime component can contain multiple public activatable classes as well as additional classes that are known only internally to the component. Applicare l'attributo WebHostHidden ai tipi C++/CX che non devono essere visibili a JavaScript.Apply the WebHostHidden attribute to C++/CX types that are not intended to be visible to JavaScript.

Tutte le classi pubbliche devono trovarsi nello stesso spazio dei nomi radice, che ha lo stesso nome del file di metadati del componente.All public classes must reside in the same root namespace which has the same name as the component metadata file. Ad esempio, è possibile creare un'istanza di una classe denominata A.B.C.MyClass solo se è definita in un file di metadati denominato A.winmd o 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. Il nome della DLL non deve necessariamente corrispondere al nome del file con estensione winmd.The name of the DLL is not required to match the .winmd file name.

Il codice client crea un’istanza del componente usando la parola chiave new (New in Visual Basic) come per qualsiasi classe.Client code creates an instance of the component by using the new (New in Visual Basic) keyword just as for any class.

Una classe attivabile deve essere dichiarata come public ref class sealed.An activatable class must be declared as public ref class sealed. La parola chiave ref class indica al compilatore di creare la classe come tipo compatibile con Windows Runtime e la parola chiave sealed specifica che la classe non può essere ereditata.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 attualmente non supporta un modello di ereditarietà generalizzato. Un modello di ereditarietà limitato supporta la creazione di controlli XAML personalizzati.The Windows Runtime does not currently support a generalized inheritance model; a limited inheritance model supports creation of custom XAML controls. Per altre informazioni, vedi Classi e struct di riferimento (C++/CX).For more information, see Ref classes and structs (C++/CX).

Per C++/CX, tutte le primitive numeriche sono definite nello spazio dei nomi predefinito.For C++/CX, all the numeric primitives are defined in the default namespace. Lo spazio dei nomi Platform contiene classi C++/CX specifiche del sistema di tipi Windows Runtime.The Platform namespace contains C++/CX classes that are specific to the Windows Runtime type system. Sono incluse le classi Platform::String e Platform::Object.These include Platform::String class and Platform::Object class. I tipi di raccolte concreti come le classi Platform::Collections::Map e Platform::Collections::Vector sono definiti nello spazio dei nomi Platform::Collections.The concrete collection types such as Platform::Collections::Map class and Platform::Collections::Vector class are defined in the Platform::Collections namespace. Le interfacce pubbliche implementate da questi tipi sono definite nello spazio dei nomi Windows::Foundation::Collections (C++/CX).The public interfaces that these types implement are defined in Windows::Foundation::Collections Namespace (C++/CX). Questi tipi di interfaccia vengono utilizzati da JavaScript, C# e Visual Basic.It is these interface types that are consumed by JavaScript, C# and Visual Basic. Per altre informazioni, vedi Sistema di tipi (C++/CX).For more information, see Type System (C++/CX).

Metodo che restituisce un valore di un tipo incorporatoMethod 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;

Metodo che restituisce uno struct di valori personalizzatoMethod 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;}
        }
    };
}

Per passare gli struct di valore definiti dall'utente nell'interfaccia ABI, definire un oggetto JavaScript con gli stessi membri dello struct valore definito in 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. È quindi possibile passare l'oggetto come argomento a un metodo C++/CX in modo che l'oggetto venga convertito in modo implicito nel tipo 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);
}

Un altro approccio consiste nel definire una classe che implementa IPropertySet (non illustrato).Another approach is to define a class that implements IPropertySet (not shown).

Nei linguaggi .NET è sufficiente creare una variabile del tipo definito nel componente 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();
}

Metodi di overloadOverloaded Methods

Una classe di riferimento pubblica C++/CX può contenere metodi di overload, ma JavaScript ha una capacità limitata di differenziare i metodi di overload.A C++/CX public ref class can contain overloaded methods, but JavaScript has limited ability to differentiate overloaded methods. Ad esempio, può rilevare la differenza tra queste firme: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);
};

Ma non può indicare la differenza tra questi:But it can't tell the difference between these:

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

In casi ambigui, puoi assicurarti che JavaScript chiami sempre un overload specifico applicando l’attributo Windows::Foundation::Metadata::DefaultOverload alla firma del metodo nel file di intestazione.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.

Questo codice JavaScript chiama sempre l'overload con l'attributo:This JavaScript always calls the attributed overload:

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

.NET.NET

I linguaggi .NET riconoscono gli overload in una classe di riferimento C++/CX esattamente come in qualsiasi classe .NET.The .NET languages recognize overloads in a C++/CX ref class just as in any .NET class.

DatetimeDateTime

In Windows Runtime un oggetto Windows::Foundation::DateTime è semplicemente un valore intero con segno a 64 bit che rappresenta il numero di intervalli di 100 nanosecondi prima o dopo l’1 gennaio 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. Un oggetto Windows:Foundation::DateTime non ha metodi.There are no methods on a Windows:Foundation::DateTime object. Al contrario, ogni linguaggio proietta il valore DateTime nel modo nativo per tale lingua: l'oggetto data in JavaScript e i tipi System. DateTime e System. DateTimeOffset in .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;
    }
};

Quando si passa un valore DateTime da C++/CX a JavaScript, JavaScript lo accetta come oggetto data e lo Visualizza per impostazione predefinita come stringa di data in formato esteso.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;

}

Quando un linguaggio .NET passa un oggetto System. DateTime a un componente C++/CX, il metodo lo accetta come 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. Quando il componente passa un oggetto Windows:: Foundation::D ateTime a un metodo .NET, il metodo Framework lo accetta come 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();
}

Raccolte e matriciCollections and arrays

Le raccolte vengono sempre passate attraverso il limite ABI come handle a tipi Windows Runtime come Windows::Foundation::Collections::IVector^ e 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^. Ad esempio, se restituisci un handle a un oggetto Platform::Collections::Map, viene convertito implicitamente in 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^. Le interfacce di raccolta sono definite in uno spazio dei nomi separato dalle classi C++/CX che forniscono le implementazioni concrete.The collection interfaces are defined in a namespace that's separate from the C++/CX classes that provide the concrete implementations. I linguaggi .NET e JavaScript utilizzano le interfacce.JavaScript and .NET languages consume the interfaces. Per altre informazioni, vedi Raccolte (C++/CX) e Array e WriteOnlyArray (C++/CX).For more information, see Collections (C++/CX) and Array and WriteOnlyArray (C++/CX).

Passaggio di 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;

I linguaggi .NET vedono IVector<T> come 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();
    }
}

Passaggio di 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;

I linguaggi .NET vedono 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();
}

ProprietàProperties

Una classe di riferimento pubblica nelle estensioni del componente C++/CX espone i membri dati pubblici come proprietà, usando la parola chiave Property.A public ref class in C++/CX component extensions exposes public data members as properties, by using the property keyword. Il concetto è identico a quello delle proprietà .NET.The concept is identical to .NET properties. Una proprietà semplice è simile a un membro dati perché la sua funzionalità è implicita.A trivial property resembles a data member because its functionality is implicit. Una proprietà non semplice ha funzioni di accesso get e set esplicite e una variabile privata denominata che funge da "archivio di backup" per il valore.A non-trivial property has explicit get and set accessors and a named private variable that's the "backing store" for the value. In questo esempio, la variabile membro privata _ propertyAValue è l'archivio di backup per PropertyA.In this example, the private member variable _propertyAValue is the backing store for PropertyA. Una proprietà può attivare un evento quando il suo valore cambia e un'app client può eseguire la registrazione per ricevere l'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;

I linguaggi .NET accedono alle proprietà in un oggetto C++/CX nativo esattamente come in un oggetto .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;

}

Delegati ed eventiDelegates and events

Un delegato è un tipo Windows Runtime che rappresenta un oggetto funzione.A delegate is a Windows Runtime type that represents a function object. Puoi usare i delegati insieme a eventi, callback e chiamate asincrone per specificare un'azione che deve essere eseguita in un secondo momento.You can use delegates in connection with events, callbacks, and asynchronous method calls to specify an action to be performed later. Analogamente a un oggetto funzione, il delegato fornisce indipendenza dai tipi consentendo al compilatore di verificare il tipo restituito e i tipi di parametro della funzione.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 dichiarazione di un delegato è simile a una firma di funzione, l'implementazione è simile a una definizione di classe e la chiamata è simile a una chiamata di funzione.The declaration of a delegate resembles a function signature, the implementation resembles a class definition, and the invocation resembles a function invocation.

Aggiunta di un listener di eventiAdding an event listener

Puoi usare la parola chiave event per dichiarare un membro pubblico di un tipo di delegato specifico.You can use the event keyword to declare a public member of a specified delegate type. Il codice client sottoscrive l'evento usando i meccanismi standard forniti nel linguaggio specifico.Client code subscribes to the event by using the standard mechanisms that are provided in the particular language.

public:
    event SomeHandler^ someEvent;

Questo esempio usa lo stesso codice C++ della sezione precedente relativa alle proprietà.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;

}

Nei linguaggi .NET, la sottoscrizione di un evento in un componente C++ equivale alla sottoscrizione di un evento in una classe .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();
}

Aggiunta di più listener di eventi per un eventoAdding multiple event listeners for one event

JavaScript ha un metodo addEventListener che consente a più gestori di sottoscrivere un singolo 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 ");

In C# un numero qualsiasi di gestori eventi può sottoscrivere l'evento usando l'operatore +=, come illustrato nell'esempio precedente.In C#, any number of event handlers can subscribe to the event by using the += operator as shown in the previous example.

EnumerazioniEnums

Una Windows Runtime enum in C++/CX viene dichiarata usando la classe pubblica enum; è simile a un'enumerazione con ambito in C++ standard.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;
};

I valori enum vengono passati tra C++/CX e JavaScript come numeri interi.Enum values are passed between C++/CX and JavaScript as integers. Facoltativamente, è possibile dichiarare un oggetto JavaScript che contiene gli stessi valori denominati dell'enumerazione C++/CX e usarlo come indicato di seguito.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];

Sia C# sia Visual Basic offrono supporto del linguaggio per le enumerazioni.Both C# and Visual Basic have language support for enums. Questi linguaggi visualizzano una classe enum pubblica C++, così come verrebbero visualizzati un'enumerazione .NET.These languages see a C++ public enum class just as they would see a .NET enum.

Metodi asincroniAsynchronous methods

Per usare metodi asincroni esposti da altri oggetti Windows Runtime, usa la classe task (runtime di concorrenza).To consume asynchronous methods that are exposed by other Windows Runtime objects, use the task Class (Concurrency Runtime). Per altre informazioni, vedi Parallelismo delle attività (runtime di concorrenza).For more information, see and Task Parallelism (Concurrency Runtime).

Per implementare metodi asincroni in C++/CX, usare la funzione Create _ Async definita in ppltasks. h.To implement asynchronous methods in C++/CX, use the create_async function that's defined in ppltasks.h. Per altre informazioni, vedere creazione di operazioni asincrone in C++/CX per app UWP.For more information, see Creating Asynchronous Operations in C++/CX for UWP apps. Per un esempio, vedere la procedura dettagliata per la creazione di un componente Windows Runtime C++/CX e la chiamata da JavaScript o C#.For an example, see Walkthrough of creating a C++/CX Windows Runtime component, and calling it from JavaScript or C#. I linguaggi .NET utilizzano i metodi asincroni C++/CX proprio come qualsiasi metodo asincrono definito in .NET.The .NET languages consume C++/CX asynchronous methods just as they would any asynchronous method that's defined in .NET.

EccezioniExceptions

Puoi generare qualsiasi tipo di eccezione definito da Windows Runtime.You can throw any exception type that's defined by the Windows Runtime. Non puoi derivare tipi personalizzati da qualsiasi tipo di eccezione Windows Runtime.You cannot derive custom types from any Windows Runtime exception type. Tuttavia, puoi generare un'eccezione COMException e fornire un valore HRESULT personalizzato a cui il codice che intercetta l'eccezione può accedere.However, you can throw COMException and provide a custom HRESULT that can be accessed by the code that catches the exception. Non è possibile specificare un messaggio personalizzato in un oggetto COMException.There's no way to specify a custom Message in a COMException.

Suggerimenti per il debugDebugging tips

Quando esegui il debug di una soluzione JavaScript che ha una DLL di un componente, puoi impostare il debugger in modo che esegua le istruzioni dello script o del codice nativo nel componente, ma non di entrambi contemporaneamente.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. Per modificare l'impostazione, seleziona il nodo del progetto JavaScript in Esplora soluzioni e quindi scegli Proprietà, Debug, Tipo di debugger.To change the setting, select the JavaScript project node in Solution Explorer and then choose Properties, Debugging, Debugger Type.

Assicurati di selezionare le funzionalità appropriate nella finestra di progettazione del pacchetto.Be sure to select appropriate capabilities in the package designer. Ad esempio, se stai provando ad aprire un file di immagine della raccolta di immagini dell'utente usando le API Windows Runtime, assicurati di selezionare la casella di controllo Raccolta di immagini nel riquadro Funzionalità della finestra di progettazione del pacchetto.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.

Se il codice JavaScript non sembra riconoscere le proprietà o i metodi pubblici nel componente, assicurati di usare la notazione camel in 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. Ad esempio, è necessario fare riferimento al metodo LogCalc C++/CX come logCalc in JavaScript.For example, the LogCalc C++/CX method must be referenced as logCalc in JavaScript.

Se si rimuove un progetto di componente Windows Runtime C++/CX da una soluzione, è necessario rimuovere manualmente anche il riferimento al progetto dal progetto 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. In caso contrario, le operazioni di debug o compilazione successive non saranno possibili.Failure to do so prevents subsequent debug or build operations. Se necessario, puoi quindi aggiungere alla DLL un riferimento a un assembly.If necessary, you can then add an assembly reference to the DLL.