locked
Create a "toast" notification RRS feed

  • Question

  • Hello!

    I was thinking about this notification feature in Windows 8 called toast notification. Looks like this;

    I would like to create these kind of notifications in a WinForms application, is that possible?

    According to this article; Stackoverflow Link, it's possible but it's in C# code and the instructions is unclear to me. You got to add some references like Windows and Windows.UI and stuff.

    Anyone knows how to do this?

    Thanks!


    Wednesday, May 20, 2015 5:38 PM

Answers

  • Make two separate versions. One for Win 8 and above and one for less than Win 8.

    Have the installer detect if the OS is Win 8 or greater or less than Win 8. Then have it install whichever app is for what OS. That will require learning the installer to some detail.

    If anything answered your question then please propose it as an answer.


    La vida loca

    Thursday, May 21, 2015 2:03 PM

All replies

  • It seems there are VB.net example, check the below:

    https://code.msdn.microsoft.com/windowsapps/Toast-notifications-sample-52eeba29/view/SourceCode


    Fouad Roumieh

    Wednesday, May 20, 2015 6:46 PM
  • Allready checked that example, it's in Windows Runtime or Metro App which is not the same as a WinForm, the the Metro App allready includes the required references which WinForms don't have automaticly.
    Wednesday, May 20, 2015 6:49 PM
  • What operating system are you targeting?

    The example is talking about one reference:Windows.UI.Notifications and if its needed you have to add, but its minimum req for the op system is windows 8


    Fouad Roumieh

    Wednesday, May 20, 2015 6:58 PM
  • Windows.UI.Notifications namespace - Minimum supported client = Windows 8

    Windows.Data.Xml.Dom namespace - Minimum supported client = Windows 8

    Code converted by Telerik. Code would not convert in order it was in as errors occured. Try using online converters when necessary. Code not tested as I don't have a Win 8 system.

    Imports Windows.UI.Notifications
    Imports Windows.Data.Xml.Dom
    Imports System.IO
    
    
    
    Private Const APP_ID As [String] = "Microsoft.Samples.DesktopToastsSample"
    
    
    
    ' Get a toast XML template
    Dim toastXml As XmlDocument = ToastNotificationManager.GetTemplateContent(ToastTemplateType.ToastImageAndText04)
    
    ' Fill in the text elements
    Dim stringElements As Windows.Data.Xml.Dom.XmlNodeList = toastXml.GetElementsByTagName("text")
    For i As Integer = 0 To stringElements.Length - 1
    	stringElements(i).AppendChild(toastXml.CreateTextNode("Line " + i))
    Next
    
    ' Specify the absolute path to an image
    Dim imagePath As [String] = "file:///" + Path.GetFullPath("toastImageAndText.png")
    Dim imageElements As Windows.Data.Xml.Dom.XmlNodeList = toastXml.GetElementsByTagName("image")
    imageElements(0).Attributes.GetNamedItem("src").NodeValue = imagePath
    
    ' Create the toast and attach event listeners
    Dim toast As New ToastNotification(toastXml)
    'toast.Activated += ToastActivated;
    'toast.Dismissed += ToastDismissed;
    'toast.Failed += ToastFailed;
    
    ' Show the toast. Be sure to specify the AppUserModelId on your application's shortcut!
    ToastNotificationManager.CreateToastNotifier(APP_ID).Show(toast)
    
    '=======================================================
    'Service provided by Telerik (www.telerik.com)
    'Conversion powered by NRefactory.
    'Twitter: @telerik
    'Facebook: facebook.com/telerik
    '=======================================================
    


    La vida loca

    Wednesday, May 20, 2015 7:05 PM
  • You can also see this link although it doesn't perform exactly like a true Toast Notification. And read the links within the thread that may have information about Toast Notifications which you may want to know.

    Toast notification WinForm vb net


    La vida loca

    Wednesday, May 20, 2015 7:12 PM
  • Very Interesting!

    But, to get the import "Windows.*" i suppose that i have to change the targeted OS.

    I have found this;

        <PropertyGroup>
          <TargetPlatformVersion>8.0</TargetPlatformVersion>
        </PropertyGroup>

    I suppose i have to put it app.config file but where? I tried to put the above inside the "Configuration Section" but then the whole program wont start.

    Wednesday, May 20, 2015 7:20 PM
  • Well, the idea of making a artificial toast notification doesn't seems like a too bad idea, it could work.
    I will try to make a artificial one.

    But i would still like to know how to make a real one too, so please answer the above question xD

    Wednesday, May 20, 2015 7:24 PM
  • Well, the idea of making a artificial toast notification doesn't seems like a too bad idea, it could work.
    I will try to make a artificial one.

    But i would still like to know how to make a real one too, so please answer the above question xD

    I would suggest you download the VB.Net app at the link Fouad Roumieh provided. Even though it is WPF or something the code available within it, except for the sub routines since they use non-Windows.Forms events will most likely work in a Windows.Forms app once the appropriate imports are selected on a Win 8 system using VS 2013 since the app will not open in lesser VS.

    Then you can test the app as it comes and then copy code from it into a Windows.Forms app until you get it working correctly perhaps.

    Update: Also there is C#, but no VB, code and explanations in this link which further links to the link Fouad Roumieh provided.

    Quickstart: Sending a toast notification (XAML)


    La vida loca


    Wednesday, May 20, 2015 7:38 PM
  • Another example seems interesting from the screenshot:

    http://www.codeproject.com/Articles/442983/Android-Style-Toast-Notification-for-NET


    Fouad Roumieh

    Wednesday, May 20, 2015 8:31 PM
  • There's another C# example here Sending toast notifications from desktop apps sample.

    However it requires some .Dll's from the "Windows 7 API Code Pack" which you can get with NuGet. But I didn't do that as I downloaded it directly from here Windows-API-Code-Pack-1.1 and at the link select "source (original)" which will take you to a new page where you can select "Windows API Code Pack 1.1.zip" that will begin a download of a zip folder which contains a project, binaries, etc. The binaries will need to be ref'd by the app to work.

    I used Telerik to convert the code for the app to VB which is below. And don't know if it will work since I don't have Win 8. And I replaced the Button click event with a Windows.Forms button click event in the app I created and copied the code below into even though the code will not work on Win 7. I also had removed the Public Sub New code and placed that code in the Form Load event with the exception of the AddHandler since it would not be necessary for using a standard Button click event handler with a Button.

    Some issues have been reported trying to ref the Windows ref required. Which seems to be a ref to Windows.Winmd whatever that is. Something that has to do with WinRT.

    Imports System.Diagnostics
    Imports System.IO
    Imports System.Windows
    Imports System.Windows.Controls
    Imports DesktopToastsSample.ShellHelpers
    Imports MS.WindowsAPICodePack.Internal
    Imports Microsoft.WindowsAPICodePack.Shell.PropertySystem
    
    Imports Windows.UI.Notifications
    Imports Windows.Data.Xml.Dom
    
    Namespace DesktopToastsSample
    	Public Partial Class MainWindow
    		Inherits Window
    		Private Const APP_ID As [String] = "Microsoft.Samples.DesktopToastsSample"
    		Public Sub New()
    			InitializeComponent()
    			TryCreateShortcut()
    			AddHandler ShowToastButton.Click, AddressOf ShowToastButton_Click
    		End Sub
    
    		' In order to display toasts, a desktop application must have a shortcut on the Start menu.
    		' Also, an AppUserModelID must be set on that shortcut.
    		' The shortcut should be created as part of the installer. The following code shows how to create
    		' a shortcut and assign an AppUserModelID using Windows APIs. You must download and include the 
    		' Windows API Code Pack for Microsoft .NET Framework for this code to function
    		'
    		' Included in this project is a wxs file that be used with the WiX toolkit
    		' to make an installer that creates the necessary shortcut. One or the other should be used.
    		Private Function TryCreateShortcut() As Boolean
    			Dim shortcutPath As [String] = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + "\Microsoft\Windows\Start Menu\Programs\Desktop Toasts Sample CS.lnk"
    			If Not File.Exists(shortcutPath) Then
    				InstallShortcut(shortcutPath)
    				Return True
    			End If
    			Return False
    		End Function
    
    		Private Sub InstallShortcut(shortcutPath As [String])
    			' Find the path to the current executable
    			Dim exePath As [String] = Process.GetCurrentProcess().MainModule.FileName
    			Dim newShortcut As IShellLinkW = DirectCast(New CShellLink(), IShellLinkW)
    
    			' Create a shortcut to the exe
    			ShellHelpers.ErrorHelper.VerifySucceeded(newShortcut.SetPath(exePath))
    			ShellHelpers.ErrorHelper.VerifySucceeded(newShortcut.SetArguments(""))
    
    			' Open the shortcut property store, set the AppUserModelId property
    			Dim newShortcutProperties As IPropertyStore = DirectCast(newShortcut, IPropertyStore)
    
    			Using appId As New PropVariant(APP_ID)
    				ShellHelpers.ErrorHelper.VerifySucceeded(newShortcutProperties.SetValue(SystemProperties.System.AppUserModel.ID, appId))
    				ShellHelpers.ErrorHelper.VerifySucceeded(newShortcutProperties.Commit())
    			End Using
    
    			' Commit the shortcut to disk
    			Dim newShortcutSave As IPersistFile = DirectCast(newShortcut, IPersistFile)
    
    			ShellHelpers.ErrorHelper.VerifySucceeded(newShortcutSave.Save(shortcutPath, True))
    		End Sub
    
    		' Create and show the toast.
    		' See the "Toasts" sample for more detail on what can be done with toasts
    		Private Sub ShowToastButton_Click(sender As Object, e As RoutedEventArgs)
    
    			' Get a toast XML template
    			Dim toastXml As XmlDocument = ToastNotificationManager.GetTemplateContent(ToastTemplateType.ToastImageAndText04)
    
    			' Fill in the text elements
    			Dim stringElements As XmlNodeList = toastXml.GetElementsByTagName("text")
    			For i As Integer = 0 To stringElements.Length - 1
    				stringElements(i).AppendChild(toastXml.CreateTextNode("Line " + i))
    			Next
    
    			' Specify the absolute path to an image
    			Dim imagePath As [String] = "file:///" + Path.GetFullPath("toastImageAndText.png")
    			Dim imageElements As XmlNodeList = toastXml.GetElementsByTagName("image")
    			imageElements(0).Attributes.GetNamedItem("src").NodeValue = imagePath
    
    			' Create the toast and attach event listeners
    			Dim toast As New ToastNotification(toastXml)
    			AddHandler toast.Activated, AddressOf ToastActivated
    			AddHandler toast.Dismissed, AddressOf ToastDismissed
    			AddHandler toast.Failed, AddressOf ToastFailed
    
    			' Show the toast. Be sure to specify the AppUserModelId on your application's shortcut!
    			ToastNotificationManager.CreateToastNotifier(APP_ID).Show(toast)
    		End Sub
    
    		Private Sub ToastActivated(sender As ToastNotification, e As Object)
    			Dispatcher.Invoke(Function() 
    			Activate()
    			Output.Text = "The user activated the toast."
    
    End Function)
    		End Sub
    
    		Private Sub ToastDismissed(sender As ToastNotification, e As ToastDismissedEventArgs)
    			Dim outputText As [String] = ""
    			Select Case e.Reason
    				Case ToastDismissalReason.ApplicationHidden
    					outputText = "The app hid the toast using ToastNotifier.Hide"
    					Exit Select
    				Case ToastDismissalReason.UserCanceled
    					outputText = "The user dismissed the toast"
    					Exit Select
    				Case ToastDismissalReason.TimedOut
    					outputText = "The toast has timed out"
    					Exit Select
    			End Select
    
    			Dispatcher.Invoke(Function() 
    			Output.Text = outputText
    
    End Function)
    		End Sub
    
    		Private Sub ToastFailed(sender As ToastNotification, e As ToastFailedEventArgs)
    			Dispatcher.Invoke(Function() 
    			Output.Text = "The toast encountered an error."
    
    End Function)
    		End Sub
    	End Class
    End Namespace
    
    '=======================================================
    'Service provided by Telerik (www.telerik.com)
    'Conversion powered by NRefactory.
    'Twitter: @telerik
    'Facebook: facebook.com/telerik
    '=======================================================
    


    La vida loca

    Wednesday, May 20, 2015 9:23 PM
  • Thank you!

    I used your converted code and it worked!, sorta.

    I fixed a few errors and then it worked!

    I use this code for the toast popup;

            ' Get a toast XML template
            Dim toastXml As XmlDocument = ToastNotificationManager.GetTemplateContent(ToastTemplateType.ToastImageAndText04)
    
            ' Fill in the text elements
            Dim stringElements As XmlNodeList = toastXml.GetElementsByTagName("text")
    
    
            stringElements(1).AppendChild(toastXml.CreateTextNode("Roligt "))
    
    
            ' Specify the absolute path to an image
            Dim imagePath As [String] = "file:///" + Path.GetFullPath("Mill2Growth.png")
            Dim imageElements As XmlNodeList = toastXml.GetElementsByTagName("image")
            imageElements(0).Attributes.GetNamedItem("src").NodeValue = imagePath
    
            ' Create the toast and attach event listeners
            Dim toast As New ToastNotification(toastXml)
    
            ' Show the toast. Be sure to specify the AppUserModelId on your application's shortcut!
            ToastNotificationManager.CreateToastNotifier(APP_ID).Show(toast)

    This to assign the id thing;

        ' In order to display toasts, a desktop application must have a shortcut on the Start menu.
        ' Also, an AppUserModelID must be set on that shortcut.
        ' The shortcut should be created as part of the installer. The following code shows how to create
        ' a shortcut and assign an AppUserModelID using Windows APIs. You must download and include the 
        ' Windows API Code Pack for Microsoft .NET Framework for this code to function
        '
        ' Included in this project is a wxs file that be used with the WiX toolkit
        ' to make an installer that creates the necessary shortcut. One or the other should be used.
        Private Function TryCreateShortcut() As Boolean
            Dim shortcutPath As [String] = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + "\Microsoft\Windows\Start Menu\Programs\Desktop Toasts Sample CS.lnk"
            If Not File.Exists(shortcutPath) Then
                InstallShortcut(shortcutPath)
                Return True
            End If
            Return False
        End Function
    
        Private Sub InstallShortcut(shortcutPath As [String])
            ' Find the path to the current executable
            Dim exePath As [String] = Process.GetCurrentProcess().MainModule.FileName
            Dim newShortcut As DesktopToastsSample.ShellHelpers.IShellLinkW = DirectCast(New CShellLink(), IShellLinkW)
    
            ' Create a shortcut to the exe
            DesktopToastsSample.ShellHelpers.ErrorHelper.VerifySucceeded(newShortcut.SetPath(exePath))
            DesktopToastsSample.ShellHelpers.ErrorHelper.VerifySucceeded(newShortcut.SetArguments(""))
    
            ' Open the shortcut property store, set the AppUserModelId property
            Dim newShortcutProperties As IPropertyStore = DirectCast(newShortcut, IPropertyStore)
    
            Using appId As New PropVariant(APP_ID)
                DesktopToastsSample.ShellHelpers.ErrorHelper.VerifySucceeded(newShortcutProperties.SetValue(SystemProperties.System.AppUserModel.ID, appId))
                DesktopToastsSample.ShellHelpers.ErrorHelper.VerifySucceeded(newShortcutProperties.Commit())
            End Using
    
            ' Commit the shortcut to disk
            Dim newShortcutSave As IPersistFile = DirectCast(newShortcut, IPersistFile)
    
            DesktopToastsSample.ShellHelpers.ErrorHelper.VerifySucceeded(newShortcutSave.Save(shortcutPath, True))
        End Sub
    
    

    Also made a class called "ShellHelpers" that includes followning code;

    Imports System.Runtime.InteropServices
    Imports System.Text
    Imports Microsoft.WindowsAPICodePack.Shell.PropertySystem
    Imports MS.WindowsAPICodePack.Internal
    
    Namespace DesktopToastsSample.ShellHelpers
        Friend Enum STGM As Long
            STGM_READ = &H0L
            STGM_WRITE = &H1L
            STGM_READWRITE = &H2L
            STGM_SHARE_DENY_NONE = &H40L
            STGM_SHARE_DENY_READ = &H30L
            STGM_SHARE_DENY_WRITE = &H20L
            STGM_SHARE_EXCLUSIVE = &H10L
            STGM_PRIORITY = &H40000L
            STGM_CREATE = &H1000L
            STGM_CONVERT = &H20000L
            STGM_FAILIFTHERE = &H0L
            STGM_DIRECT = &H0L
            STGM_TRANSACTED = &H10000L
            STGM_NOSCRATCH = &H100000L
            STGM_NOSNAPSHOT = &H200000L
            STGM_SIMPLE = &H8000000L
            STGM_DIRECT_SWMR = &H400000L
            STGM_DELETEONRELEASE = &H4000000L
        End Enum
    
        Friend NotInheritable Class ShellIIDGuid
            Private Sub New()
            End Sub
            Friend Const IShellLinkW As String = "000214F9-0000-0000-C000-000000000046"
            Friend Const CShellLink As String = "00021401-0000-0000-C000-000000000046"
            Friend Const IPersistFile As String = "0000010b-0000-0000-C000-000000000046"
            Friend Const IPropertyStore As String = "886D8EEB-8CF2-4446-8D02-CDBA1DBDCF99"
        End Class
    
        <ComImport, Guid(ShellIIDGuid.IShellLinkW), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)> _
        Friend Interface IShellLinkW
            'ref _WIN32_FIND_DATAW pfd,
            Function GetPath(<Out, MarshalAs(UnmanagedType.LPWStr)> pszFile As StringBuilder, cchMaxPath As Integer, pfd As IntPtr, fFlags As UInteger) As UInt32
            Function GetIDList(ByRef ppidl As IntPtr) As UInt32
            Function SetIDList(pidl As IntPtr) As UInt32
            Function GetDescription(<Out, MarshalAs(UnmanagedType.LPWStr)> pszFile As StringBuilder, cchMaxName As Integer) As UInt32
            Function SetDescription(<MarshalAs(UnmanagedType.LPWStr)> pszName As String) As UInt32
            Function GetWorkingDirectory(<Out, MarshalAs(UnmanagedType.LPWStr)> pszDir As StringBuilder, cchMaxPath As Integer) As UInt32
            Function SetWorkingDirectory(<MarshalAs(UnmanagedType.LPWStr)> pszDir As String) As UInt32
            Function GetArguments(<Out, MarshalAs(UnmanagedType.LPWStr)> pszArgs As StringBuilder, cchMaxPath As Integer) As UInt32
            Function SetArguments(<MarshalAs(UnmanagedType.LPWStr)> pszArgs As String) As UInt32
            Function GetHotKey(ByRef wHotKey As Short) As UInt32
            Function SetHotKey(wHotKey As Short) As UInt32
            Function GetShowCmd(ByRef iShowCmd As UInteger) As UInt32
            Function SetShowCmd(iShowCmd As UInteger) As UInt32
            Function GetIconLocation(<Out, MarshalAs(UnmanagedType.LPWStr)> ByRef pszIconPath As StringBuilder, cchIconPath As Integer, ByRef iIcon As Integer) As UInt32
            Function SetIconLocation(<MarshalAs(UnmanagedType.LPWStr)> pszIconPath As String, iIcon As Integer) As UInt32
            Function SetRelativePath(<MarshalAs(UnmanagedType.LPWStr)> pszPathRel As String, dwReserved As UInteger) As UInt32
            Function Resolve(hwnd As IntPtr, fFlags As UInteger) As UInt32
            Function SetPath(<MarshalAs(UnmanagedType.LPWStr)> pszFile As String) As UInt32
        End Interface
    
        <ComImport, Guid(ShellIIDGuid.IPersistFile), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)> _
        Friend Interface IPersistFile
            Function GetCurFile(<Out, MarshalAs(UnmanagedType.LPWStr)> pszFile As StringBuilder) As UInt32
            Function IsDirty() As UInt32
            Function Load(<MarshalAs(UnmanagedType.LPWStr)> pszFileName As String, <MarshalAs(UnmanagedType.U4)> dwMode As STGM) As UInt32
            Function Save(<MarshalAs(UnmanagedType.LPWStr)> pszFileName As String, fRemember As Boolean) As UInt32
            Function SaveCompleted(<MarshalAs(UnmanagedType.LPWStr)> pszFileName As String) As UInt32
        End Interface
        <ComImport> _
        <Guid(ShellIIDGuid.IPropertyStore)> _
        <InterfaceType(ComInterfaceType.InterfaceIsIUnknown)> _
        Interface IPropertyStore
            Function GetCount(<Out> ByRef propertyCount As UInteger) As UInt32
            Function GetAt(<[In]> propertyIndex As UInteger, ByRef key As PropertyKey) As UInt32
            Function GetValue(<[In]> ByRef key As PropertyKey, <Out> pv As PropVariant) As UInt32
            Function SetValue(<[In]> ByRef key As PropertyKey, <[In]> pv As PropVariant) As UInt32
            Function Commit() As UInt32
        End Interface
    
    
        <ComImport, Guid(ShellIIDGuid.CShellLink), ClassInterface(ClassInterfaceType.None)> _
        Friend Class CShellLink
        End Class
    
        Public NotInheritable Class ErrorHelper
            Private Sub New()
            End Sub
            Public Shared Sub VerifySucceeded(hresult As UInt32)
                If hresult > 1 Then
                    Throw New Exception("Failed with HRESULT: " + hresult.ToString("X"))
                End If
            End Sub
        End Class
    End Namespace
    
    

    So that's it, but just one qustion. I have set the targeted OS to Win 8, i suppose then that i can't run the app on a Win 7 platform. I would like the program to identify which operating system version it is and then decide if it's gonna use the toast function. Now i suppose i have to make two seperate versions of the software for Win 7 and Win 8. Anyone have a clue how to solve that?

    • Proposed as answer by Fouad Roumieh Thursday, May 21, 2015 2:51 PM
    Thursday, May 21, 2015 11:43 AM
  • Make two separate versions. One for Win 8 and above and one for less than Win 8.

    Have the installer detect if the OS is Win 8 or greater or less than Win 8. Then have it install whichever app is for what OS. That will require learning the installer to some detail.

    If anything answered your question then please propose it as an answer.


    La vida loca

    Thursday, May 21, 2015 2:03 PM
  • Thank you, i will try to make it.
    Thursday, May 21, 2015 2:48 PM
  • I just looked to see if an installer can detect which OS and then install an appropriate app. I don't believe that is possible.

    Most likely for installing from CD or DVD you can use an AutorRun.INF file using Notepad and save it as type All Files with an extension of .Inf which would need to be placed in the root directory of the CD or DVD. Then have it launch a 32 bit .exe you will need to create which detects the OS on the system and whether the system perhaps is 32 or 64 bit (as apps compiled to AnyCPU (and x64 of course) on 64 bit systems are 64 bit apps to my knowledge). Then you may need 4 revs of the app, one compiled to x86 for 32 bit systems less than Win 8, one compiled to AnyCPU (when compiled on x64 systems) for 64 bit systems less than Win 8, and the same for greater than or equal to Win 8 which I suppose comes in 32 bit versions also.

    Then when that app detects what the system is you will have 4 MSI's with 4 different names that the app can execute via Case or If statements using Process.Start.

    For a memory stick install you would just launch your detection app manually I suppose.

    For a web install, if customers accessed the internet to install the app or something, I've seen websites detect what my PC OS/bit level is but don't know how that works.


    La vida loca

    Thursday, May 21, 2015 4:02 PM