FiveTech Support Forums

FiveWin / Harbour / xBase community
Board index FiveWin for Harbour/xHarbour Windows Toast notifications - second try
Posts: 44162
Joined: Thu Oct 06, 2005 05:47 PM
Re: Windows Toast notifications - second try
Posted: Fri Apr 15, 2016 07:21 AM
Its working! :-)

Download the EXE and try it on your Windows 10:
https://bitbucket.org/fivetech/fivewin-contributions/downloads/toast.zip





toast.prg
Code (fw): Select all Collapse
#include "FiveWin.ch"

function Main()

   Toast()

return nil

#pragma BEGINDUMP

#include <Windows.h>
#include <psapi.h>
#include <Shobjidl.h>
#include <Propvarutil.h>
#include <propkey.h>
#include <wrl\client.h>
#include <windows.ui.notifications.h>
#include <hbapi.h>

using namespace Microsoft::WRL;
using namespace ABI::Windows::UI::Notifications;
using namespace ABI::Windows::Data::Xml::Dom;
using namespace Windows::Foundation;

static HRESULT InstallShortcut(_In_z_ wchar_t *shortcutPath)
{
    wchar_t exePath[MAX_PATH];
    
    DWORD charWritten = GetModuleFileNameEx(GetCurrentProcess(), nullptr, ( LPSTR ) exePath, ARRAYSIZE(exePath));

    HRESULT hr = charWritten > 0 ? S_OK : E_FAIL;
    
    if (SUCCEEDED(hr))
    {
        ComPtr<IShellLink> shellLink;
        hr = CoCreateInstance(CLSID_ShellLink, nullptr, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&shellLink));

        if (SUCCEEDED(hr))
        {
            hr = shellLink->SetPath((LPCSTR)exePath);
            if (SUCCEEDED(hr))
            {
                hr = shellLink->SetArguments((LPCSTR)L"");
                if (SUCCEEDED(hr))
                {
                    ComPtr<IPropertyStore> propertyStore;

                    hr = shellLink.As(&propertyStore);
                    if (SUCCEEDED(hr))
                    {
                        PROPVARIANT appIdPropVar;
                        hr = InitPropVariantFromString(L"FiveTech.FiveWin.samples", &appIdPropVar);
                        if (SUCCEEDED(hr))
                        {
                            hr = propertyStore->SetValue(PKEY_AppUserModel_ID, appIdPropVar);
                            if (SUCCEEDED(hr))
                            {
                                hr = propertyStore->Commit();
                                if (SUCCEEDED(hr))
                                {
                                    ComPtr<IPersistFile> persistFile;
                                    hr = shellLink.As(&persistFile);
                                    if (SUCCEEDED(hr))
                                    {
                                        hr = persistFile->Save(shortcutPath, TRUE);
                                    }
                                }
                            }
                            PropVariantClear(&appIdPropVar);
                        }
                    }
                }
            }
        }
    }
    return hr;
}

static HRESULT TryCreateShortcut( void )
{
   wchar_t shortcutPath[MAX_PATH];
   DWORD charWritten = GetEnvironmentVariableW( L"APPDATA", shortcutPath, MAX_PATH );
   HRESULT hr = charWritten > 0 ? S_OK : E_INVALIDARG;

    if (SUCCEEDED(hr))
    {
        errno_t concatError = wcscat_s(shortcutPath, ARRAYSIZE(shortcutPath), L"\\Microsoft\\Windows\\Start Menu\\Programs\\Desktop Toasts App.lnk");
 
        hr = concatError == 0 ? S_OK : E_INVALIDARG;
        if (SUCCEEDED(hr))
        {
            DWORD attributes = GetFileAttributes( ( LPCSTR ) shortcutPath );
            bool fileExists = attributes < 0xFFFFFFF;

            if (!fileExists)
            {
                hr = InstallShortcut(shortcutPath);  // See step 2.
            }
            else
            {
                hr = S_FALSE;
            }
        }
    }
    return hr;
}

