C++/WinRT Runtime Component in Win32 Applications

Part 3



Creazione di un'applicazione C++ Win32 che "consuma" un Runtime Component C++/WinRT.

Nota:
Nelle stessa soluzione Visual Studio, creeremo un progetto Runtime Component C++/WinRT nel quale implementeremo delle runtime classes ed un progetto app Win32 C++ Classic che userà le stesse.
Per l'app Win32 classic userò un Project Template per Visual Studio 2019 basato sull'omonimo framework C++ per Win32: Win32Framework, nella sua versone con Ribbon che spesso, io stesso e il mio team, usiamo come base iniziale per le app C++ Win32 in quanto semplifica e velocizza il lavoro.
(il Project Template ed il Win32Framework sono entrambi di mia creazione e distribuiti in via esclusiva internamente al mio team C++, non è escluso comunque che in futuro possa rilasciare una versione del Win32Framework su questo website o su GitHub).
Naturalmente Win32Framework non è un requisito obbligatiorio e siete ovviamente liberi di usare la tipologia di progetto C++ che più vi aggrada, a patto che sia basato sul C++ standard 17.


Il primo passo sarà quindi creare un nuovo progetto C++ in Visual Studio 2019.

Nota:
In questo tutorial è stato usato Visual Studio 2019 vers. 16.8.x


Scegliamo un nome significativo per il nuovo progetto, io ho scelto UWPWin32Demo, e creato la relativa cartella con lo stesso nome.

New solution Set name



Una volta creato il progetto ci accoglie la pagina di benvenuto e licenza del framework, il file Readme ed le tabs con già aperti i files CFrameWindow.h e CFrameWindow.cpp.

Project ready Project ready Project ready Project ready


Nota: il progetto basato sul framework Win32Framework Ribbon è già predisposto per essere compilato con il linguaggio C++ standard 17. Qualora il vostro progetto non lo sia andare in Properties -> General -> C++ Language Standard e assicurarsi di scegliere la versione 17 [ISO C++17 Standard (/std:c++17)]

Set C++ 17 Project running

Facciamo il build dell'applicazione per verificare che tutto sia OK, o mandiamo in run una sessione di Debug l'app Win32 (vedi immagini qui sopra).


Se anche la vostra app di partenza C++ Win32, compilata con la versione C++ standard 17 è OK, passiamo al secondo step: il Runtime Component custom che verrà consumato dalla nostra applicazione.

Nota:
Affinchè un Runtime Component possa essere "consumato" da altre applicazioni, la classe deve essere obbligatoriamente una runtime class.
Se volessimo usare il runtime component in un'applicazione locale cioè esclusivamente nello stesso progetto sarebbe sufficiente una classe C++ ordinaria.


Aggiungiamo un nuovo progetto e scegliamo il template: Windows Runtime Component C++/WinRT.

Il componente WinRT in questo esempio gestirà un sistema elimina code per cui diamo un nome significativo al progetto UWP: TicketMachine.
Scegliamo il target minimo e massimo del sistema operativo e confermiamo.

Set C++ 17 Project running Project running Project running


Come già detto (vedi parte 1), il wizard di Visual Studio, oltre a tutto ciò che serve per compilare e istanziare correttamente a runtime il componente, ha creato per noi una runtime class di nome Class ed il file IDL Class.idl:

Più precisamente troviamo 3 files:

Rename IDL


Nel file .idl vengono definite le classi C++/WinRT (Runtime Classes).

Aprendo il file .idl (Interface Definition Language), che verrà dato in pasto allo strumento MIDL (Microsoft Interface Definition Language) durante la compilazione del progetto, si può vedere la nuova sintassi del linguaggio IDL nella sua versione 3.0.
Per chi non conoscesse COM (Component Object Model) ricordo che i files .idl vengono usati per descrivere i tipi e le interfacce COM.
Chi invece conosce COM e quindi IDL "tradizionale" troverà alquanto diversa la sintassi in quanto, nella versione aggiornata, il linguaggio è stato semplificato e modificato per supportare i tipi di Windows Runtime.


Nella soluzione in Visual Studio selezioniamo il progetto UWP TicketMachine; per prima cosa rinominiamo il file Class.idl. Scegliamo un nome significativo.

Nota
In C++/WinRT per ogni file .idl viene creato un corrispondente file .winmd, per cui per evitare di avere vari file .winmd, dichiarerò tutte le interfacce e classi in un unico file .idl.
Questa tecnica è perfettamente legale e consente, in progetti complessi, di abbreviare di molto i tempi di build.


Nel nostro esempio interfacce e classi saranno raccolte (vedi nota qui sopra) in un unico file .idl; chiamerò quest'ultimo Common.idl. Una volta rinominato il file .idl, i due file, header e implementation, (rispettivamente Class.h e Class.cpp) vengono rinominati automaticamente.

IDL rename



Una volta rinominati i 3 files dobbiamo correggere gli includes e il nome della classe che di default sono riferiti a Class.

Change class reference Change class reference



Proseguiamo compilando una prima volta il progetto TicketMachine, creando così la prima versione (anche se al momento inutile) dei files TicketMachine.winmd e TicketMachine.dll.

Vedremo più avanti che al momento opportuno la DLL verrà caricata a runtime (o per meglio dire, il sistema operativo lo farà per noi) e, attraverso essa, avremo accesso ai metadati contenuti nel file .winmd dalla nostra applicazione Win32; infatti, dato che non è possibile (almeno attualmente) importare direttamente in una applicazione Win32 nativa i tipi contenuti in un file .winmd, questo è (al momento) il modo per accedere ai metadati. Se pensavate di potervela cavare semplicemente importando in un progetto Win32 nativo un file .winmd aggiungendo una reference in Visual Studio, beh vi ricredereste se ci provaste in quanto Visual Studio vi sbarrerebbe la strada con l'avviso qui sotto:

No reference admitted




Breve analisi per il componente C++/WinRT di esempio.

Il nostro progetto di esempio ci consentirà di vedere all'opera incapsulazione, ereditarietà e polimorfismo dal punto di vista C++/WinRT; progetteremo un componente WinRT che gestisce delle code agli sportelli di un ipotetico ufficio e un'applicazione client C++ Win32 Classic che "consumerà" il medesimo .
Sempre nel componente implementeremo anche alcuni eventi che potranno poi essere gestiti, oltre che nel client Win32, nelle applicazioni (che siano esse UWP, .Net etc.) eventualmente implementate in futuro.

Per prima cosa individuiamo le entità coinvolte:

→ Servizi
→ Sportelli
→ Operatori
→ Totem per i tickets
→ Tickects via smartphone app
→ Coda operazioni in attesa
→ Log operazioni completate


Qualche specifica iniziale:

→ Un operatore, per ogni giornata lavorativa, può essere assegnato ad un qualunque sportello.
→ Ogni operatore al suo sportello può eseguire tutti i servizi.
→ Per ogni ticket in coda si deve indicare il tempo stimato di attesa.
→ All'emissione del ticket deve essere generato un evento di inizio attesa
→ Al completamento dell'operazione dev'essere generato un evento di chiusura operazione.


Da quanto sopra si deduce si debbano implementare le seguenti interfacce e classi:


Rappresentiamo con un grafico UML le relazioni che intendiamo sviluppare.

Interfaces and classes Aggregation/Composition




Definiamo interfacce e classi nel file Common.idl


////====================================================================
//                          TicketMachine 
//                          C++/WinRT Component 
//
//                          Copyright (C) 2021
//                          G.Pischedda, all rights reserved
//                          software-on-demand-ita.com
////=====================================================================

namespace TicketMachine
{

