RAD Studio 10.2: Windows 10 VCL UWP/WinRT Support

Posted by on in Blogs

Windows 10 VCL Universal Windows Platform (UWP)/WinRT Services and Components has been added to the Run Time Library (RTL).

For example, the Windows 10 Notifications Component and Windows 10 Sharing/Contract Component, for both Object Pascal and C++ is included in RAD Studio, Delphi and/or C++ Builder

Introduction/Background on WinRT

To implement Windows 8 and Windows 10 features like Notifications and Sharing Contract, there is no Win32 API available for this, so you need access to the WinRT (Windows Runtime).

What is the Windows Runtime (WinRT)?

Starting with Windows 8, WinRT is the default application programming interface.

To be clear, WinRT does NOT replace the Win32 API that has been running underneath all Windows applications but rather augments it.  Microsoft decided to add new APIs instead of adding into the Win32 layer, they think that’s it better to use their new WinRT.  Microsoft has its reasons like its object-oriented, and it’s at the same level as Win32.

The C++ object-oriented API sits at the same level as Win32 API, not a shell that sits under Win32.

This is NOT like the .NET framework that is managed code.  WinRT is NATIVE code and is focused on performance!  For us RAD Studio developers this is perfect to integrate with WinRT!

All the parts of the WinRT API are designed to be asynchronous.  Meaning, according to Microsoft, if a function takes more than 50 milliseconds, this function needs to be asynchronous.

The API definitions are in metadata format, which is the same as the one used for .NET (ECMA 335).  And we use this to generate the new Winapi.* units for WinRT support, that we’ll see later in this post. 

WinRT is not new technology, it’ just the old COM based interface (old friends of ours!), so it was easy to integrate and support WinRT into RAD Studio!

Important to note is NOT all the WinRT classes can be used from Win32 Desktop applications.  WinRT has some classes that can only be used for Metro Applications or used to build WinRT applications, so we translated the classes that can be used from Win32 Desktop applications.

What does the WinRT and Universal Windows Platform Integration mean in RAD Studio?

Using the WinRT API definitions metadata, we created a new set of UNITS, called Winapi.* units (about 40 units) from the metadata.

We created some Helper Classes to let you easily manage the hard part of the creation of the objects (such as avoid getting class factories, etc.).

We created a new TWindowString record to manage HString type.  This is a record helper, to help manage a new HString type that was introduced by Microsoft.

RAD Studio provides WinRT API mappings and Object Pascal interfaces, and this provides support for Services such as Win 10 Notifications and Win 10 Contracts (source only).  

We provide components for both Notifications and Contracts that you can use in your application in both VCL and FMX C++ and Object Pascal.  The Notifications come through the Win10 Standard Action Center.  The Contracts are similar to Intents on Android or ShareSheet on iOS.  The Contracts allow you to find what types of applications can consume the content of your application.  For example, you can select TEXT content in your app, and click SHARE, and then you can open it up with a Reading List Application or a Notes Application.

The sample  \Object Pascal\VCL\Windows 10 Calendar includes WinRT support by System.Win.Winrt and Winapi.winrt.

Using WinRT Classes

Let's takes a quick overview look at some of the WinRT units, and how to use them.

Using RAD Studio 10.2 Tokyo, from Windows Explorer, you can see all the WinAPI units (that Embarcadero has translated) using the APIs metadata, installed at C:\Program Files (x86)\Embarcadero\Studio\19.0\source\rtl\win\winrt

We have Units like UI.Notifications, Globalization, and some interesting ones like Devices.Bluetooth.

WinRTClasses

WinAPI.Devices.Bluetooth contains the new BT and BTLE classes.  (NOTE:  We did discover that Windows implementation of this unit was very poor, and lacked some of the needed BT and BTLE characteristics like Advertisement, but the good news is WinRT fixed all of this!)

Let's say we are interested in working with BluetoothLE Advertisement Manufacture Data.

Open unit Winapi.Devices.Bluetooth.Advertisement in RAD Studio and Search | Find | advertisement, and you will see interfaces for BT LE Advertisement:

BTLEAdvertisement

Let’s look at one more WinRT unit.  Let’s look at Winapi.UI.Notifications that we used for the new Windows 10 Notifications

From Windows Explorer, Drag and Drop Winapi.UI.Notifications.pas into the IDE.

 

WinAPI_Notifications

Looking at the source code for Winapi.UI.Notifications, we see, looking for the TToastManager (line 280), we have the ToastNotificationManagerStatics :

ToastMaster

 We have static methods of a class that you can use, for example, if you create:

1. File | New | VCL Forms App – Delphi.

2. Add Winapi.UI.Notifications to the uses.

WinAPI_UI_Uses

3. Then you can code: TToastNotificationManager.   