HB_FUNC( TOAST )
{
   ComPtr<IToastNotificationManagerStatics> toastStatics;
   HSTRING hs = 0;
   HRESULT hr = WindowsCreateString( RuntimeClass_Windows_UI_Notifications_ToastNotificationManager, 
                                     wcslen( RuntimeClass_Windows_UI_Notifications_ToastNotificationManager ), &hs );
                         
   CoInitialize( NULL );

   hr = TryCreateShortcut();

   hr = GetActivationFactory( hs, toastStatics.GetAddressOf() );

   if( toastStatics )
   {
      ComPtr<IXmlDocument> toastXml;
      ComPtr<IToastNotifier> notifier;
      ComPtr<IToastNotification> notification;
      ComPtr<IToastNotificationFactory> factory;
      
      hr = toastStatics->GetTemplateContent( ToastTemplateType::ToastTemplateType_ToastText01, &toastXml );
      
      ComPtr<IXmlNodeList> toastTextElements, toastImageElements;
      ComPtr<IXmlNode> titleTextNodeRoot, msgTextNodeRoot, imageNodeRoot, srcAttribute;

      // HSTRING title, msg, imagePath;
      HSTRING textNodeStr, imageNodeStr, srcNodeStr;
      HSTRING_HEADER textHeader, imageHeader, srcHeader;
  
      WindowsCreateStringReference( L"text", 4, &textHeader, &textNodeStr );
      WindowsCreateStringReference( L"image", 5, &imageHeader, &imageNodeStr );
      WindowsCreateStringReference( L"src", 3, &srcHeader, &srcNodeStr );
     
      toastXml->GetElementsByTagName( textNodeStr, &toastTextElements );
      toastXml->GetElementsByTagName( imageNodeStr, &toastImageElements );

      toastTextElements->Item( 0, &titleTextNodeRoot );
      toastTextElements->Item( 1, &msgTextNodeRoot );
      toastImageElements->Item( 0, &imageNodeRoot );

      ComPtr<IXmlNamedNodeMap> attributes;
      // imageNodeRoot->get_Attributes( &attributes );
      // attributes->GetNamedItem( srcNodeStr, &srcAttribute );

      // SetNodeValueString( title, titleTextNodeRoot.Get(), toastXml.Get());
      // SetNodeValueString( msg, msgTextNodeRoot.Get(), toastXml.Get());
      // SetNodeValueString( imagePath, srcAttribute.Get(), toastXml.Get());
  
      hr = WindowsCreateString( RuntimeClass_Windows_UI_Notifications_ToastNotification,
                                wcslen( RuntimeClass_Windows_UI_Notifications_ToastNotification ), &hs );  
                                
      hr = GetActivationFactory( hs, &factory );

      hr = factory->CreateToastNotification( toastXml.Get(), &notification );

      hr = WindowsCreateString( L"FiveWin", wcslen( L"FiveWin" ), &hs );  

      hr = toastStatics->CreateToastNotifierWithId( hs, &notifier );
      
      hr = notifier->Show( notification.Get() );
   }    
}

#pragma ENDDUMP
regards, saludos

Antonio Linares
www.fivetechsoft.com
Posts: 990
Joined: Wed Oct 19, 2005 02:17 PM
Re: Windows Toast notifications - second try
Posted: Fri Apr 15, 2016 07:39 AM

Great !!!

Thanks !

Regards

Posts: 7318
Joined: Thu Oct 18, 2012 07:17 PM
Re: Windows Toast notifications - second try
Posted: Fri Apr 15, 2016 10:38 AM

Antonio,
but How it is compiled ? because here I have problems to compile it ?

Since from 1991/1992 ( fw for clipper Rel. 14.4 - Momos)

I use : FiveWin for Harbour March-April 2024 - Harbour 3.2.0dev (harbour_bcc770_32_20240309) - Bcc7.70 - xMate ver. 1.15.3 - PellesC - mail: silvio[dot]falconi[at]gmail[dot]com
Posts: 866
Joined: Tue Oct 16, 2007 08:57 AM
Re: Windows Toast notifications - second try
Posted: Fri Apr 15, 2016 11:53 AM

Antonio,

It's work.

Best Regards,



Richard



Harbour 3.2.0dev (r2503251254) => Borland C++ v7.7 32bit

MySQL v8.0