    //New type Date
    interface IDate
    {
    Int32 Year;
    Int32 Month;
    Int32 Day;    
    };

    //New type Time    
    interface ITime
    {
        Int32 Hh;
        Int32 Mm;
        Int32 Ss;    
    };

   
    unsealed runtimeclass Date:  IDate,ITime
    {
        Date();
        String DateToString{get; };
        String TimeToString{ get; };       
    };

    //Services
    interface IServices
    {
        String ServiceCode;
        String ServiceName;
    };

    runtimeclass Service : IServices, ICommon
    {
        Service();
        Windows.Foundation.IAsyncOperation<IVector<Service> > GetCollection{ get; };        
    }


    //Tickets
    interface IImageFiles
    {
        Windows.Storage.StorageFile ImageFile;
    };

   
    
    
    interface ITickets
    {
        String TicketNumber;
        String TicketBarcode;      
        Int32 MaxQueueItems;
        Date CreationDate;
        Windows.Storage.StorageFile TicketQRCode;
    };

    
    
   

    unsealed runtimeclass Ticket: ITickets, IImageFiles, ICommon,IServices,IDesks,IOperators
    {
        Ticket();
        void Create();
        String TicketToString{ get; };

       
        
    }
    
    //Desks
    interface IDesks
    {
        String DeskNumber;
        String DeskCode;
        String DeskName;

    };

    runtimeclass Desk: IDesks, ICommon
    {
        Desk();
        Windows.Foundation.IAsyncOperation<IVector<Desk> > GetCollection{ get; };
    }

    //Operators
    interface IOperators
    {
        String FirstName;
        String LastName;
        Date BirthDate;

    };

    runtimeclass Operator : IOperators, ICommon
    {
        Operator();
        String BadgeCode;
        Windows.Foundation.IAsyncOperation<IVector<Operator> > GetCollection{ get; };
    }

    //Operations Queue
    [default_interface]
    unsealed runtimeclass OperationsQueue : IServices, IDesks, ITickets,ICommon
    {
        OperationsQueue();

        Windows.Foundation.IAsyncOperation<IVector<OperationsQueue> > GetCollection{ get; };

        //Events Methods
        void OperationItemAdded(Boolean isAdded);       
        void OperationCompleted(Boolean isCompleted);

       
        //Events
        event Windows.Foundation.EventHandler<TicketMachine.StartQueueEventArgs> OnQueueItemAdded;
        event Windows.Foundation.EventHandler<TicketMachine.CloseOperationEventArgs> OnOperationCompleted;

    };


    //Operations Log
    [default_interface]
    unsealed runtimeclass OperationsLog : IServices, ITickets, ICommon
    {
        OperationsLog();

        Windows.Foundation.IAsyncOperation<IVector<OperationsLog> > GetCollection{ get; };

       
    };


    interface ICommon
    {
        void Add();
        void Edit();
        void Delete();
        void Save();
    };

    [default_interface]
    unsealed runtimeclass Common: ICommon
    {
        Common();
        
    }



    //Events
    runtimeclass StartQueueEventArgs
    {
        Boolean ItemAdded{get; };
    };

    runtimeclass CloseOperationEventArgs
    {
        Boolean OperationClosed{get; };

    };
}



Compiliamo il progetto TicketMachine per consentire a Visual Studio di creare tutti i file stubs (h e cpp).

Stubs



Ora apriamo la cartella del progetto TicketMachine e creiamo una nuova cartella con nome a scelta, io la chiamerò Generated. All'interno di questa copiamo tutti i files (h e cpp) che Visual Studio ha creato nella subfolder del progetto ..\TicketMachine\Generated Files\sources tranne Common.h e Common.cpp
Quindi in Solution Explorer, nel filtro Generated Files facciamo click destro -> Add -> Existing Item... e aggiungiamo tutti i files della cartella appena creata (Generated nel mio caso).


Stubs Stubs Stubs



Commentiamo in tutti i files della cartella Generated (h e cpp) la riga :
static_assert(false, "Do not compile generated C++/WinRT source files directly");

Compiliamo il progetto TicketMachine e assicuriamoci TicketMachine.winmd e TicketMachine.dll siano stati prodotti da Visual Studio.

Binaries



Tra poco vedremo come consumare il nostro componente WinRT in un applicazione Win32 nativa, prima però occupiamoci di implementare, nelle rispettive classi, proprietà, metodi ed eventi.

Implementeremo per prime le classi Date, Service, Operator, Desk e Ticket.
La classe Date ha lo scopo di implementare due nuovi titoi di dati (Date e Time); Service, Operator e Ticket forniranno una lista statica, rispettivamente, dei servizi, degli operatori e degli sportelli; ovviamente in una reale applicazione questi dati proverrebbero da un database o da un webservice. La classe Ticket servirà per (appunto) creare i tickets delle prenotazioni agli sportelli.

Date.h

////====================================================================
//                          TicketMachine 
//                          C++/WinRT Component 
//
//                          Copyright (C) 2021
//                          G.Pischedda, all rights reserved
//                          software-on-demand-ita.com
////=====================================================================

#pragma once
#include "Date.g.h"

// Note: Remove this static_assert after copying these generated source files to your project.
// This assertion exists to avoid compiling these generated source files directly.
//static_assert(false, "Do not compile generated C++/WinRT source files directly");

namespace winrt::TicketMachine::implementation
{
    struct Date : DateT<Date>
    {
        Date() = default;

        hstring DateToString();
        hstring TimeToString();
        int32_t Year();
        void Year(int32_t value);
        int32_t Month();
        void Month(int32_t value);
        int32_t Day();
        void Day(int32_t value);
        int32_t Hh();
        void Hh(int32_t value);
        int32_t Mm();
        void Mm(int32_t value);
        int32_t Ss();
        void Ss(int32_t value);

    private:
        int32_t m_year{ 0 };
        int32_t m_month{ 0 };
        int32_t m_day{ 0 };
        int32_t m_hh{ 0 };
        int32_t m_mm{ 0 };
        int32_t m_ss{ 0 };

        hstring Format(int32_t t);

    };
}
namespace winrt::TicketMachine::factory_implementation
{
    struct Date : DateT<Date, implementation::Date>
    {
    };
}


Date.cpp

////====================================================================
//                          TicketMachine 
//                          C++/WinRT Component 
//
//                          Copyright (C) 2021
//                          G.Pischedda, all rights reserved
//                          software-on-demand-ita.com
////=====================================================================

#include "pch.h"
#include "Date.h"
#include "Date.g.cpp"

// Note: Remove this static_assert after copying these generated source files to your project.
// This assertion exists to avoid compiling these generated source files directly.
//static_assert(false, "Do not compile generated C++/WinRT source files directly");

namespace winrt::TicketMachine::implementation
{
    hstring Date::DateToString()
    {
        //throw hresult_not_implemented();
        hstring tmpDate = winrt::to_hstring(m_month) + L"/" + to_hstring(m_day)+L"/"+to_hstring(m_year);
        return tmpDate;
    }
    hstring Date::TimeToString()
    {
       // throw hresult_not_implemented();
        hstring tmpTime = L"";
        tmpTime =  Format(m_hh) + L":" + Format(m_mm) + L":" + Format(m_ss);
        return tmpTime;
    }


    hstring implementation::Date::Format(int32_t t)
    {
        hstring tmpTime = to_hstring(t);

        switch (tmpTime.size())
        {
        case 1:tmpTime = L"0" + tmpTime; break;
        }
        return tmpTime;
    }