And you see Statics: IToastNotificationManagerStatics

 ToastStatics  ToastStaticsButton.jpg

And TToastNotificationManager.Statics.  gives the static methods of the class (functions we can use!).

 

Create a Windows 10 VCL Universal Windows Platform (UWP) application.

Let’s look at one more of the classes, the Calendar class and create a Windows 10 VCL Universal Windows Platform (UWP) application.

For example, using C# and Visual Studio, to create a calendar and display the current year, the code looks like this:

Using Windows.Globalization;

Using Windows.UI.Popups;

Calendar Cal = new Calendar();

String Year = Cal.YearAsString();

MessageDialog ToShow = new MessageDialog(Year);

ToShow.ShowAsync();

In Delphi, we do:

1. New | VCL Forms Application. 

2. Add a Button.  

3. Add to uses:  Winapi.Globalization, System.Win.WinRT;

(Note:  We use the same Globalization classes, and the WinRT is for the Helper classes).

4. For the Button’s onClick Event, we declare the Calendar:

procedure TForm2.Button1Click(Sender: TObject);

var

Cal: ICalendar;

begin

//create the Calendar

Cal := TCalendar.Create;

//get the Calendar Year as a String method (YearAsString),

//returns the new Type HSTRING

//

// So we need to convert it to a Delphi String, using the

//TWindowsString class, with the HStringToString method

//

// And then we can display the Year in a ShowMessage

ShowMessage(TWindowsString.HStringToString(Cal.YearAsString));

end;

5. We want to build this for our Windows 10 machine, Win32:

- Project Options | Delphi Compiler | Linking | Include remote debug symbols | TRUE

RemoteDebugSymbolsWin32

6. Build and Run the app. 

7. Click the Button. 

8. The ShowMessage displays the current year 2017:

Year2017

 So, as you can see, the code in Delphi is similar to the code in Microsoft C# Visual Studio to create a new Calendar. 

This is because if you look at the Winapi.Globalization.pas code from C:\Program Files (x86)\Embarcadero\Studio\19.0\source\rtl\win\winrt, (Drag and Drop the file into the IDE), search for TCalendar (line 1042):

 function GetCalendarSystem: HSTRING; safecall;

We see we have an ICalendarFactory (Search | Find Class):

ICalendarFactory

  // DualAPI Interface
  // Windows.Globalization.ICalendar
  [WinRTClassNameAttribute(SCalendar)]
  ICalendar = interface(IInspectable)
  ['{CA30221D-86D9-40FB-A26B-D44EB7CF08EA}']
  // Windows.Globalization.ICalendarFactory
  ICalendarFactory = interface;
  PICalendarFactory = ^ICalendarFactory;

In the IDE, place your cursor on the ICalendarFactory, | Find Declarations | gives us the Interfaces:

  // DualAPI Interface
  // Windows.Globalization.ICalendarFactory
  [WinRTClassNameAttribute(SCalendar)]
  ICalendarFactory = interface(IInspectable)
  ['{83F58412-E56B-4C75-A66E-0F63D57758A6}']
    function CreateCalendarDefaultCalendarAndClock(languages: IIterable_1__HSTRING): ICalendar; safecall;
    function CreateCalendar(languages: IIterable_1__HSTRING; calendar: HSTRING; clock: HSTRING): ICalendar; safecall;
  end;

We see we have a function CreateCalendar that we can use to create a Calendar.  So we can do a CREATE on the Calendar.  In other cases, you need to use the Factory.

In our sample Calendar app above, we used Cal := TCalendar.Create;

This post gave a quick overview of the Windows 10 VCL Universal Windows Platform (UWP)/WinRT Services and Components added to the RAD Studio, Delphi and C++ Builder Run Time Library (RTL).

 



About
Gold User, Rank: 90, Points: 4
Al Mannarino has 25+ years of software development experience, including object-oriented analysis and design (OOAD) and developing and deploying production applications. He is currently a Principal Software Consultant and Evangelist for Embarcadero Technologies. Prior to joining Embarcadero, Al spent three years working with CodeGear, a division of Borland that was acquired by Embarcadero in 2008. He also worked for five years as a lead systems engineer for Borland supporting application lifecycle management, software delivery optimization and developer tools solutions. Prior to Borland, Al served as a systems engineer for companies including Objectivity, Versant, Red Brick Systems, Information Builders, and was an electrical engineer for Grumman Aerospace performing application implementations on complex electrical-mechanical systems. Al has a bachelor's of science degree in electrical engineering from Manhattan College.

Comments

  • Sandro Adad
    Sandro Adad Wednesday, 4 October 2017

    Do you know if integration to the cortana API will be avaiable in Delphi soon or is on the roadmap?

  • Please login first in order for you to submit comments
  • Page :
  • 1

Check out more tips and tricks in this development video: