Windows Toast notifications - second try

User avatar
Antonio Linares
Site Admin
Posts: 42511
Joined: Thu Oct 06, 2005 5:47 pm
Location: Spain
Has thanked: 31 times
Been thanked: 73 times
Contact:

Re: Windows Toast notifications - second try

Post by Antonio Linares »

Its working! :-)

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

Image

Image

toast.prg

Code: Select all | Expand

#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
User avatar
Baxajaun
Posts: 969
Joined: Wed Oct 19, 2005 2:17 pm
Location: Gatika. Bizkaia

Re: Windows Toast notifications - second try

Post by Baxajaun »

Great !!!

Thanks !

Regards
User avatar
Silvio.Falconi
Posts: 7133
Joined: Thu Oct 18, 2012 7:17 pm
Been thanked: 1 time

Re: Windows Toast notifications - second try

Post by Silvio.Falconi »

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 November 2023 - January 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
User avatar
richard-service
Posts: 807
Joined: Tue Oct 16, 2007 8:57 am
Location: New Taipei City, Taiwan
Has thanked: 1 time
Contact:

Re: Windows Toast notifications - second try

Post by richard-service »

Antonio,

It's work.
Best Regards,

Richard

Harbour 3.2.0dev (r2402101027) => Borland C++ v7.7 32bit
MySQL v8.0 /ADS v10
Harbour 3.2.0dev (r2011030937) => Borland C++ v7.4 64bit
norberto
Posts: 566
Joined: Thu Aug 30, 2007 3:40 pm
Location: BR

Re: Windows Toast notifications - second try

Post by norberto »

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

thanks
User avatar
Antonio Linares
Site Admin
Posts: 42511
Joined: Thu Oct 06, 2005 5:47 pm
Location: Spain
Has thanked: 31 times
Been thanked: 73 times
Contact:

Re: Windows Toast notifications - second try

Post by Antonio Linares »

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
User avatar
James Bott
Posts: 4840
Joined: Fri Nov 18, 2005 4:52 pm
Location: San Diego, California, USA
Contact:

Re: Windows Toast notifications - second try

Post by James Bott »

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
User avatar
Antonio Linares
Site Admin
Posts: 42511
Joined: Thu Oct 06, 2005 5:47 pm
Location: Spain
Has thanked: 31 times
Been thanked: 73 times
Contact:

Re: Windows Toast notifications - second try

Post by Antonio Linares »

Enhanced version

toast.prg

Code: Select all | Expand

#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
User avatar
Antonio Linares
Site Admin
Posts: 42511
Joined: Thu Oct 06, 2005 5:47 pm
Location: Spain
Has thanked: 31 times
Been thanked: 73 times
Contact:

Re: Windows Toast notifications - second try

Post by Antonio Linares »

Images working :-)

Image

toast.prg

Code: Select all | Expand

#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
User avatar
Silvio.Falconi
Posts: 7133
Joined: Thu Oct 18, 2012 7:17 pm
Been thanked: 1 time

Re: Windows Toast notifications - second try

Post by Silvio.Falconi »

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 November 2023 - January 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
User avatar
Silvio.Falconi
Posts: 7133
Joined: Thu Oct 18, 2012 7:17 pm
Been thanked: 1 time

Re: Windows Toast notifications - second try

Post by Silvio.Falconi »

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 November 2023 - January 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
User avatar
Antonio Linares
Site Admin
Posts: 42511
Joined: Thu Oct 06, 2005 5:47 pm
Location: Spain
Has thanked: 31 times
Been thanked: 73 times
Contact:

Re: Windows Toast notifications - second try

Post by Antonio Linares »

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
norberto
Posts: 566
Joined: Thu Aug 30, 2007 3:40 pm
Location: BR

Re: Windows Toast notifications - second try

Post by norberto »

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
User avatar
Antonio Linares
Site Admin
Posts: 42511
Joined: Thu Oct 06, 2005 5:47 pm
Location: Spain
Has thanked: 31 times
Been thanked: 73 times
Contact:

Re: Windows Toast notifications - second try

Post by Antonio Linares »

Norberto,

We need to build a special WinRT support module

Lets see if we can build it
regards, saludos

Antonio Linares
www.fivetechsoft.com
User avatar
Silvio.Falconi
Posts: 7133
Joined: Thu Oct 18, 2012 7:17 pm
Been thanked: 1 time

Re: Windows Toast notifications - second try

Post by Silvio.Falconi »

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 November 2023 - January 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
Post Reply