    int32_t Date::Year()
    {
       // throw hresult_not_implemented();
        return m_year;
    }
    void Date::Year(int32_t value)
    {
        //throw hresult_not_implemented();
        m_year = value;
    }
    int32_t Date::Month()
    {
       // throw hresult_not_implemented();
        return m_month;
    }
    void Date::Month(int32_t value)
    {
        //throw hresult_not_implemented();
        m_month = value;
    }
    int32_t Date::Day()
    {
       //throw hresult_not_implemented();
        return m_day;
    }
    void Date::Day(int32_t value)
    {
        //throw hresult_not_implemented();
        m_day = value;
    }
    int32_t Date::Hh()
    {
        //throw hresult_not_implemented();
        return m_hh;

    }
    void Date::Hh(int32_t value)
    {
        //throw hresult_not_implemented();
        m_hh = value;
    }
    int32_t Date::Mm()
    {
        //throw hresult_not_implemented();
        return m_mm;
    }
    void Date::Mm(int32_t value)
    {
        //throw hresult_not_implemented();
        m_mm = value;
    }
    int32_t Date::Ss()
    {
        //throw hresult_not_implemented();
        return m_ss;
    }
    void Date::Ss(int32_t value)
    {
        //throw hresult_not_implemented();
        m_ss = value;
    }
}

Service.h

////====================================================================
//                          TicketMachine 
//                          C++/WinRT Component 
//
//                          Copyright (C) 2021
//                          G.Pischedda, all rights reserved
//                          software-on-demand-ita.com
////=====================================================================


#pragma once
#include "Service.g.h"

// Note: Remove this static_assert after copying these generated source files to your project.
// This assertion exists to avoid compiling these generated source files directly.
//static_assert(false, "Do not compile generated C++/WinRT source files directly");

namespace winrt::TicketMachine::implementation
{
    struct Service : ServiceT<Service>
    {
        Service() = default;
       
        Windows::Foundation::IAsyncOperation<Windows::Foundation::Collections::IVector<TicketMachine::Service>> GetCollection();

        hstring ServiceCode();
        void ServiceCode(hstring const& value);
        hstring ServiceName();
        void ServiceName(hstring const& value);
        
       //Common
        void Add();
        void Edit();
        void Delete();
        void Save();

    private:       
        hstring m_serviceCode{ L"" };
        hstring m_serviceName{ L"" };
        Windows::Foundation::Collections::IVector<TicketMachine::Service> m_services;
    };
}
namespace winrt::TicketMachine::factory_implementation
{
    struct Service : ServiceT<Service, implementation::Service>
    {
    };
}



Service.cpp

////====================================================================
//                          TicketMachine 
//                          C++/WinRT Component 
//
//                          Copyright (C) 2021
//                          G.Pischedda, all rights reserved
//                          software-on-demand-ita.com
////=====================================================================

#include "pch.h"
#include "Service.h"
#include "Service.g.cpp"

#include <winrt/Windows.Foundation.Collections.h>

// Note: Remove this static_assert after copying these generated source files to your project.
// This assertion exists to avoid compiling these generated source files directly.
//static_assert(false, "Do not compile generated C++/WinRT source files directly");

namespace winrt::TicketMachine::implementation
{
    
    
    
    
    Windows::Foundation::IAsyncOperation<Windows::Foundation::Collections::IVector<TicketMachine::Service>> Service::GetCollection()
    {



        winrt::TicketMachine::Service srv[4];
       
        m_services = winrt::single_threaded_vector<winrt::TicketMachine::Service>();

       int i = 0;
       while (i <= 4)
       {

            srv[i] = winrt::make<winrt::TicketMachine::implementation::Service>();

            switch (i)
            {
            case 0: srv[i].ServiceCode(L"01");
                    srv[i].ServiceName(L"Currency Exchanges"); 
                    break;
            case 1: srv[i].ServiceCode(L"02");
                    srv[i].ServiceName(L"Front Desk Customer Service"); 
                    break;
            case 2: srv[i].ServiceCode(L"03");
                    srv[i].ServiceName(L"Computer&Smartphone Assistance"); 
                    break;
            case 3: srv[i].ServiceCode(L"04");
                    srv[i].ServiceName(L"Lost&Found"); 
                    break;
            case 4: srv[i].ServiceCode(L"05");
                    srv[i].ServiceName(L"Parking"); 
                    break;
            }


            m_services.Append(srv[i]);

            ++i;
        }



       co_return m_services;

    }


    hstring Service::ServiceCode()
    {
        return m_serviceCode;
    }
    void Service::ServiceCode(hstring const& value)
    {
         m_serviceCode = value;
    }
    hstring Service::ServiceName()
    {
        return m_serviceName;
    }
    void Service::ServiceName(hstring const& value)
    {

        m_serviceName = value;
    }
    void Service::Add()
    {
        //throw hresult_not_implemented();
    }
    void Service::Edit()
    {
        //throw hresult_not_implemented();
    }
    void Service::Delete()
    {
        //throw hresult_not_implemented();
    }
    void Service::Save()
    {
        //throw hresult_not_implemented();
    }
}



Operator.h

////====================================================================
//                          TicketMachine 
//                          C++/WinRT Component 
//
//                          Copyright (C) 2021
//                          G.Pischedda, all rights reserved
//                          software-on-demand-ita.com
////=====================================================================

#pragma once
#include "Operator.g.h"

// Note: Remove this static_assert after copying these generated source files to your project.
// This assertion exists to avoid compiling these generated source files directly.
//static_assert(false, "Do not compile generated C++/WinRT source files directly");

namespace winrt::TicketMachine::implementation
{
    struct Operator : OperatorT<Operator>
    {
        Operator() = default;

        hstring BadgeCode();
        void BadgeCode(hstring const& value);
        Windows::Foundation::IAsyncOperation<Windows::Foundation::Collections::IVector<TicketMachine::Operator>> GetCollection();
        hstring FirstName();
        void FirstName(hstring const& value);
        hstring LastName();
        void LastName(hstring const& value);
        TicketMachine::Date BirthDate();
        void BirthDate(TicketMachine::Date const& value);

        //Common
        void Add();
        void Edit();
        void Delete();
        void Save();

    private:
        hstring m_badgeCode{ L"" };
        hstring m_firstName{ L"" };
        hstring m_lastName{ L"" };
        TicketMachine::Date m_birthDate;
        Windows::Foundation::Collections::IVector<TicketMachine::Operator> m_operators;

    };
}
namespace winrt::TicketMachine::factory_implementation
{
    struct Operator : OperatorT<Operator, implementation::Operator>
    {
    };
}

Operator.cpp

////====================================================================
//                          TicketMachine 
//                          C++/WinRT Component 
//
//                          Copyright (C) 2021
//                          G.Pischedda, all rights reserved
//                          software-on-demand-ita.com
////=====================================================================

#include "pch.h"
#include "Operator.h"
#include "Operator.g.cpp"


#include <winrt/Windows.Foundation.Collections.h>

// Note: Remove this static_assert after copying these generated source files to your project.
// This assertion exists to avoid compiling these generated source files directly.
//static_assert(false, "Do not compile generated C++/WinRT source files directly");

namespace winrt::TicketMachine::implementation
{
    hstring Operator::BadgeCode()
    {
        return m_badgeCode;
    }
    void Operator::BadgeCode(hstring const& value)
    {
        m_badgeCode = value;
    }
    
    
    Windows::Foundation::IAsyncOperation<Windows::Foundation::Collections::IVector<TicketMachine::Operator>> Operator::GetCollection()
    {
        winrt::TicketMachine::Operator opr[4];
        m_operators = winrt::single_threaded_vector<winrt::TicketMachine::Operator>();


        int i = 0;
        while (i <= 4)
        {

            opr[i] = winrt::make<winrt::TicketMachine::implementation::Operator>();


            switch (i)
            {
            case 0:  opr[i].BadgeCode(L"8C8882D9-5BDE-4FDA-86C7-DB9926DB75AE");
                     opr[i].FirstName(L"Mario");
                     opr[i].LastName(L"Rossi");
                     m_birthDate.Year(2001); m_birthDate.Month(12); m_birthDate.Day(10);
                     opr[i].BirthDate(m_birthDate);
                     break;

            case 1:  opr[i].BadgeCode(L"441661CA-9A44-4B6A-AA4B-B99B13F4C214");
                     opr[i].FirstName(L"Franco");
                     opr[i].LastName(L"Verdi");
                     m_birthDate.Year(1976); m_birthDate.Month(4); m_birthDate.Day(22);
                     opr[i].BirthDate(m_birthDate);
                     break;

            case 2:  opr[i].BadgeCode(L"1F10AFF3-4365-445B-B256-AFFA2CCC8BF7");
                     opr[i].FirstName(L"Gianna");
                     opr[i].LastName(L"Gialli");
                     m_birthDate.Year(1985); m_birthDate.Month(5); m_birthDate.Day(31);
                     opr[i].BirthDate(m_birthDate);
                     break;

            case 3:  opr[i].BadgeCode(L"FE1F901F-6BBF-45F0-8885-DE049153FFD0");
                     opr[i].FirstName(L"Maria");
                     opr[i].LastName(L"Bianchi");
                     m_birthDate.Year(1998); m_birthDate.Month(12); m_birthDate.Day(19);
                     opr[i].BirthDate(m_birthDate);
                     break;


            case 4:  opr[i].BadgeCode(L"C3D6F5F7-7981-433B-8A7E-61DD6AF8735E");
                     opr[i].FirstName(L"Rosa");
                     opr[i].LastName(L"Neri");
                     m_birthDate.Year(1990); m_birthDate.Month(2); m_birthDate.Day(22);
                     opr[i].BirthDate(m_birthDate);
                     break;


            }


            m_operators.Append(opr[i]);

            ++i;
        }



        co_return m_operators;
    }
    hstring Operator::FirstName()
    {
        return m_firstName;
    }
    void Operator::FirstName(hstring const& value)
    {
        m_firstName = value;
    }
    hstring Operator::LastName()
    {
        return m_lastName;
    }
    void Operator::LastName(hstring const& value)
    {
        m_lastName = value;
    }
    TicketMachine::Date Operator::BirthDate()
    {
        return m_birthDate;
    }
    void Operator::BirthDate(TicketMachine::Date const& value)
    {
        m_birthDate = value;
    }
    void Operator::Add()
    {
        //throw hresult_not_implemented();
    }
    void Operator::Edit()
    {
        //throw hresult_not_implemented();
    }
    void Operator::Delete()
    {
        //throw hresult_not_implemented();
    }
    void Operator::Save()
    {
        //throw hresult_not_implemented();
    }
}



Desk.h

////====================================================================
//                          TicketMachine 
//                          C++/WinRT Component 
//
//                          Copyright (C) 2021
//                          G.Pischedda, all rights reserved
//                          software-on-demand-ita.com
////=====================================================================



#pragma once
#include "Desk.g.h"

// Note: Remove this static_assert after copying these generated source files to your project.
// This assertion exists to avoid compiling these generated source files directly.
//static_assert(false, "Do not compile generated C++/WinRT source files directly");

namespace winrt::TicketMachine::implementation
{
    struct Desk : DeskT<Desk>
    {
        Desk() = default;

        Windows::Foundation::IAsyncOperation<Windows::Foundation::Collections::IVector<TicketMachine::Desk>> GetCollection();
        hstring DeskNumber();
        void DeskNumber(hstring const& value);
        hstring DeskCode();
        void DeskCode(hstring const& value);
        hstring DeskName();
        void DeskName(hstring const& value);

        //Common
        void Add();
        void Edit();
        void Delete();
        void Save();

    private:
        hstring m_deskNumber{ L"" };
        hstring m_deskCode{ L"" };
        hstring m_deskName {L"" };
        Windows::Foundation::Collections::IVector<TicketMachine::Desk> m_desks;

    };
}
namespace winrt::TicketMachine::factory_implementation
{
    struct Desk : DeskT<Desk, implementation::Desk>
    {
    };
}

Desk.cpp

////====================================================================
//                          TicketMachine 
//                          C++/WinRT Component 
//
//                          Copyright (C) 2021
//                          G.Pischedda, all rights reserved
//                          software-on-demand-ita.com
////=====================================================================



#include "pch.h"
#include "Desk.h"
#include "Desk.g.cpp"

// Note: Remove this static_assert after copying these generated source files to your project.
// This assertion exists to avoid compiling these generated source files directly.
//static_assert(false, "Do not compile generated C++/WinRT source files directly");

namespace winrt::TicketMachine::implementation
{
    Windows::Foundation::IAsyncOperation$lt;Windows::Foundation::Collections::IVector<TicketMachine::Desk>> Desk::GetCollection()
    {
        winrt::TicketMachine::Desk dsk[4];
        m_desks = winrt::single_threaded_vector<winrt::TicketMachine::Desk>();

        int i = 0;
        while (i <= 4)
        {

            dsk[i] = winrt::make<winrt::TicketMachine::implementation::Desk>();


            switch (i)
            {

            case 0: dsk[i].DeskNumber(L"1");
                    dsk[i].DeskCode(L"A");
                    dsk[i].DeskName(L"A01");
                    break;

            case 1: dsk[i].DeskNumber(L"2");
                    dsk[i].DeskCode(L"B");
                    dsk[i].DeskName(L"B02");
                    break;

            case 2: dsk[i].DeskNumber(L"3");
                    dsk[i].DeskCode(L"C");
                    dsk[i].DeskName(L"C03");
                    break;

            case 3: dsk[i].DeskNumber(L"4");
                    dsk[i].DeskCode(L"D");
                    dsk[i].DeskName(L"D04");
                    break;

            case 4: dsk[i].DeskNumber(L"5");
                    dsk[i].DeskCode(L"E");
                    dsk[i].DeskName(L"E05");
                    break;

            }

            m_desks.Append(dsk[i]);

            ++i;

        }

        co_return m_desks;

    }
    hstring Desk::DeskNumber()
    {
        return m_deskNumber;
    }
    void Desk::DeskNumber(hstring const& value)
    {
        m_deskNumber = value;
    }
    hstring Desk::DeskCode()
    {
        return m_deskCode;
    }
    void Desk::DeskCode(hstring const& value)
    {
        m_deskCode = value;
    }
    hstring Desk::DeskName()
    {
        return m_deskName;
    }
    void Desk::DeskName(hstring const& value)
    {
        m_deskName = value;
    }


    void Desk::Add()
    {
       // throw hresult_not_implemented();
    }
    void Desk::Edit()
    {
        //throw hresult_not_implemented();
    }
    void Desk::Delete()
    {
        //throw hresult_not_implemented();
    }
    void Desk::Save()
    {
        //throw hresult_not_implemented();
    }
}




Ticket.h

////====================================================================
//                          TicketMachine 
//                          C++/WinRT Component 
//
//                          Copyright (C) 2021
//                          G.Pischedda, all rights reserved
//                          software-on-demand-ita.com
////=====================================================================


#pragma once
#include "Ticket.g.h"

// Note: Remove this static_assert after copying these generated source files to your project.
// This assertion exists to avoid compiling these generated source files directly.
//static_assert(false, "Do not compile generated C++/WinRT source files directly");

namespace winrt::TicketMachine::implementation
{
    struct Ticket : TicketT<Ticket>
    {
        Ticket() = default;

