Skip to content
Bruno Sonnino
Menu
  • Home
  • About
Menu

Monetizing your Delphi app with TWindowsStore

Posted on 26 February 2019

In a previous post, I've shown how to publish your Delphi app to the Windows Store. If it is a paid app, you can start getting money with it as soon as it starts to sell. But sometimes, you don't want to make it a paid app, but you still want to earn money with it.

One way to do it is to do the same that many games do: to use In-app purchases. You can offer a free basic version and put some paid add-ins in the app, so the user must pay to get the premium features. Even if it's a paid app, you can also give the user a trial period, so, the user can use the premium version for some time and then, if he doesn't want to pay for the app, he can still use the basic features.

Delphi 10.3 introduced a new component, TWindowsStore, that allows you to control the store features (add-ins, trial version) and enable or disable features depending on what the user pays. In this article, I will show how to use the TWindowsStore component to control the features and set the In-app purchases.

We will use the same Financial Calculator we've used in the previous article, but we'll do some changes:

  • The basic calculator will be able to calculate only the Present Value of the investment. The other calculators won't be available.
  • The user will have a trial period where all the calculators are available. Once the trial period is expired, the app will revert to the basic version
  • The user will be able to buy calculators as add-in purchases. He won't need to buy all, he will be able to buy just the ones he needs as add-in purchases.

Developing the trial and in-app purchases

The first step in the development of the trial version is to add a TWindowsStore component in the main window of the calculator. Then, we will change the app to show the basic features for the app. To do this, change the PageIndex of the calculators:

  • Present Value - 0
  • Future Value - 1
  • Payments - 2
  • Return Rate - 3

Put a panel with a button over each calculator, except the first one, with this text: "To open this calculator, click on the button". Change the ParentBackground property to false. Add another TabSheet, with a label with a caption with text "Trial version - % days remaining". If you run the app, you should have something like this:

Now, let's program the trial version. When the user is in trial period, he will be able to use all calculators. To do that, we'll do something like this:

procedure TForm1.CheckIfTrial;
begin
  if WindowsStore1.AppLicense.IsActive then begin
    if WindowsStore1.AppLicense.IsTrial then begin
      var RemainingDays := WindowsStore1.AppLicense.TrialTimeRemaining.Days;
      Label21.Caption := Format(Label21.Caption, [RemainingDays]);
      EnableFullVersion;
    end
  end
  else begin
    CheckBoughtCalculators;
  end;
end;
Pascal

The CheckIfTrial procedure will be called in the OnCreate handler of the form, thus setting the UI accordingly at start. The EnableFullVersion procedure will hide all trial panels:

procedure TForm1.EnableFullVersion;
begin
  Panel1.Visible := False;
  Panel2.Visible := False;
  Panel3.Visible := False;
end;
Pascal

The CheckBoughtCalculators will only hide the panels for the add-ons that had been bought:

procedure TForm1.CheckBoughtCalculators;
begin
  Panel1.Visible := not WindowsStore1.UserHasBought('FutureCalc');
  Panel2.Visible := not WindowsStore1.UserHasBought('PaymentCalc');
  Panel3.Visible := not WindowsStore1.UserHasBought('RateCalc');
end;
Pascal

The code to buy the add-ons is:

function TForm1.PurchaseItem(Item: string) : string;
begin
  LogMessage('Will purchase item: ' +Item);
  for var i := 0 to WindowsStore1.AppProducts.Count - 1 do
    if TWindowsString.HStringToString(WindowsStore1.AppProducts[i].InAppOfferToken) = Item then begin
      BuyProduct(WindowsStore1.AppProducts[i]);
      exit;
    end;
  LogMessage('Item not found: ' +Item);
end;

procedure TForm1.BuyProduct(Product: IStoreProduct);
begin
  try
    var status := WindowsStore1.PurchaseProduct(Product);
    LogMessage('Got status: '+Integer(status).ToString);
    if status = StorePurchaseStatus.Succeeded then begin
      LogMessage('Item ' +TWindowsString.HStringToString(Product.Title)+' bought');
      CheckBoughtCalculators();
    end
    else begin
      ShowMessage('Item could not be purchased. Error: '+Integer(status).ToString);
    end;
  except
    On e : Exception do
      LogMessage('Exception while buying item.'+Chr(13)+
        E.ClassName+', with message : '+E.Message);
  end;
end;
Pascal

The code for the buttons is:

procedure TForm1.Button1Click(Sender: TObject);
begin
  PurchaseItem('FutureCalc');