Harbour 3.2.0dev (r2503251254) => Borland C++ v7.7 64bit
Posts: 566
Joined: Thu Aug 30, 2007 03:40 PM
Re: Windows Toast notifications - second try
Posted: Fri Apr 15, 2016 12:46 PM

Antonio, your test work fine here, can i use with xharbour and bcc or only with VS?

thanks

Posts: 44162
Joined: Thu Oct 06, 2005 05:47 PM
Re: Windows Toast notifications - second try
Posted: Fri Apr 15, 2016 02:06 PM

Norberto, Silvio,

I am using VSC2015 (Visual Studio Community 2015) to implement it.

later on, I will try to build it using Borland too

regards, saludos

Antonio Linares
www.fivetechsoft.com
Posts: 4840
Joined: Fri Nov 18, 2005 04:52 PM
Re: Windows Toast notifications - second try
Posted: Fri Apr 15, 2016 02:29 PM

Congrats, Antonio!

I'm looking forward to trying it when you have a Borland version running.

James

FWH 18.05/xHarbour 1.2.3/BCC7/Windows 10
Posts: 44162
Joined: Thu Oct 06, 2005 05:47 PM
Re: Windows Toast notifications - second try
Posted: Fri Apr 15, 2016 05:53 PM
Enhanced version

toast.prg
Code (fw): Select all Collapse
#include "FiveWin.ch"

function Main()

   Toast( "Harbour and FWH power", "it is working", "three lines" )

return nil

#pragma BEGINDUMP

#include <Windows.h>
#include <psapi.h>
#include <Shobjidl.h>
#include <Propvarutil.h>
#include <propkey.h>
#include <wrl\client.h>
#include <windows.ui.notifications.h>
#include <hbapi.h>

using namespace Microsoft::WRL;
using namespace ABI::Windows::UI::Notifications;
using namespace ABI::Windows::Data::Xml::Dom;
using namespace Windows::Foundation;

extern "C" {
LPWSTR UTF8toUTF16( LPCSTR utf8 );
}

static void InstallShortcut( wchar_t * shortcutPath )
{
    wchar_t exePath[ MAX_PATH] ;
    ComPtr<IShellLink> shellLink;
    ComPtr<IPropertyStore> propertyStore;
    PROPVARIANT appIdPropVar;
    ComPtr<IPersistFile> persistFile;
    
    DWORD charWritten = GetModuleFileNameEx( GetCurrentProcess(), nullptr, 
                                             ( LPSTR ) exePath, ARRAYSIZE( exePath ) );

    CoCreateInstance( CLSID_ShellLink, nullptr, CLSCTX_INPROC_SERVER, IID_PPV_ARGS( &shellLink ) );
    shellLink->SetPath( ( LPCSTR ) exePath );
    shellLink->SetArguments( ( LPCSTR ) L"" );

    shellLink.As( &propertyStore );
    InitPropVariantFromString( L"FiveTech.FiveWin.samples", &appIdPropVar );
                        
    propertyStore->SetValue( PKEY_AppUserModel_ID, appIdPropVar);
    propertyStore->Commit();
                                
    shellLink.As( &persistFile );
    persistFile->Save( shortcutPath, TRUE );
    PropVariantClear( &appIdPropVar );
}

static void TryCreateShortcut( void )
{
   wchar_t shortcutPath[ MAX_PATH ];
   DWORD charWritten = GetEnvironmentVariableW( L"APPDATA", shortcutPath, MAX_PATH );

   errno_t concatError = wcscat_s( shortcutPath, ARRAYSIZE( shortcutPath ), 
                                   L"\\Microsoft\\Windows\\Start Menu\\Programs\\Desktop Toasts App.lnk" );
 
   if( GetFileAttributes( ( LPCSTR ) shortcutPath ) >= 0xFFFFFFF )
      InstallShortcut( shortcutPath );
}

static void SetNodeValueString( const char * szText, IXmlNode * node, IXmlDocument * xml )
{
   LPWSTR pW = UTF8toUTF16( szText );
   HSTRING hs;
   ComPtr<IXmlText> inputText;
   ComPtr<IXmlNode> inputTextNode;
   ComPtr<IXmlNode> pAppendedChild;
   
   WindowsCreateString( pW, wcslen( pW ), &hs );  
   hb_xfree( pW );
   xml->CreateTextNode( hs, &inputText );
   WindowsDeleteString( hs );    
   inputText.As( &inputTextNode );
   node->AppendChild( inputTextNode.Get(), &pAppendedChild );
}