        void Create();
        hstring TicketNumber();
        void TicketNumber(hstring const& value);
        hstring TicketBarcode();
        void TicketBarcode(hstring const& value);
        int32_t MaxQueueItems();
        void MaxQueueItems(int32_t value);
        TicketMachine::Date CreationDate();
        void CreationDate(TicketMachine::Date const& value);
        Windows::Storage::StorageFile TicketQRCode();
        void TicketQRCode(Windows::Storage::StorageFile const& value);
        Windows::Storage::StorageFile ImageFile();
        void ImageFile(Windows::Storage::StorageFile const& value);
        hstring TicketToString();


        //Common
        void Add();
        void Edit();
        void Delete();
        void Save();

        //Services
        hstring ServiceCode();
        void ServiceCode(hstring const& value);
        hstring ServiceName();
        void ServiceName(hstring const& value);

        //Desks
        hstring DeskNumber();
        void DeskNumber(hstring const& value);
        hstring DeskCode();
        void DeskCode(hstring const& value);
        hstring DeskName();
        void DeskName(hstring const& value);

        //Operators
        hstring FirstName();
        void FirstName(hstring const& value);
        hstring LastName();
        void LastName(hstring const& value);
        TicketMachine::Date BirthDate();
        void BirthDate(TicketMachine::Date const& value);

       
    private:
       
        hstring m_ticketNumber{ L"" };
        hstring m_ticketBarcode{ L"" };
        int32_t m_maxQueueElements{ 100 };
        winrt::TicketMachine::Date m_creationDate;

        winrt::TicketMachine::Service m_service;
        winrt::TicketMachine::Desk m_desk;
        winrt::TicketMachine::Operator m_operator;

        int m_index = 0;

        hstring m_ticketString = L"";       


        //Services
        hstring m_serviceCode{ L"" };
        hstring m_serviceName{ L"" };

        //Desks
        hstring m_deskNumber{ L"" };
        hstring m_deskCode{ L"" };
        hstring m_deskName{ L"" };

        //Operators
        hstring m_badgeCode{ L"" };
        hstring m_firstName{ L"" };
        hstring m_lastName{ L"" };
        TicketMachine::Date m_birthDate;

        TicketMachine::Date GetDate();

       
    };
}
namespace winrt::TicketMachine::factory_implementation
{
    struct Ticket : TicketT<Ticket, implementation::Ticket>
    {
    };
}



Ticket.cpp

////====================================================================
//                          TicketMachine 
//                          C++/WinRT Component 
//
//                          Copyright (C) 2021
//                          G.Pischedda, all rights reserved
//                          software-on-demand-ita.com
////=====================================================================


#include "pch.h"
#include "Ticket.h"
#include "Ticket.g.cpp"

#include "Helpers.h"
#include <ctime>


using namespace winrt::Windows::Foundation;
using namespace winrt::Windows::Foundation::Collections;
// Note: Remove this static_assert after copying these generated source files to your project.
// This assertion exists to avoid compiling these generated source files directly.
//static_assert(false, "Do not compile generated C++/WinRT source files directly");

namespace winrt::TicketMachine::implementation
{
   
    
    void Ticket::Create()
    {
      

       // Get Services
        winrt::TicketMachine::Service srv;
        Collection<winrt::TicketMachine::Service> _srv;
        
        auto _services = _srv.GetItems(srv,true);        
        //===========================
               

        // Get Desks
        winrt::TicketMachine::Desk dsk;
        Collection<winrt::TicketMachine::Desk> _dsk;

        auto _desks = _dsk.GetItems(dsk, true);
        //===========================
       
               

        // Get Operators
        winrt::TicketMachine::Operator opr;
        Collection<winrt::TicketMachine::Operator> _opr;

        auto _operators = _opr.GetItems(opr, true);
        //===========================

       
        //Check ticket number        
        if (m_index > m_maxQueueElements)
            m_index = 1;
        else
            m_index += 1;

        
        //Set current ticket index
        TicketNumber(winrt::to_hstring(m_index));
        
        
        //Ticket combinations
        int rnd = rand() % 5;

        hstring tmpTicket = _services[rnd].ServiceCode() + L", " +
                            _services[rnd].ServiceName() + L", " +
                            _desks[rnd].DeskNumber()     + L", " +
                            _desks[rnd].DeskCode()       + L", " +
                            _desks[rnd].DeskName()       + L", " +
                            _operators[rnd].BadgeCode()  + L", " +
                            _operators[rnd].FirstName()  + L", " +
                            _operators[rnd].LastName()   + L", " +
                            _operators[rnd].BirthDate().DateToString()  + L", ";


        
        m_creationDate = GetDate();


        //Service 
        m_serviceCode = _services[rnd].ServiceCode();
        m_serviceName = _services[rnd].ServiceName();

        //Desk
        m_deskNumber = _desks[rnd].DeskNumber();
        m_deskCode = _desks[rnd].DeskCode();
        m_deskName = _desks[rnd].DeskName();
        
        //Operator
        m_badgeCode = _operators[rnd].BadgeCode();
        m_firstName = _operators[rnd].FirstName();
        m_lastName =  _operators[rnd].LastName();
        m_birthDate = _operators[rnd].BirthDate();
        


        //Set current ticket code
        m_ticketString = tmpTicket;
      
               

    }


    TicketMachine::Date implementation::Ticket::GetDate()
    {

        std::time_t t = std::time(0);
        struct tm date;
        _localtime64_s(&date, &t);


        int year = date.tm_year + 1900;
        int month = date.tm_mon + 1;
        int day = date.tm_mday;

        int hour = date.tm_hour;
        int minutes = date.tm_min;
        int seconds = date.tm_sec;

        TicketMachine::Date dt;

        dt.Year(year);
        dt.Month(month);
        dt.Day(day);

        dt.Hh(hour);
        dt.Mm(minutes);
        dt.Ss(seconds);

        return dt;
        
    }


    hstring Ticket::TicketToString()
    {
        return m_ticketString;
    }

    hstring Ticket::TicketNumber()
    {
        return m_ticketNumber;
    }
    void Ticket::TicketNumber(hstring const& value)
    {
        m_ticketNumber = value;
    }
    hstring Ticket::TicketBarcode()
    {
        return m_ticketBarcode;
    }
    void Ticket::TicketBarcode(hstring const& value)
    {
        m_ticketBarcode = value;
    }
    int32_t Ticket::MaxQueueItems()
    {
        return m_maxQueueElements;
    }
    void Ticket::MaxQueueItems(int32_t value)
    {
        m_maxQueueElements = value;
    }
    TicketMachine::Date Ticket::CreationDate()
    {
        return m_creationDate;
    }
    void Ticket::CreationDate(TicketMachine::Date const& value)
    {
        m_creationDate = value;
    }
    Windows::Storage::StorageFile Ticket::TicketQRCode()
    {
        //throw hresult_not_implemented();
        return nullptr;
    }
    void Ticket::TicketQRCode(Windows::Storage::StorageFile const& /*value*/)
    {
        //throw hresult_not_implemented();
    }
    Windows::Storage::StorageFile Ticket::ImageFile()
    {
        //throw hresult_not_implemented();
        return nullptr;
    }
    void Ticket::ImageFile(Windows::Storage::StorageFile const& /*value*/)
    {
        //throw hresult_not_implemented();
    }
    
    
    
    //Common
    void Ticket::Add()
    {
        //throw hresult_not_implemented();
    }
    void Ticket::Edit()
    {
        //throw hresult_not_implemented();
    }
    void Ticket::Delete()
    {
        //throw hresult_not_implemented();
    }
    void Ticket::Save()
    {
        //throw hresult_not_implemented();
    }