end;
Pascal

While developing the app, I found that this code generates an exception, there is something in the code that doesn't like the Delphi Window handle and crashes the app when the code is run. Not a good experience for a paid app. So, I searched the web for an alternative and found this article that shows how to create a dll in C# that can be used in Delphi, to allow buying add-in purchases in the Windows Store. If you follow the instructions there and compile the dll, you will have the IAPWrapper.dll that can be used in our Delphi program.

This dll exposes a function, Purchase, that makes the purchase of an add-in. It's different than the TWindowsStore's PurchaseProduct, because it receives the item id as a parameter and not the item itself. That way, we must add the dll to the project, declare the Purchase function and change the BuyProduct method:

function Purchase(StoreId : PAnsiChar) : PAnsiChar; stdcall; external 'IAPWrapper.dll';

procedure TForm1.BuyProduct(Product: IStoreProduct);
begin
  try
    var status := Purchase(PAnsiChar(AnsiString(TWindowsString.HStringToString(Product.StoreId))));
    LogMessage('Got status: '+status);
    if status = 'Succeeded' then begin
      LogMessage('Item ' +TWindowsString.HStringToString(Product.Title)+' bought');
      CheckBoughtCalculators();
    end
    else begin
      ShowMessage('Item could not be purchased. Error: '+Integer(status).ToString);
    end;
  except
    On e : Exception do
      LogMessage('Exception while buying item.'+Chr(13)+
        E.ClassName+', with message : '+E.Message);
  end;
end;

Pascal

With this code, you can put your app in the store and monetize with it. When the user wants a calculator, he can buy the item and it will be available forever. You could also make it consumable, so it can be bought again at anytime, but for our purposes, that's fine.

Creating the add-ins in the store

Once you have the program developed, you must create your add-ins in the store. Go to the Windows Development Center, select the app you have developed for the store and click on the "Create a new add-on" button.

There you can create many types of add-ons:

  • Developer-managed consumable - this kind of add-on is managed by your app, like some kind of strength. If this consumable is used on your app, the user can buy it again.
  • Store-managed consumable - this kind of add-on is managed by the store, like some kind of gun. You can query the store to know how many guns the user has bought
  • Durable - this kind of add-on is bought once and it is available until its lifetime
  • Subscription - this kind of add-on needs periodic payment to keep using it

Our add-ons will all be durable, once the user buys a calculator, he won't need to buy it again. Create a new durable add-on and name it FutureCalc. Then start the submission for it:

Set the properties for the add-on, with a product lifetime Forever and Content type as Software as service:

Then, set the price and availability of the add-on:

We won't change anything here - we will leave the add-in for free, so you just need to click the Save button.

The next step is to add the store listings. Add a new language and select English (United States) and edit it:

Set the title and description and click on the Save button. When you have everything set, just click on the Submit to the store to submit it. Do the same thing with the PaymentCalc and RateCalc add-ons.