HB_FUNC( TOAST )
{
   ComPtr<IToastNotificationManagerStatics> toastStatics;
   HSTRING hs = 0; LPWSTR pW; int i;
        
   CoInitialize( NULL );

   TryCreateShortcut();

   WindowsCreateString( RuntimeClass_Windows_UI_Notifications_ToastNotificationManager, 
                        wcslen( RuntimeClass_Windows_UI_Notifications_ToastNotificationManager ), &hs );
   GetActivationFactory( hs, toastStatics.GetAddressOf() );
   WindowsDeleteString( hs );

   ComPtr<IXmlDocument> toastXml;
   ComPtr<IToastNotifier> notifier;
   ComPtr<IToastNotification> notification;
   ComPtr<IToastNotificationFactory> factory;
      
   toastStatics->GetTemplateContent( ToastTemplateType::ToastTemplateType_ToastText04, &toastXml );
      
   ComPtr<IXmlNodeList> toastTextElements, toastImageElements;
   ComPtr<IXmlNode> xmlNode;

   WindowsCreateString( L"text", wcslen( L"text" ), &hs );
   toastXml->GetElementsByTagName( hs, &toastTextElements );
   WindowsDeleteString( hs );

   WindowsCreateString( L"image", wcslen( L"image" ), &hs );
   toastXml->GetElementsByTagName( hs, &toastImageElements );
   WindowsDeleteString( hs );

   for( i = 0; i < 3; i++ )
   {
      if( HB_ISCHAR( i + 1 ) )
      {
         toastTextElements->Item( i, &xmlNode );
         SetNodeValueString( hb_parc( i + 1 ), xmlNode.Get(), toastXml.Get() );
      }   
   }

   WindowsCreateString( RuntimeClass_Windows_UI_Notifications_ToastNotification,
                        wcslen( RuntimeClass_Windows_UI_Notifications_ToastNotification ), &hs );  
   GetActivationFactory( hs, &factory );
   WindowsDeleteString( hs );    

   factory->CreateToastNotification( toastXml.Get(), &notification );

   pW = UTF8toUTF16( "FiveTech" );
   WindowsCreateString( pW, wcslen( pW ), &hs );  
   hb_xfree( pW );
   toastStatics->CreateToastNotifierWithId( hs, &notifier );
   WindowsDeleteString( hs );
      
   notifier->Show( notification.Get() );
}

#pragma ENDDUMP
regards, saludos

Antonio Linares
www.fivetechsoft.com
Posts: 44162
Joined: Thu Oct 06, 2005 05:47 PM
Re: Windows Toast notifications - second try
Posted: Fri Apr 15, 2016 07:03 PM
Images working :-)



toast.prg
Code (fw): Select all Collapse
#include "FiveWin.ch"

function Main()

   Toast( "Harbour and FWH power", "it is working", "three lines",;
          "file://c:\fwh\bitmaps\pngs\fivetech.png" )

return nil

#pragma BEGINDUMP

#include <Windows.h>
#include <psapi.h>
#include <Shobjidl.h>
#include <Propvarutil.h>
#include <propkey.h>
#include <wrl\client.h>
#include <windows.ui.notifications.h>
#include <hbapi.h>

using namespace Microsoft::WRL;
using namespace ABI::Windows::UI::Notifications;
using namespace ABI::Windows::Data::Xml::Dom;
using namespace Windows::Foundation;

extern "C" {
LPWSTR UTF8toUTF16( LPCSTR utf8 );
}