    //Services
    hstring Ticket::ServiceCode()
    {
        return m_serviceCode;
    }
    void Ticket::ServiceCode(hstring const& value)
    {
        m_serviceCode = value;
    }
    hstring Ticket::ServiceName()
    {
        return m_serviceName;
    }
    void Ticket::ServiceName(hstring const& value)
    {
        m_serviceName = value;
    }


    //Desks
    hstring Ticket::DeskNumber()
    {
        return m_deskNumber;
    }
    void Ticket::DeskNumber(hstring const& value)
    {
        m_deskNumber = value;
    }
    hstring Ticket::DeskCode()
    {
        return m_deskCode;
    }
    void Ticket::DeskCode(hstring const& value)
    {
        m_deskCode = value;
    }
    hstring Ticket::DeskName()
    {
        return m_deskName;
    }
    void Ticket::DeskName(hstring const& value)
    {
        m_deskName = value;
    }


    //Operators
    hstring Ticket::FirstName()
    {
        return m_firstName;
    }
    void Ticket::FirstName(hstring const& value)
    {
        m_firstName = value;
    }
    hstring Ticket::LastName()
    {
        return m_lastName;
    }
    void Ticket::LastName(hstring const& value)
    {
        m_lastName = value;
    }
    TicketMachine::Date Ticket::BirthDate()
    {
        return m_birthDate;
    }
    void Ticket::BirthDate(TicketMachine::Date const& value)
    {
        m_birthDate = value;
    }
}



Il metodo Create nel file Ticket.cpp dovrà essere chiamato, dalle applicazioni che consumeranno il componente, ogni qualvolta si debba creare un nuovo ticket.
Questo, dopo essere stato creato, andrà in coda ad eventuali altri tickets in attesa, allo scopo implementeremo la classe OperationsQueue.
Ogni ticket, una volta completata l'operazione allo sportello andrà inserito in un'altra area (in una reale applicazione in un database etc.) che rappresenteremo qui con la classe OperationsLog.

Se analizziamo il metodo Create possiamo notare che viene istanziata diverse volte la classe Collection.
Lo scopo di questa classe template è di creare una lista di:

ed associarli tra loro (se vogliamo) in maniera pseudo randomica.
Pertanto ogni volta che eseguiremo il metodo Create avremo una diversa combinazione tra servizi, sportelli e operatori.
Questo meccanismo, a runtime, simulerà la funzione di un Totem per l'emissione dei tickets.

La classe template Collection si trova nel file di inclusione Helpers.h

Helpers.h

////====================================================================
//                          TicketMachine 
//                          C++/WinRT Component 
//
//                          Copyright (C) 2021
//                          G.Pischedda, all rights reserved
//                          software-on-demand-ita.com
////=====================================================================



#pragma once
#include "pch.h"
#include <vector>
#include <algorithm>
#include <deque>
#include <list>
#include <set>
#include <map>
#include <string>
#include <functional>
#include <numeric>
#include <random>
#include <chrono>
#include <ppltasks.h >


template <typename T>
inline void CreateIntegerRange(T& _vector, int min, int max)
{

	int index = min;
	do
	{

		_vector.insert(_vector.end(), index);
		++index;
	} while (index <= max);

}




template <typename T>
class RandomOrder
{

public:

	RandomOrder() = delete;

	virtual ~RandomOrder()
	{
		m_vector.clear();

	}


	RandomOrder(std::vector<T> D)
	{

		unsigned seed = (unsigned)std::chrono::system_clock::now().time_since_epoch().count();

		std::shuffle(D.begin(), D.end(), std::default_random_engine(seed));


		m_vector = D;

	}

	std::vector<T> get()
	{
		return m_vector;
	}
private:
	std::vector<T> m_vector;
	
};



template <typename I>
class Collection
{
public:
	Collection() = default;
	
	winrt::Windows::Foundation::Collections::IVectorView<I> GetView(winrt::Windows::Foundation::IAsyncOperation<winrt::Windows::Foundation::Collections::IVector<I>> items)
	{
		return Concurrency::create_task([items] {
			return  items.get().GetView();
			}).get();
	}

   std::vector<I> GetItems(I const& E,  bool shuffle)
	{
		
	   winrt::Windows::Foundation::IAsyncOperation<winrt::Windows::Foundation::Collections::IVector<I>> items = E.GetCollection(); 
	   winrt::Windows::Foundation::Collections::IVectorView<I> viewItems = GetView(items);

	   std::vector<I> _items;

		int i = 0;
		int elements = viewItems.Size();
		do
		{
			_items.push_back(viewItems.GetAt(i));
			++i;
		} while (i <= (elements - 1));

		
		if (shuffle)
		{
			RandomOrder<I> rdrItems(_items);
			return rdrItems.get();
		}

		else
			return _items;
	}
};


Events in a C++/WinRT Component
Come ben sappiamo, in generale, un evento in una classe è il modo per notificare all'applicazione che usa tale classe che "qualcosa" è appena accaduto (es: click su un bottone, fine del download di un file etc..).

In C++/WinRT un evento è dichiarato come tipo delegato e per poter essere gestito deve essere registrato; infine quando non più utilizzato può essere revocato.

A seconda dei casi un evento può essere dichiarato come tipo delegato tra i seguenti:

Useremo il tipo winrt::delegate quando l'evento non deve comunicare "con l'esterno"; useremo invece winrt::event quando l'evento deve essere accessibile attraverso ABI (application binary interface), e cioè quando sia il componente WinRT , che l'applicazione che lo consuma, accedono all'evento.

Altrettanto notorio è che un evento può avere degli argomenti.
Nel caso del tipo winrt::delegate non è strettamente necessario che l'argomento sia un tipo Windows Runtime, ma può essere di tipo Windows Runtime o di tipo custom.
Viceversa, per il tipo winrt::event, l'argomento può essere esclusivamente di tipo Windows Runtime o di tipo primitivo (int, float etc..).

Ora, dato che gli eventi del nostro componente TicketMachine devono "oltrepassare" ABI, dichiariamo nel file Common.idl nella classe OperationsQueue due eventi di tipo: winr::event, entrambi con argomento di tipo bool.
Il primo evento verrà invocato al momento dell'emissione di un nuovo ticket ed il secondo quando un'operazione è stata completata.

Common.idl

.............................
.............................
.............................

//Event Methods
void OperationItemAdded(Boolean isAdded);       
void OperationCompleted(Boolean isCompleted);

       
//Events
event Windows.Foundation.EventHandler<TicketMachine.StartQueueEventArgs> OnQueueItemAdded;
event Windows.Foundation.EventHandler<TicketMachine.CloseOperationEventArgs> OnOperationCompleted;


A seguire la dichiarazione e l'implementazione delle classi



OperationsQueue.h

////====================================================================
//                          TicketMachine 
//                          C++/WinRT Component 
//
//                          Copyright (C) 2021
//                          G.Pischedda, all rights reserved
//                          software-on-demand-ita.com
////=====================================================================



#pragma once
#include "OperationsQueue.g.h"

// Note: Remove this static_assert after copying these generated source files to your project.
// This assertion exists to avoid compiling these generated source files directly.
//static_assert(false, "Do not compile generated C++/WinRT source files directly");

namespace winrt::TicketMachine::implementation
{
    struct OperationsQueue : OperationsQueueT<OperationsQueue>
    {
        OperationsQueue() = default;

        Windows::Foundation::IAsyncOperation<Windows::Foundation::Collections::IVector<TicketMachine::OperationsQueue>> GetCollection();

        //Event Methods and handlers:

