Wednesday, December 14, 2011

Writing Hello World for WinRT in Delphi

There is relatively little information out there on developing Native Metro applications, especially for languages other than those that Microsoft has provided projections for (C++, C#, and JavaScript). Other languages, including Delphi, need to create their own projections before they can use them effectively. I've been investigating getting Delphi to produce native applications for WinRT. This is a rough low level look at the WinRT native APIs, and how to use them from a language that isn't C#, C++, or JavaScript. Eventually this investigation will lead to development of Delphi wrappers around the Windows 8 WinRT classes that will be much easier to use. Much of the discussion in this post is very similar to Ian Griffiths discussion on Real Native WinRT Development, but where he's using C++, I'm using Delphi. If you're interested in more technical detail about what's going on behind the scenes, I suggest you give that article a read.

I started with an empty console application, and removed the {$APPTYPE CONSOLE} directive. Essentially this just allows me to have a Windows application that doesn't use VCL. Eventually this application will need to be wrapped up as a AppX package, I'll discuss that more in depth later. It seems that WinRT XAML applications can be run outside of Metro, so for now I'm take advantage of that.

I'm going to jump around in the code a bit, sharing important as it comes up. Lets start with the uses clause:
program SampleWinrt;

uses
  System.Win.ComObj,
  Winapi.Winrt in 'Winapi.Winrt.pas',
  AllWinRt in 'Generated\AllWinRt.pas',
  WinRtHelpers in 'WinRtHelpers.pas';
There are three new units here:

  • Winapi.Winrt contains translations of the new global WinRT APIs. These are essentially the functions and datatypes defined in the Windows Runtime C++ reference: things such as RoInitialize and WindowsCreateString, etc.
  • AllWinRt contains all the enumerations, records, and interfaces defined in the Windows Metadata files. This file was generated by a tool that turns the metadata into delphi style interfaces. I'll go into the details of more of this process at a later time.
  • WinRtHelpers contains some helper classes that reduce the amount of code one needs to write in order to use the native APIs. This is the starting of a Delphi wrapper around the API to make the code more "Delphi". Currently, it contains a TInspectableObject-- which similar to TInterfacedObject but also implements the IInspectable interface -- and TWindowsString -- a helper class to convert strings to/from HSTRINGs.
Next up, we need to initialize our application. So lets look at the main program body:
begin
  OleCheck(RoInitialize(RO_INIT_MULTITHREADED));
  try
    Main;
  finally
    RoUninitialize;
  end;
end.
This code is just to initialize the Windows Runtime, and make sure it gets uninitialized on termination. RoInitialize is similar to COM's CoInitialize -- all threads that interact with WinRT objects must call RoInitialize prior to using it. The application can be initialized as single threaded or multithreaded. Ian Griffiths had difficulty getting the RO_INIT_SINGLETHREADED and likewise my app seems to have issues starting up as single threaded. I suspect this problem may just be a bug in the Metro API.

There are a couple of Application Runtime classes in the WinRT framework: Windows.ApplicationModel.Core.CoreApplication, and Windows.UI.Xaml.Application. The Xaml Application is easier to set up, so we'll start with that one. It is interesting to be able to create Xaml applications in Delphi, because immediately we can take advantage of all the Xaml controls provided by Microsoft as well as consume third party controls (regardless of implementation language) and even provide libraries of additional Xaml components that could be consumed by Delphi or other language projections.

procedure Main;
var
  Factory: IApplicationFactory;
  App: IApplication;
  insp, outer, inner: IInspectable;
begin
  outer := TDerivedApp.Create;
  OleCheck(RoGetActivationFactory(TWindowsString('Windows.UI.Xaml.Application'), IApplicationFactory, insp));
  Factory := insp as IApplicationFactory;
  app := Factory.CreateInstance(outer as IApplicationOverrides, inner);
  TDerivedApp(outer).inner := inner as IApplicationOverrides;
  app.Run;
  app := nil; // App needs to be _Released first, otherwise it AVs
end;
Here we create a TDerivedApp (which I'll expand on below), request a Xaml ApplicationFactory, and construct a IApplication specifying the TDerivedApp is the outer implementation of IApplicationOverrides. The ApplicationFactory provides an Inner implementation, which we store off so that we can make inherited calls. Finally we Run the app. This is sort of a bizarre inheritance model provided by WinRT that I'll gloss over here. Ian Griffiths has an in depth article about how to create inherited WinRT classes, give that a read for some of the more technical details of how it's implemented in C++.

Everything here is being stored in Interfaces, so it's reference counted. Even our classes, such as TDerivedApp are reference counted. TDerivedApp derives from TInspectableObject, which derives from TInterfacedObject from System. The Delphi compiler automatically generates calls to _Release, making this code look a lot cleaner than the raw C++ version. Note however that App is being initialized to nil manually before exiting. If Inner is released first, WinRT crashes. I haven't investigated closely, but my suspicion is that Inner may actually be a weak reference to the same object as App, and releasing both is unnecessary/incorrect.

So what is our TDerived app? It's an object that implements Windows.UI.Xaml.IApplicationOverrides so we can actually define the behavior of our application.

type
  TDerivedApp = class(TInspectableObject, IApplicationOverrides)
  private
    FInner: IApplicationOverrides;
  public
    // IApplicationOverrides interface
    procedure OnInitialize; safecall;
    procedure OnActivated(args: IActivatedEventArgs); safecall;
    procedure OnLaunched(args: ILaunchActivatedEventArgs); safecall;
    procedure OnFileActivated(args: IFileActivatedEventArgs); safecall;
    procedure OnSearchActivated(args: ISearchActivatedEventArgs); safecall;
    procedure OnSharingTargetActivated(args: IShareTargetActivatedEventArgs); safecall;
    procedure OnFilePickerActivated(args: IFilePickerActivatedEventArgs); safecall;

    property inner: IApplicationOverrides read FInner write FInner;
  end;
Note, like in C++, we have to implement all the entries in the interface, even if we don't want to handle those events. Implementation of those methods will just be a pass through to the Inner IApplicationOverrides provided by the Activation Factory. For example:
procedure TDerivedApp.OnActivated(args: IActivatedEventArgs);
begin
  FInner.OnActivated(args);
end;
Eventually there should be class wrappers that handle all the inheritance for you if you don't want to override methods. When the Application Runs, we get an OnLaunched event. That's the one event we wanted to hook up, so let's do that:
procedure TDerivedApp.OnLaunched(args: ILaunchActivatedEventArgs);
const
  content = '<TextBlock xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" ' +
            '  Name="Text" TextAlignment="Center" HorizontalAlignment="Center" ' +
            '  VerticalAlignment="Center" FontSize="56">' +
            '  <Run Text="Hello World"/>' +
            '  <LineBreak/>' +
            '  <Run Text="Delphi"/>' +
            '  <LineBreak/>' +
            '  <Run Text="Metro Native App (Xaml)"/>' +
            '</TextBlock>';
var
  WinStatic: IWindowStatics;
  ReaderStatic: IXamlReaderStatics;
begin
  // Get the IWindowStatics
  RoGetActivationFactory(TWindowsString(SWindow), IWindowStatics, WinStatic);
  // Get an IXamlReaderStatics
  RoGetActivationFactory(TWindowsString(SXamlReader), IXamlReaderStatics, ReaderStatic);
  // Populate Xaml
  WinStatic.Current.Content := ReaderStatic.Load(TWindowsString(content)) as IUIElement;
  // Activate the current view
  WinStatic.Current.Activate;
  FInner.OnLaunched(args); // inherited call;
end;
Here we just load some constant XML data into the current frame using an XamlReader. It would be easy to design your Xaml in a separate file using Rad Studio or your favorite XML editor and storing on disk it along side your Application, but for simplicity's sake I've just included it inline.

And that's what it takes to present some text in Metro Xaml controls. Obviously I've omitted some code here; I'll see if I can minimize the AllWinRT and Winapi.Winrt units to only the APIs used in this example to provide a full code sample.

57 comments:

  1. Are the WinRT (win8 rt units) you use in the sample available in the current package or somewhere on the web?

    ReplyDelete
  2. No, they are not available. Because Windows 8 is still in Developer Preview and the APIs could possibly change, and because this represents only preliminary research on how the Delphi API will look, I hesitate to make my translations available.

    I would however like to provide enough of it to let people take a look at this example and run it for themselves; I hope to get that out soon.

    ReplyDelete
  3. Thank you, Thom.

    It's a very interesting article. The million question: FireMonkey or XAML? Or where FireMonkey, and where XAML?

    Best regards. :)

    Al Gonzalez.

    ReplyDelete
  4. Thom, have you been able to update https://github.com/tgerdes/DelphiWinRT to make it compatible with the consumer preview version ? keep up the great work! :-)

    ReplyDelete
  5. It truly is imperative in order to try to remember that you should stay positive within your tone or approach while
    paper writing service your dissertation card-stock. Write in an appropriate tone so that the followers appreciate examining the dissertation proposal.

    ReplyDelete
  6. Thanks for everything guys
    Cheers
    Elias

    ReplyDelete
  7. A person who has had experience of Visual Chief will remark the similaries of the Delphi and Visual Chief IDEs. Equally use 'Forms' that are the basis of the building blocks of Windows programs, excluding of course the underlying languages are different. sbobet,

    ReplyDelete
  8. I need this article to complete my assignment in the college, and it has same topic with your article. Thanks, great share.
    werkblad keramiek

    ReplyDelete
  9. Thank you for posting this.You most absolutely have built this blog website into something special.
    dekton keukenwerkblad

    ReplyDelete
  10. I really be grateful for your blog, you have completed the great job. Thanks for the bunch of excellent resourceful site.
    terrazzo keukenblad

    ReplyDelete
  11. Thank you for your sharing! I really like to read it,So good to find somebody with some original thoughts on this subject .
    bra tape

    ReplyDelete
  12. Another great post, I appreciate all the work you put into this site, helping out others with your fun and creative works.
    badgarnituur

    ReplyDelete
  13. Thanks on your marvelous posting! I really enjoyed reading it, you’re a great author.Please visit here:
    Packers And Movers Hyderabad

    ReplyDelete
  14. I loved this one. It has given me courage to try scarier things. I tend to steer clear of them but not anymore.Packers And Movers Jaipur

    ReplyDelete
  15. Thanks on your marvelous posting! I really enjoyed reading it, you’re a great author.Please visit here:
    Packers And Movers Chennai

    ReplyDelete
  16. Generally I don't read anything but thanks for writing when i read this i felt how graceful as a writer you are.thank you for posting-Packers and Movers Kolkata

    ReplyDelete
  17. Thanks have been given the opportunity to comment. Hopefully what you provided is useful for all those who need them. Visit my website if you want to know more about:Situs Judi poker

    ReplyDelete
  18. I like the post format as you create user engagement in the complete article. It seems round up of all published posts. Thanks for gauging the informative posts.
    cara menggugurkan kandungan
    cara menggugurkan kandungan

    ReplyDelete
  19. QuickBooks Tech Support Phone Number is one the best accounting assistance available which can be accessed through QuickBooks Helpline Number. We are able to resolve all your QuickBooks related issues through our Intuit certified QuickBooks Pro-Advisors.

    ReplyDelete
  20. QuickBooks Payroll Support Phone Number. For any kind of queries or any other related issue, we encourage you to call us at QuickBooks Payroll Support Phone Number +1-888-396-0208.

    ReplyDelete
  21. Best technical support by Intuit professionals for QuickBooks installation, updates, setup, migration, data recovery, company file repair and data services.
    QuickBooks Payroll Service Number CAll 1888-567-1159 VISIT https://www.qbpayrollsupport.com/

    ReplyDelete
  22. That was a great read. I really like your writing style and how you explain certain things. I will be back to read more from you.We also provide Technical Support for QuickBooks Payroll , if you face any problem with your QuickBooks Payroll you can just click here QuickBooks Basic Payroll Support. Or dial 1888-567-1159.

    ReplyDelete
  23. Are you stuck with any technical issues with the device, software, operating system or browsers that you are presently using? If yes, we understand that how frustrating this situation could turn to be, especially if you are trying to do some important work and couldn’t complete it due to the technical bugs. Dial QuickBooks Support Phone Number 1888-396-0208 , If you are facing Errors in your Quickbooks.

    ReplyDelete
  24. QuickBooks 2018 Desktop version for Windows has been launched and it is full of exciting and innovative features and tools. Furthermore, enhancement to older version of the software is also made within the new release of QuickBooks Point Of Sale Support Phone Number 2018 upgrade.

    ReplyDelete
  25. Move up to QuickBooks Tech 2018 now and experience the most recent highlights including multi-screen support, batch receipt preparing, enhanced inquiry choice, mobile receipt process and that's only the tip of the iceberg. Call Quickbook Tech Support Phone Number +1888-396-0208 whenever for QB Tech 2018 Setup, Installation and Updates. Pick your phone and dial our toll free number anytime, We are here to help you 24/7.

    ReplyDelete
  26. The QuickBooks Support Phone Number 1888-396-0208 has numerous guaranteed professionals who are constantly prepared to give a moment arrangement regardless of the kind of issue you are confronting. The Quickbooks undertaking support has exceptionally prepared experts, who can deal with a wide range of issues one next to the other, in the meantime.

    ReplyDelete
  27. Online Business Analytics, This is an add-on tool which opens up numerous more options for QuickBooks Enterprise clients. This device helps in opening information in QuickBooks Enterprise software in such a way you don't have to enter subtle elements like numbers and so forth to run reports of any sort. It is advised to take the help from QuickBooks Enterprise Support phone Number 1800-291-2485 and get your Tool Install.

    ReplyDelete
  28. Pretty blog, so many ideas in a single site, thanks for the informative article, keep updating more article.
    Webdesining course in chennai

    ReplyDelete
  29. The Number itself says that it's the fundamental and right Tech advantage for your business. In case you need any help call our QuickBooks Customer service Phone Number -- to get minute support from our authorities.

    ReplyDelete
  30. After some time QuickBooks has turned into a necessary piece of numerous little and medium-sized entrepreneurs to run and deal with their records. The software accompanies different accommodating highlights for their clients and one of them is the adjust director, however now and again there can be circumstances where a client of this bookkeeping software may need to uninstall Intuit QuickBooks Sync Manager. This article gives the means on the most proficient method to do that.so call our QuickBooks Sync Manager

    ReplyDelete
  31. Shopify as a web based business stage was known all finished for its simple customization and easy to use stage which has even constrained numerous other surely understand POS framework to interface through this stage. Be that as it may, as Shopify began to extend past only an internet business stage it began to give overwhelming rivalry to these know POS framework too. This unification of online store and POS framework under one standard was very helpful for constrained spending organizations managing in new businesses or little size organizations.Connect with us by dialing our toll free.Shopify Point of Sale customer support

    ReplyDelete
  32. The Magtek Mini USB Credit card reader for QuickBooks POS is compatible with the PC series of personal computers or any device with a USB interface. A card is read by sliding it, stripe down and facing the LED side, through the slot either forward or backward. A LED (Light Emitting Diode) indicator on the Reader panel provides the operator with continuous status of the Reader operations. The reader emulates a USB Human Interface Device (HID) keyboard. This allows host applications designed to acquire card data from keyboard input to seamlessly acquire the card data from the USB swipe reader.

    ReplyDelete