static void InstallShortcut( wchar_t * shortcutPath )
{
    wchar_t exePath[ MAX_PATH] ;
    ComPtr<IShellLink> shellLink;
    ComPtr<IPropertyStore> propertyStore;
    PROPVARIANT appIdPropVar;
    ComPtr<IPersistFile> persistFile;
    
    DWORD charWritten = GetModuleFileNameEx( GetCurrentProcess(), nullptr, 
                                             ( LPSTR ) exePath, ARRAYSIZE( exePath ) );

    CoCreateInstance( CLSID_ShellLink, nullptr, CLSCTX_INPROC_SERVER, IID_PPV_ARGS( &shellLink ) );
    shellLink->SetPath( ( LPCSTR ) exePath );
    shellLink->SetArguments( ( LPCSTR ) L"" );

    shellLink.As( &propertyStore );
    InitPropVariantFromString( L"FiveTech.FiveWin.samples", &appIdPropVar );
                        
    propertyStore->SetValue( PKEY_AppUserModel_ID, appIdPropVar);
    propertyStore->Commit();
                                
    shellLink.As( &persistFile );
    persistFile->Save( shortcutPath, TRUE );
    PropVariantClear( &appIdPropVar );
}

static void TryCreateShortcut( void )
{
   wchar_t shortcutPath[ MAX_PATH ];
   DWORD charWritten = GetEnvironmentVariableW( L"APPDATA", shortcutPath, MAX_PATH );

   errno_t concatError = wcscat_s( shortcutPath, ARRAYSIZE( shortcutPath ), 
                                   L"\\Microsoft\\Windows\\Start Menu\\Programs\\Desktop Toasts App.lnk" );
 
   if( GetFileAttributes( ( LPCSTR ) shortcutPath ) >= 0xFFFFFFF )
      InstallShortcut( shortcutPath );
}

static void SetNodeValueString( const char * szText, IXmlNode * node, IXmlDocument * xml )
{
   LPWSTR pW = UTF8toUTF16( szText );
   HSTRING hs;
   ComPtr<IXmlText> inputText;
   ComPtr<IXmlNode> inputTextNode;
   ComPtr<IXmlNode> pAppendedChild;
   
   WindowsCreateString( pW, wcslen( pW ), &hs );  
   hb_xfree( pW );
   xml->CreateTextNode( hs, &inputText );
   WindowsDeleteString( hs );    
   inputText.As( &inputTextNode );
   node->AppendChild( inputTextNode.Get(), &pAppendedChild );
}

static void SetImageSrc( LPCSTR imagePath, IXmlDocument * toastXml )
{
   HSTRING hs;
   HRESULT hr;

   ComPtr<IXmlNodeList> nodeList;
   WindowsCreateString( L"image", wcslen( L"image" ), &hs );
   hr = toastXml->GetElementsByTagName( hs, &nodeList );
   WindowsDeleteString( hs );

   ComPtr<IXmlNode> imageNode;
   hr = nodeList->Item( 0, &imageNode );

   ComPtr<IXmlNamedNodeMap> attributes;
   hr = imageNode->get_Attributes( &attributes );

   ComPtr<IXmlNode> srcAttribute;
   WindowsCreateString( L"src", wcslen( L"src" ), &hs );
   attributes->GetNamedItem( hs, &srcAttribute );
   WindowsDeleteString( hs );

   SetNodeValueString( imagePath, srcAttribute.Get(), toastXml );
}

HB_FUNC( TOAST )
{
   ComPtr<IToastNotificationManagerStatics> toastStatics;
   HSTRING hs = 0; LPWSTR pW; int i;
        
   CoInitialize( NULL );

   TryCreateShortcut();

   WindowsCreateString( RuntimeClass_Windows_UI_Notifications_ToastNotificationManager, 
                        wcslen( RuntimeClass_Windows_UI_Notifications_ToastNotificationManager ), &hs );
   GetActivationFactory( hs, toastStatics.GetAddressOf() );
   WindowsDeleteString( hs );

   ComPtr<IXmlDocument> toastXml;
   ComPtr<IToastNotifier> notifier;
   ComPtr<IToastNotification> notification;
   ComPtr<IToastNotificationFactory> factory;
      
   toastStatics->GetTemplateContent( ToastTemplateType::ToastTemplateType_ToastImageAndText04, &toastXml );
      
   ComPtr<IXmlNodeList> toastTextElements;
   ComPtr<IXmlNode> xmlNode;

   WindowsCreateString( L"text", wcslen( L"text" ), &hs );
   toastXml->GetElementsByTagName( hs, &toastTextElements );
   WindowsDeleteString( hs );

   for( i = 0; i < 3; i++ )
   {
      if( HB_ISCHAR( i + 1 ) )
      {
         toastTextElements->Item( i, &xmlNode );
         SetNodeValueString( hb_parc( i + 1 ), xmlNode.Get(), toastXml.Get() );
      }   
   }

   if( HB_ISCHAR( 4 ) )
      SetImageSrc( hb_parc( 4 ), toastXml.Get() );

   WindowsCreateString( RuntimeClass_Windows_UI_Notifications_ToastNotification,
                        wcslen( RuntimeClass_Windows_UI_Notifications_ToastNotification ), &hs );  
   GetActivationFactory( hs, &factory );
   WindowsDeleteString( hs );    

   factory->CreateToastNotification( toastXml.Get(), &notification );

   pW = UTF8toUTF16( "FiveTech" );
   WindowsCreateString( pW, wcslen( pW ), &hs );  
   hb_xfree( pW );
   toastStatics->CreateToastNotifierWithId( hs, &notifier );
   WindowsDeleteString( hs );
      
   notifier->Show( notification.Get() );
}

