Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. Mobile and Embedded
  4. How can I use WINRT c++ APIs in at Qt WINRT app?
Forum Updated to NodeBB v4.3 + New Features

How can I use WINRT c++ APIs in at Qt WINRT app?

Scheduled Pinned Locked Moved Unsolved Mobile and Embedded
13 Posts 4 Posters 6.1k Views 2 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • R Offline
    R Offline
    Rad B
    wrote on 25 Jun 2016, 05:34 last edited by
    #1

    How can I use WINRT c++ APIs in at Qt WINRT app?

    1 Reply Last reply
    0
    • C Offline
      C Offline
      Chris Kawa
      Lifetime Qt Champion
      wrote on 25 Jun 2016, 08:44 last edited by Chris Kawa
      #2

      Well, depending on the approach it's either smooth ride or a horror show. Here's a "world of pain" type example that gets current date using WRL and puts it on a Qt's label:

      #include <QApplication>
      #include <QLabel>
      
      #include <wrl/client.h>
      #include <wrl/wrappers/corewrappers.h>
      #include <windows.globalization.h>
      #include <windows.globalization.datetimeformatting.h>
      
      namespace WRL     = Microsoft::WRL;
      namespace Wrap    = Microsoft::WRL::Wrappers;
      namespace Fnd     = Windows::Foundation;
      namespace ABIFnd  = ABI::Windows::Foundation;
      namespace ABIGlob = ABI::Windows::Globalization;
      
      auto format = L"{year.full}-{month.integer(2)}-{day.integer(2)}";
      
      int main(int argc, char *argv[])
      {
          QApplication a(argc, argv);
      
          QLabel lbl;
          lbl.setAlignment(Qt::AlignCenter);
          lbl.show();
      
          //Qt initializes COM for us so we don't need to call RoInitialize
      
          WRL::ComPtr<ABIGlob::ICalendar> calendar;
          Wrap::HStringReference calendarClassId(RuntimeClass_Windows_Globalization_Calendar);
          if (SUCCEEDED(Fnd::ActivateInstance(calendarClassId.Get(), calendar.GetAddressOf())))
          {
             ABIFnd::DateTime dateTime;
             if (SUCCEEDED(calendar->GetDateTime(&dateTime)))
             {
                 WRL::ComPtr<ABIGlob::DateTimeFormatting::IDateTimeFormatterFactory> dateTimeFormatterFactory;
                 Wrap::HStringReference dateTimeFormatterId(RuntimeClass_Windows_Globalization_DateTimeFormatting_DateTimeFormatter);
                 if (SUCCEEDED(Fnd::GetActivationFactory(dateTimeFormatterId.Get(), dateTimeFormatterFactory.GetAddressOf())))
                 {
                     WRL::ComPtr<ABIGlob::DateTimeFormatting::IDateTimeFormatter> dateTimeFormatter;
                     Wrap::HStringReference dateTimeFormat(format);
                     if (SUCCEEDED(dateTimeFormatterFactory->CreateDateTimeFormatter(dateTimeFormat.Get(), dateTimeFormatter.GetAddressOf())))
                     {
                         Wrap::HString formattedDateTime;
                         if (SUCCEEDED(dateTimeFormatter->Format(dateTime, formattedDateTime.GetAddressOf())))
                         {
                             uint buff_len;
                             auto buff = formattedDateTime.GetRawBuffer(&buff_len);
      
                             lbl.setText(QString::fromWCharArray(buff, buff_len));
                         }
                     }
                 }
             }
          }
      
          return a.exec();
      }
      

      And yes, before you manage to say "H O L Y    F U U U ..."  this is exactly the same as:

      #include <QApplication>
      #include <QLabel>
      #include <QDate>
      
      int main(int argc, char *argv[])
      {
          QApplication a(argc, argv);
      
          QLabel lbl(QDate::currentDate().toString("yyyy-MM-dd"));
          lbl.setAlignment(Qt::AlignCenter);
          lbl.show();
      
          return a.exec();
      }
      

      To spare yourself from going absolutely insane you might want to look into wrapper libraries like Modern.

      R 1 Reply Last reply 25 Jun 2016, 19:39
      0
      • C Chris Kawa
        25 Jun 2016, 08:44

        Well, depending on the approach it's either smooth ride or a horror show. Here's a "world of pain" type example that gets current date using WRL and puts it on a Qt's label:

        #include <QApplication>
        #include <QLabel>
        
        #include <wrl/client.h>
        #include <wrl/wrappers/corewrappers.h>
        #include <windows.globalization.h>
        #include <windows.globalization.datetimeformatting.h>
        
        namespace WRL     = Microsoft::WRL;
        namespace Wrap    = Microsoft::WRL::Wrappers;
        namespace Fnd     = Windows::Foundation;
        namespace ABIFnd  = ABI::Windows::Foundation;
        namespace ABIGlob = ABI::Windows::Globalization;
        
        auto format = L"{year.full}-{month.integer(2)}-{day.integer(2)}";
        
        int main(int argc, char *argv[])
        {
            QApplication a(argc, argv);
        
            QLabel lbl;
            lbl.setAlignment(Qt::AlignCenter);
            lbl.show();
        
            //Qt initializes COM for us so we don't need to call RoInitialize
        
            WRL::ComPtr<ABIGlob::ICalendar> calendar;
            Wrap::HStringReference calendarClassId(RuntimeClass_Windows_Globalization_Calendar);
            if (SUCCEEDED(Fnd::ActivateInstance(calendarClassId.Get(), calendar.GetAddressOf())))
            {
               ABIFnd::DateTime dateTime;
               if (SUCCEEDED(calendar->GetDateTime(&dateTime)))
               {
                   WRL::ComPtr<ABIGlob::DateTimeFormatting::IDateTimeFormatterFactory> dateTimeFormatterFactory;
                   Wrap::HStringReference dateTimeFormatterId(RuntimeClass_Windows_Globalization_DateTimeFormatting_DateTimeFormatter);
                   if (SUCCEEDED(Fnd::GetActivationFactory(dateTimeFormatterId.Get(), dateTimeFormatterFactory.GetAddressOf())))
                   {
                       WRL::ComPtr<ABIGlob::DateTimeFormatting::IDateTimeFormatter> dateTimeFormatter;
                       Wrap::HStringReference dateTimeFormat(format);
                       if (SUCCEEDED(dateTimeFormatterFactory->CreateDateTimeFormatter(dateTimeFormat.Get(), dateTimeFormatter.GetAddressOf())))
                       {
                           Wrap::HString formattedDateTime;
                           if (SUCCEEDED(dateTimeFormatter->Format(dateTime, formattedDateTime.GetAddressOf())))
                           {
                               uint buff_len;
                               auto buff = formattedDateTime.GetRawBuffer(&buff_len);
        
                               lbl.setText(QString::fromWCharArray(buff, buff_len));
                           }
                       }
                   }
               }
            }
        
            return a.exec();
        }
        

        And yes, before you manage to say "H O L Y    F U U U ..."  this is exactly the same as:

        #include <QApplication>
        #include <QLabel>
        #include <QDate>
        
        int main(int argc, char *argv[])
        {
            QApplication a(argc, argv);
        
            QLabel lbl(QDate::currentDate().toString("yyyy-MM-dd"));
            lbl.setAlignment(Qt::AlignCenter);
            lbl.show();
        
            return a.exec();
        }
        

        To spare yourself from going absolutely insane you might want to look into wrapper libraries like Modern.

        R Offline
        R Offline
        Rad B
        wrote on 25 Jun 2016, 19:39 last edited by Rad B
        #3

        @Chris-Kawa Thanks! I was actually hoping to use the HoloLens gestures as Qt has major problems with mouse and clicking on HoloLens. Or if Qt can be fixed I wouldn't have to.

        I need to make the mouse follow and make clicking work on HoloLens. Like before Tuesday, haha!

        M 1 Reply Last reply 29 Sept 2016, 13:30
        0
        • hskoglundH Offline
          hskoglundH Offline
          hskoglund
          wrote on 25 Jun 2016, 20:21 last edited by hskoglund
          #4

          Hi, thanks @Chris-Kawa for that example!

          Because I like to hurt myself I had to try it on my Windows 10 PC (worked fine).
          Just want to add, if you want to run it as well, you need to add:

          LIBS += -lruntimeobject
          

          to your .pro file.

          Edit: forgot to say: I tested with a vanilla Widgets app using the kit Desktop Qt 5.7.0 MSVC2015. However, if you instead select the Universal Windows Platform kit then that LIBS line above is not needed.

          1 Reply Last reply
          1
          • C Offline
            C Offline
            Chris Kawa
            Lifetime Qt Champion
            wrote on 25 Jun 2016, 21:28 last edited by
            #5

            As much as I hate language extensions it would probably be easier to use C++/CX. It would make the example not much longer than that with Qt, but I can't seem to enable it.
            Passing /ZW and /AI <path to Platform.winmd> to the compiler (via QMAKE_CXXFLAGS in .pro file) should be enough AFAIK, but I get errors on as simple line as this:

            String^ foo = ref new String(L"Hello");
            

            error: C2664: 'long __winRT::__getActivationFactoryByPCWSTR(void *,Platform::Guid &,void **)': cannot convert argument 1 from 'const wchar_t []' to 'void *'
            Probably some switch still missing somewhere...

            1 Reply Last reply
            1
            • hskoglundH Offline
              hskoglundH Offline
              hskoglund
              wrote on 25 Jun 2016, 23:18 last edited by
              #6

              Hmm, never tried those pesky extensions, but being curious, I tried to reproduce your error but no luck :-( Maybe you're not on Windows 10 and MSVC2015?

              I got it to run with your example above, by adding #include <qdebug.h> and these lines just before return a.exec(); at the end:

              using namespace Platform;
              String^ foo = ref new String(L"Hello");
              qDebug() << QString::fromWCharArray(foo->Data());
              

              I tested both the 5.7.0 Desktop MSVC2015 32-bit and the Universal Windows Platform kit.

              And yeah, those /ZW and /AI switches (no space between /AI and dirname!) have to be in the .pro file:
              QMAKE_CXXFLAGS += /ZW /AI\"C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcpackages\"

              1 Reply Last reply
              2
              • C Offline
                C Offline
                Chris Kawa
                Lifetime Qt Champion
                wrote on 25 Jun 2016, 23:53 last edited by
                #7

                @hskoglund said:

                Maybe you're not on Windows 10 and MSVC2015?

                I'm on Win10 and MSVC2015 with Qt5.7UWP. Yeah, sorry, I mixed up my tests. The string alone works indeed, but try this full example and you should see the errors:

                #include <QApplication>
                #include <QLabel>
                
                using namespace Platform;
                using namespace Windows::Globalization;
                using namespace Windows::Globalization::DateTimeFormatting;
                
                int main(int argc, char *argv[])
                {
                    QApplication a(argc, argv);
                
                    auto calendar = ref new Calendar();
                    auto dateTime = calendar->GetDateTime();
                    String^ format = L"{year.full}-{month.integer(2)}-{day.integer(2)}";
                    auto dateTimeFormatter = ref new DateTimeFormatter(format);
                    auto formatted = dateTimeFormatter->Format(dateTime);
                
                    QLabel lbl(QString::fromWCharArray(formatted->Data()));
                    lbl.setAlignment(Qt::AlignCenter);
                    lbl.show();
                
                    return a.exec();
                }
                
                R 1 Reply Last reply 26 Jun 2016, 00:27
                0
                • C Chris Kawa
                  25 Jun 2016, 23:53

                  @hskoglund said:

                  Maybe you're not on Windows 10 and MSVC2015?

                  I'm on Win10 and MSVC2015 with Qt5.7UWP. Yeah, sorry, I mixed up my tests. The string alone works indeed, but try this full example and you should see the errors:

                  #include <QApplication>
                  #include <QLabel>
                  
                  using namespace Platform;
                  using namespace Windows::Globalization;
                  using namespace Windows::Globalization::DateTimeFormatting;
                  
                  int main(int argc, char *argv[])
                  {
                      QApplication a(argc, argv);
                  
                      auto calendar = ref new Calendar();
                      auto dateTime = calendar->GetDateTime();
                      String^ format = L"{year.full}-{month.integer(2)}-{day.integer(2)}";
                      auto dateTimeFormatter = ref new DateTimeFormatter(format);
                      auto formatted = dateTimeFormatter->Format(dateTime);
                  
                      QLabel lbl(QString::fromWCharArray(formatted->Data()));
                      lbl.setAlignment(Qt::AlignCenter);
                      lbl.show();
                  
                      return a.exec();
                  }
                  
                  R Offline
                  R Offline
                  Rad B
                  wrote on 26 Jun 2016, 00:27 last edited by Rad B
                  #8

                  @Chris-Kawa @hskoglund

                  Great information, Thanks!

                  Unfortunately I don't think UWP HoloLens Gestures will work as it is 3D based and with a UWP app that's tough if not impossible. Well it would take some time and I have to have this project done before Tuesday. Probably not going to be possible.

                  Unless either of you know how to do this:
                  So the UWP apps are run in a container. Not sure if it is a Windows App Container or not but I want to be able to access the raw mouse & keyboard from the container level.

                  Thanks so much for your help!

                  1 Reply Last reply
                  0
                  • hskoglundH Offline
                    hskoglundH Offline
                    hskoglund
                    wrote on 26 Jun 2016, 01:10 last edited by hskoglund
                    #9

                    @Rad-B: Hi, I know games need to do this, and since some of them are UWP apps, raw mouse and keyboard access should be possible, for an example see stackoverflow

                    @Chris-Kawa: Indeed this time I got the errors (2 of them):
                    C:\Projects\untitled\main.cpp:23: error: C2664: 'long __winRT::__getActivationFactoryByPCWSTR(void *,Platform::Guid &,void **)': cannot convert argument 1 from 'const wchar_t [31]' to 'void *'

                    Googling a bit it seems this interesting error has struck more people than you (i.e you have not forgotten any switch or something similar).

                    So in conclusion I think this is a Monday morning bug and, while waiting for Microsoft to fix it (perhaps in Update 3?) you can always resort to a kludge, insert these fine lines of code just before int main(...:

                    HRESULT __stdcall GetActivationFactoryByPCWSTR(void*,Guid&, void**);
                    namespace __winRT
                    {
                        HRESULT __stdcall __getActivationFactoryByPCWSTR(const void* str, ::Platform::Guid& pGuid, void** ppActivationFactory)
                        {
                            return GetActivationFactoryByPCWSTR(const_cast<void*>(str), pGuid, ppActivationFactory);
                        }
                    }
                    

                    This will cast away that const problem for you :-)

                    1 Reply Last reply
                    1
                    • C Offline
                      C Offline
                      Chris Kawa
                      Lifetime Qt Champion
                      wrote on 26 Jun 2016, 14:35 last edited by Chris Kawa
                      #10

                      @hskoglund Thanks for the workaround. I wonder how such a blatant bug could have slipped in :/

                      @Rad-B I don't have HoloLens so I can only speculate, but looking at the examples it doesn't seem to be that different from my calendar example, you just use the classes from the Windows::UI::Input::Spatial namespace. It seems the C++/CX is the easiest here, so you will probably have to use the workaround @hskoglund provided.
                      See here for some code examples (the SpatialInputHandler.h/.cpp files).

                      R 1 Reply Last reply 27 Jun 2016, 07:54
                      0
                      • C Chris Kawa
                        26 Jun 2016, 14:35

                        @hskoglund Thanks for the workaround. I wonder how such a blatant bug could have slipped in :/

                        @Rad-B I don't have HoloLens so I can only speculate, but looking at the examples it doesn't seem to be that different from my calendar example, you just use the classes from the Windows::UI::Input::Spatial namespace. It seems the C++/CX is the easiest here, so you will probably have to use the workaround @hskoglund provided.
                        See here for some code examples (the SpatialInputHandler.h/.cpp files).

                        R Offline
                        R Offline
                        Rad B
                        wrote on 27 Jun 2016, 07:54 last edited by Rad B
                        #11

                        @Chris-Kawa @hskoglund How can I access Windows.UI.Core.CoreWindow?

                        namespace Windows::UI does not seem to work.

                        Thanks for both of your help!

                        1 Reply Last reply
                        0
                        • R Rad B
                          25 Jun 2016, 19:39

                          @Chris-Kawa Thanks! I was actually hoping to use the HoloLens gestures as Qt has major problems with mouse and clicking on HoloLens. Or if Qt can be fixed I wouldn't have to.

                          I need to make the mouse follow and make clicking work on HoloLens. Like before Tuesday, haha!

                          M Offline
                          M Offline
                          mkalinow
                          wrote on 29 Sept 2016, 13:30 last edited by
                          #12

                          @Rad-B Sorry for being a bit late to the discussion, but input on Hololens should have been fixed by https://codereview.qt-project.org/#/c/170653/ . At least we got feedback on JIRA, that this resolves input problems...

                          1 Reply Last reply
                          2
                          • C Offline
                            C Offline
                            Chris Kawa
                            Lifetime Qt Champion
                            wrote on 16 Oct 2016, 09:58 last edited by Chris Kawa
                            #13

                            Hey, good news! After years of begging Microsoft released a WinRT C++ library that doesn't suck like WRL: C++/WinRT

                            It's actually kinda simple to use. Close to Qt if not for the long names and namespaces. I gave it a whirl with the calendar example:

                            #include <QApplication>
                            #include <QLabel>
                            #include "winrt/Windows.Globalization.h"
                            #include "winrt/Windows.Globalization.DateTimeFormatting.h"
                            
                            #pragma comment(lib, "windowsapp")
                            using namespace winrt::Windows::Globalization;
                            using namespace winrt::Windows::Globalization::DateTimeFormatting;
                            
                            int main(int argc, char *argv[])
                            {
                                QApplication a(argc, argv);
                            
                                std::wstring formatted = DateTimeFormatter(L"{year.full}-{month.integer(2)}-{day.integer(2)}").Format(Calendar().GetDateTime());
                            
                                QLabel lbl(QString::fromWCharArray(formatted.c_str()));
                                lbl.setAlignment(Qt::AlignCenter);
                                lbl.show();
                            
                                return a.exec();
                            }
                            
                            1 Reply Last reply
                            0

                            • Login

                            • Login or register to search.
                            • First post
                              Last post
                            0
                            • Categories
                            • Recent
                            • Tags
                            • Popular
                            • Users
                            • Groups
                            • Search
                            • Get Qt Extensions
                            • Unsolved