The next step is to create a new flight for the package. Just change the version to 1.1 and compile the app for the store (don't forget to change the Provisioning data to Store). Then, create a new flight for the submission and send the package there. It will be available to download as soon as it passes certification. It will show that it has in-app purchases:

Once you've installed it, it will show you the new version, and you can unlock the calculator you want:

Conclusions

As you can see you can send your Delphi apps to the Windows store and get some money with them The TWindowsStore component allows you to interact with the add-ins you've set in the store, so you can earn money by creating a paid version or even by adding purchases in the app. While developing the app, I've shown that you can also create a dll in C# that interacts with your Delphi program in the same way that a Win32 dll does. You can use this dll in the store to buy add-ins and monetize your app.

The full source code for this article is in https://github.com/bsonnino/FinCalcAddIn

7 thoughts on “Monetizing your Delphi app with TWindowsStore”

  1. fajrin says:
    19 March 2019 at 03:56

    Hi Sir,
    I tried with delphi 10.3.1 Rio, error shows up when adding TWindowsStore component to form, the error is ‘delphi can not get factory class Windows.Services.store.storecontext’.
    What to do ?. Kindly help.

    Regards
    Fajrin

    Reply
    1. bsonnino says:
      22 March 2019 at 19:17

      Which version of Windows are you running? This component only works with the October 2018 Windows 10 version

      Reply
      1. Felipe Bustamante says:
        28 July 2019 at 11:32

        The sample application is compilable but not executable, at the time of starting the application an initiation error message is displayed and the application must be terminated. No information is shown as to why or in which unit the error is located.

        I think there is an incompatibility of initiation (a circular reference, perhaps) between the windowsstore reference units and the TWindowsStore component reference unit.

        Reply
        1. bsonnino says:
          13 August 2019 at 15:10

          I will check it, it was running fine, maybe some change in the Delphi version. Let me check it and I’ll return to you

          Reply
          1. Felipe Bustamante says:
            13 August 2019 at 16:17

            Sorry, I found the problem. The problem of execution was in the use of the library that was not attached to the project.

            According to what I could read on Microsoft sites, some problems still prevail to obtain the correct information, such as the remaining time of the Trial period, the return value is incorrect even in applications made in C #!

  2. Felipe Bustamante says:
    28 July 2019 at 06:54

    Hi Bruno,
    The sample application is compilable but it is not executable!

    There is an incompatibility between the units referred to WindowsStore. The following units are declared in Uses:
       Vcl.WindowsStore, required for the component
       System.Win.WinRt, unit needed for HStringToString
       WinApi.WinRt,
       WinApi.Foundation,
       WinApi.WindowsStore,
       WinApi.CommonTypes,
       Winapi.Storage,
       WinApi.ServicesRt.Store,
       WinApi.WinRt.Utils,

    I have tried all the combinations that have occurred to me and I have not been able to make the application run, regardless of the combination between referenced units, the application compiles but does not run. Immediately upon executing the application, the message that the application could not be started correctly and must be closed is displayed. The problem is that it does not indicate why the error is due or in which unit it is hosted.

    Any ideas????

    Reply
    1. Felipe Bustamante says:
      13 August 2019 at 16:18

      Sorry, I found the problem. The problem of execution was in the use of the library that was not attached to the project.

      According to what I could read on Microsoft sites, some problems still prevail to obtain the correct information, such as the remaining time of the Trial period, the return value is incorrect even in applications made in C #!

      Reply

Leave a Reply Cancel reply

Your email address will not be published. Required fields are marked *

  • May 2025
  • December 2024
  • October 2024
  • August 2024
  • July 2024
  • June 2024
  • November 2023
  • October 2023
  • August 2023
  • July 2023
  • June 2023
  • May 2023
  • November 2022
  • October 2022
  • September 2022
  • August 2022
  • June 2022
  • April 2022
  • March 2022
  • February 2022
  • January 2022
  • July 2021
  • June 2021
  • May 2021
  • April 2021
  • March 2021
  • February 2021
  • January 2021
  • December 2020
  • October 2020
  • September 2020
  • April 2020
  • March 2020
  • January 2020
  • November 2019
  • September 2019
  • August 2019
  • July 2019
  • June 2019
  • April 2019
  • March 2019
  • February 2019
  • January 2019
  • December 2018
  • November 2018
  • October 2018
  • September 2018
  • August 2018
  • July 2018
  • June 2018
  • May 2018
  • November 2017
  • October 2017
  • September 2017
  • August 2017
  • June 2017
  • May 2017
  • March 2017
  • February 2017
  • January 2017
  • December 2016
  • November 2016
  • October 2016
  • September 2016
  • August 2016
  • July 2016
  • June 2016
  • May 2016
  • April 2016
  • March 2016
  • February 2016
  • October 2015
  • August 2013
  • May 2013
  • February 2012
  • January 2012
  • April 2011
  • March 2011
  • December 2010
  • November 2009
  • June 2009
  • April 2009
  • March 2009
  • February 2009
  • January 2009
  • December 2008
  • November 2008
  • October 2008
  • July 2008
  • March 2008
  • February 2008
  • January 2008
  • December 2007
  • November 2007
  • October 2007
  • September 2007
  • August 2007
  • July 2007
  • Development
  • English
  • Português
  • Uncategorized
  • Windows

.NET AI Algorithms asp.NET Backup C# Debugging Delphi Dependency Injection Desktop Bridge Desktop icons Entity Framework JSON Linq Mef Minimal API MVVM NTFS Open Source OpenXML OzCode PowerShell Sensors Silverlight Source Code Generators sql server Surface Dial Testing Tools TypeScript UI Unit Testing UWP Visual Studio VS Code WCF WebView2 WinAppSDK Windows Windows 10 Windows Forms Windows Phone WPF XAML Zip

  • Entries RSS
  • Comments RSS
©2025 Bruno Sonnino | Design: Newspaperly WordPress Theme
Menu
  • Home
  • About