        //Event methods
        void OperationItemAdded(bool isAdded);
        void OperationCompleted(bool isCompleted);

        //Event handlers
        winrt::event_token OnQueueItemAdded(Windows::Foundation::EventHandler<TicketMachine::StartQueueEventArgs> const& handler);
        winrt::event_token OnOperationCompleted(Windows::Foundation::EventHandler<TicketMachine::CloseOperationEventArgs> const& handler);

        //Register/Revoke events
        void OnQueueItemAdded(winrt::event_token const& token) noexcept;
        void OnOperationCompleted(winrt::event_token const& token) noexcept;



        //Services
        hstring ServiceCode();
        void ServiceCode(hstring const& value);
        hstring ServiceName();
        void ServiceName(hstring const& value);

        //Desks
        hstring DeskNumber();
        void DeskNumber(hstring const& value);
        hstring DeskCode();
        void DeskCode(hstring const& value);
        hstring DeskName();
        void DeskName(hstring const& value);


        //Ticket
        hstring TicketNumber();
        void TicketNumber(hstring const& value);
        hstring TicketBarcode();
        void TicketBarcode(hstring const& value);
        int32_t MaxQueueItems();
        void MaxQueueItems(int32_t value);
        TicketMachine::Date CreationDate();
        void CreationDate(TicketMachine::Date const& value);
        Windows::Storage::StorageFile TicketQRCode();
        void TicketQRCode(Windows::Storage::StorageFile const& value);

        //Common
        void Add();
        void Edit();
        void Delete();
        void Save();


    private:
        hstring m_serviceCode{ L"" },
                m_serviceName{ L"" },
                m_deskCode{ L"" },
                m_deskName{ L"" },
                m_deskNumber{ L"" },
                m_ticketNumber{ L"" };

        int32_t m_maxQueueItems{ 0 };
        TicketMachine::Date m_CreationDate;


        winrt::event<Windows::Foundation::EventHandler<StartQueueEventArgs>> m_OnStartQueueEvent;
        bool m_startQueue = false;

        winrt::event<Windows::Foundation::EventHandler>CloseOperationEventArgs<< m_OnCompletedEvent;
        bool m_completed = false;


    };
}
namespace winrt::TicketMachine::factory_implementation
{
    struct OperationsQueue : OperationsQueueT<OperationsQueue, implementation::OperationsQueue>
    {
    };
}

OperationsQueue.cpp

////====================================================================
//                          TicketMachine 
//                          C++/WinRT Component 
//
//                          Copyright (C) 2021
//                          G.Pischedda, all rights reserved
//                          software-on-demand-ita.com
////=====================================================================



#include "pch.h"
#include "OperationsQueue.h"
#include "OperationsQueue.g.cpp"
#include "StartQueueEventArgs.h"
#include "CloseOperationEventArgs.h"
#include "Helpers.h"

// Note: Remove this static_assert after copying these generated source files to your project.
// This assertion exists to avoid compiling these generated source files directly.
//static_assert(false, "Do not compile generated C++/WinRT source files directly");

namespace winrt::TicketMachine::implementation
{
    Windows::Foundation::IAsyncOperation<Windows::Foundation::Collections::IVector<TicketMachine::OperationsQueue>> OperationsQueue::GetCollection()
    {
       
        return nullptr;
    }

    //Events
    void OperationsQueue::OperationItemAdded(bool isAdded)
    {
        m_startQueue = isAdded;
        auto args = winrt::make_self<winrt::TicketMachine::implementation::StartQueueEventArgs>(m_startQueue);
        m_OnStartQueueEvent(*this, *args);
    }

    void OperationsQueue::OperationCompleted(bool isCompleted)
    {
        m_completed = isCompleted;
        auto args = winrt::make_self<winrt::TicketMachine::implementation::CloseOperationEventArgs>(m_completed);
        m_OnCompletedEvent(*this, *args);
    }

    winrt::event_token OperationsQueue::OnQueueItemAdded(Windows::Foundation::EventHandler const& handler)
    {
        return  m_OnStartQueueEvent.add(handler);
    }
    void OperationsQueue::OnQueueItemAdded(winrt::event_token const& token) noexcept
    {
        m_OnStartQueueEvent.remove(token);
    }

    winrt::event_token OperationsQueue::OnOperationCompleted(Windows::Foundation::EventHandler const& handler)
    {
       return m_OnCompletedEvent.add(handler);
    }
    void OperationsQueue::OnOperationCompleted(winrt::event_token const& token) noexcept
    {
        m_OnCompletedEvent.remove(token);
    }



    //Service
    hstring OperationsQueue::ServiceCode()
    {
        return m_serviceCode;
    }
    void OperationsQueue::ServiceCode(hstring const& value)
    {
        m_serviceCode = value;
    }
    hstring OperationsQueue::ServiceName()
    {
        return m_serviceName;
    }
    void OperationsQueue::ServiceName(hstring const& value)
    {
        m_serviceName = value;
    }


    //Desk
    hstring OperationsQueue::DeskNumber()
    {
        return m_deskNumber;
    }
    void OperationsQueue::DeskNumber(hstring const& value)
    {
        m_deskNumber = value;
    }
    hstring OperationsQueue::DeskCode()
    {
        return m_deskCode;
    }
    void OperationsQueue::DeskCode(hstring const& value)
    {
        m_deskCode = value;
    }
    hstring OperationsQueue::DeskName()
    {
        return m_deskName;
    }
    void OperationsQueue::DeskName(hstring const& value)
    {
        m_deskName = value;
    }



    //Ticket
    hstring OperationsQueue::TicketNumber()
    {
        return m_ticketNumber;
    }
    void OperationsQueue::TicketNumber(hstring const& value)
    {
        m_ticketNumber = value;
    }
    hstring OperationsQueue::TicketBarcode()
    {
        return L"";
    }
    void OperationsQueue::TicketBarcode(hstring const& /*value*/)
    {

    }
    int32_t OperationsQueue::MaxQueueItems()
    {
        return m_maxQueueItems;
    }
    void OperationsQueue::MaxQueueItems(int32_t value)
    {
        m_maxQueueItems = value;
    }
    TicketMachine::Date OperationsQueue::CreationDate()
    {
        return m_CreationDate;
    }
    void OperationsQueue::CreationDate(TicketMachine::Date const& value)
    {
        m_CreationDate = value;
    }
    Windows::Storage::StorageFile OperationsQueue::TicketQRCode()
    {
        return nullptr;
    }
    void OperationsQueue::TicketQRCode(Windows::Storage::StorageFile const& /*value*/)
    {

    }


    //Common
    void OperationsQueue::Add()
    {
        //throw hresult_not_implemented();
    }
    void OperationsQueue::Edit()
    {
        //throw hresult_not_implemented();
    }
    void OperationsQueue::Delete()
    {
        //throw hresult_not_implemented();
    }
    void OperationsQueue::Save()
    {
        //throw hresult_not_implemented();
    }
}

OperationsLog.h

////====================================================================
//                          TicketMachine 
//                          C++/WinRT Component 
//
//                          Copyright (C) 2021
//                          G.Pischedda, all rights reserved
//                          software-on-demand-ita.com
////=====================================================================



#pragma once
#include "OperationsLog.g.h"

// Note: Remove this static_assert after copying these generated source files to your project.
// This assertion exists to avoid compiling these generated source files directly.
//static_assert(false, "Do not compile generated C++/WinRT source files directly");

namespace winrt::TicketMachine::implementation
{
    struct OperationsLog : OperationsLogT
    {
        OperationsLog() = default;

        Windows::Foundation::IAsyncOperation<Windows::Foundation::Collections::IVector<TicketMachine::OperationsLog>> GetCollection();