#pragma ENDDUMP
regards, saludos

Antonio Linares
www.fivetechsoft.com
Posts: 7318
Joined: Thu Oct 18, 2012 07:17 PM
Re: Windows Toast notifications - second try
Posted: Sat Apr 16, 2016 10:32 AM

it need the possibility to insert a button for close the toast ( at right) and another ( at left ) to open a user function
I hope you make the borland version

Since from 1991/1992 ( fw for clipper Rel. 14.4 - Momos)

I use : FiveWin for Harbour March-April 2024 - Harbour 3.2.0dev (harbour_bcc770_32_20240309) - Bcc7.70 - xMate ver. 1.15.3 - PellesC - mail: silvio[dot]falconi[at]gmail[dot]com
Posts: 7318
Joined: Thu Oct 18, 2012 07:17 PM
Re: Windows Toast notifications - second try
Posted: Sat Apr 16, 2016 04:47 PM

on win seven not run it need a api-ms.core-winrt-i1-1-0.dll

Since from 1991/1992 ( fw for clipper Rel. 14.4 - Momos)

I use : FiveWin for Harbour March-April 2024 - Harbour 3.2.0dev (harbour_bcc770_32_20240309) - Bcc7.70 - xMate ver. 1.15.3 - PellesC - mail: silvio[dot]falconi[at]gmail[dot]com
Posts: 44162
Joined: Thu Oct 06, 2005 05:47 PM
Re: Windows Toast notifications - second try
Posted: Sun Apr 17, 2016 04:39 AM

Silvio,

We are focused on Windows 10 now

This will be the code for Borland once it is ready:

viewtopic.php?p=189308#p189308

regards, saludos

Antonio Linares
www.fivetechsoft.com
Posts: 566
Joined: Thu Aug 30, 2007 03:40 PM
Re: Windows Toast notifications - second try
Posted: Sun Apr 17, 2016 10:06 AM

Antonio, it would be very interesting to do this also with email, calendar, people, translator, native and free Windows 10 applications, native interact with these applications to our programs in fwh. Thank you

Posts: 44162
Joined: Thu Oct 06, 2005 05:47 PM
Re: Windows Toast notifications - second try
Posted: Sun Apr 17, 2016 11:41 AM

Norberto,

We need to build a special WinRT support module

Lets see if we can build it

regards, saludos

Antonio Linares
www.fivetechsoft.com
Posts: 7318
Joined: Thu Oct 18, 2012 07:17 PM
Re: Windows Toast notifications - second try
Posted: Sun Apr 17, 2016 04:28 PM
Antonio Linares wrote:Silvio,

We are focused on Windows 10 now

This will be the code for Borland once it is ready:

viewtopic.php?p=189308#p189308


where I can download combase.dll ?
Since from 1991/1992 ( fw for clipper Rel. 14.4 - Momos)

I use : FiveWin for Harbour March-April 2024 - Harbour 3.2.0dev (harbour_bcc770_32_20240309) - Bcc7.70 - xMate ver. 1.15.3 - PellesC - mail: silvio[dot]falconi[at]gmail[dot]com