        //Service
        hstring ServiceCode();
        void ServiceCode(hstring const& value);
        hstring ServiceName();
        void ServiceName(hstring const& value);

        //Ticket
        hstring TicketNumber();
        void TicketNumber(hstring const& value);
        hstring TicketBarcode();
        void TicketBarcode(hstring const& value);
        int32_t MaxQueueItems();
        void MaxQueueItems(int32_t value);
        TicketMachine::Date CreationDate();
        void CreationDate(TicketMachine::Date const& value);
        Windows::Storage::StorageFile TicketQRCode();
        void TicketQRCode(Windows::Storage::StorageFile const& value);

        //Common
        void Add();
        void Edit();
        void Delete();
        void Save();


    private:
        hstring m_serviceCode{ L"" },
            m_serviceName{ L"" },
            m_deskCode{ L"" },
            m_deskName{ L"" },
            m_deskNumber{ L"" },
            m_ticketNumber{ L"" };

        int32_t m_maxQueueItems{ 0 };
        TicketMachine::Date m_CreationDate;
    };
}
namespace winrt::TicketMachine::factory_implementation
{
    struct OperationsLog : OperationsLogT<OperationsLog, implementation::OperationsLog>
    {
    };
}


OperationsLog.cpp

////====================================================================
//                          TicketMachine 
//                          C++/WinRT Component 
//
//                          Copyright (C) 2021
//                          G.Pischedda, all rights reserved
//                          software-on-demand-ita.com
////=====================================================================



#include "pch.h"
#include "OperationsLog.h"
#include "OperationsLog.g.cpp"
#include "Helpers.h"

// Note: Remove this static_assert after copying these generated source files to your project.
// This assertion exists to avoid compiling these generated source files directly.
//static_assert(false, "Do not compile generated C++/WinRT source files directly");

namespace winrt::TicketMachine::implementation
{
    Windows::Foundation::IAsyncOperation<Windows::Foundation::Collections::IVector<TicketMachine::OperationsLog>> OperationsLog::GetCollection()
    {
        return nullptr;
    }

    hstring OperationsLog::ServiceCode()
    {
        return m_serviceCode;
    }
    void OperationsLog::ServiceCode(hstring const& value)
    {
        m_serviceCode = value;
    }
    hstring OperationsLog::ServiceName()
    {
        return m_serviceName;
    }
    void OperationsLog::ServiceName(hstring const& value)
    {
        m_serviceName = value;
    }
    hstring OperationsLog::TicketNumber()
    {
        return m_ticketNumber;
    }
    void OperationsLog::TicketNumber(hstring const& value)
    {
        m_ticketNumber = value;
    }
    hstring OperationsLog::TicketBarcode()
    {
        return L"";
    }
    void OperationsLog::TicketBarcode(hstring const& /*value*/)
    {

    }
    int32_t OperationsLog::MaxQueueItems()
    {
        return m_maxQueueItems;
    }
    void OperationsLog::MaxQueueItems(int32_t value)
    {
        m_maxQueueItems = value;
    }
    TicketMachine::Date OperationsLog::CreationDate()
    {
        return m_CreationDate;
    }
    void OperationsLog::CreationDate(TicketMachine::Date const& value)
    {
        m_CreationDate = value;
    }
    Windows::Storage::StorageFile OperationsLog::TicketQRCode()
    {
        return nullptr;
    }
    void OperationsLog::TicketQRCode(Windows::Storage::StorageFile const& /*value*/)
    {

    }
    void OperationsLog::Add()
    {
       // throw hresult_not_implemented();
    }
    void OperationsLog::Edit()
    {
       // throw hresult_not_implemented();
    }
    void OperationsLog::Delete()
    {
        //throw hresult_not_implemented();
    }
    void OperationsLog::Save()
    {
        //throw hresult_not_implemented();
    }
}

StartQueueEventArgs.h

////====================================================================
//                          TicketMachine 
//                          C++/WinRT Component 
//
//                          Copyright (C) 2021
//                          G.Pischedda, all rights reserved
//                          software-on-demand-ita.com
////=====================================================================



#pragma once
#include "StartQueueEventArgs.g.h"

// Note: Remove this static_assert after copying these generated source files to your project.
// This assertion exists to avoid compiling these generated source files directly.
//static_assert(false, "Do not compile generated C++/WinRT source files directly");

namespace winrt::TicketMachine::implementation
{
    struct StartQueueEventArgs : StartQueueEventArgsT<StartQueueEventArgs>
    {
        StartQueueEventArgs() = default;

        bool ItemAdded();

        StartQueueEventArgs(bool isAdded);

       private:
           bool m_added = false;
    };
}

StartQueueEventArgs.cpp

////====================================================================
//                          TicketMachine 
//                          C++/WinRT Component 
//
//                          Copyright (C) 2021
//                          G.Pischedda, all rights reserved
//                          software-on-demand-ita.com
////=====================================================================



#include "pch.h"
#include "StartQueueEventArgs.h"
#include "StartQueueEventArgs.g.cpp"

// Note: Remove this static_assert after copying these generated source files to your project.
// This assertion exists to avoid compiling these generated source files directly.
//static_assert(false, "Do not compile generated C++/WinRT source files directly");

namespace winrt::TicketMachine::implementation
{
    bool StartQueueEventArgs::ItemAdded()
    {
        return m_added;
    }

    StartQueueEventArgs::StartQueueEventArgs(bool isAdded) :m_added(isAdded)
    {
        m_added = isAdded;
    }
}

CloseOperationEventArgs.h

////====================================================================
//                          TicketMachine 
//                          C++/WinRT Component 
//
//                          Copyright (C) 2021
//                          G.Pischedda, all rights reserved
//                          software-on-demand-ita.com
////=====================================================================



#pragma once
#include "CloseOperationEventArgs.g.h"

// Note: Remove this static_assert after copying these generated source files to your project.
// This assertion exists to avoid compiling these generated source files directly.
//static_assert(false, "Do not compile generated C++/WinRT source files directly");

namespace winrt::TicketMachine::implementation
{
    struct CloseOperationEventArgs : CloseOperationEventArgsT<CloseOperationEventArgs>
    {
        CloseOperationEventArgs() = default;

        bool OperationClosed();

        CloseOperationEventArgs(bool isClosed);

    private:
        bool m_closed = false;
    };
}

CloseOperationEventArgs.cpp

////====================================================================
//                          TicketMachine 
//                          C++/WinRT Component 
//
//                          Copyright (C) 2021
//                          G.Pischedda, all rights reserved
//                          software-on-demand-ita.com
////=====================================================================



#include "pch.h"
#include "CloseOperationEventArgs.h"
#include "CloseOperationEventArgs.g.cpp"

// Note: Remove this static_assert after copying these generated source files to your project.
// This assertion exists to avoid compiling these generated source files directly.
//static_assert(false, "Do not compile generated C++/WinRT source files directly");

namespace winrt::TicketMachine::implementation
{
    bool CloseOperationEventArgs::OperationClosed()
    {
        return m_closed;
    }

    implementation::CloseOperationEventArgs::CloseOperationEventArgs(bool isClosed)
    {
        m_closed = isClosed;
    }

}



Il componente è pronto, compiliamo il progetto e produciamo una versione aggiornata di TicketMachine.dll e TicketMachine.winmd.

Nella prossima, nonchè ultima parte di questo tutorial, vedremo come consumare il componente C++/WinRT in un'applicazione C++ Win32.





Giuseppe Pischedda 2021


Se il post ti è utile puoi fare una donazione all'autore, l'importo è a tua libera scelta.

Grazie