[WPF – NET 7.0] – NotifyIcon de Windows Form en un formualrio WPF

Descripción general:

Programa de pruebas sobre como se usa el control NotifyIcon de Windows Form en un formulario WPF con NET 7.0

El código que se expone a continuación corresponde a un formulario WPF y soluciona los problemas de integración que existen con el nuevo NET 7.0, esta muy documentado para que sea auto explicativo

Una advertencia

Esta pagina la he escrito para tener un recuerdo de como se emplea este control y resuelve un problema mío. Si a ti también te sirve de ayuda me alegrare.

¡¡¡ Atención !!!

He tenido problemas para incluir el icono del control. Al final lo he solucionado incluyendo el icono como un recurso y llamándolo desde el código


↑↑↑

Código XAML


<Window  x:Class="WindowPruebaNotifyIcon1"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        mc:Ignorable="d"
        Title="Window Prueba NotifyIcon" Height="150" Width="200">
    <Grid>
        <Button  x:Name="ButtonTerminar" Content="Terminar" 
                HorizontalAlignment="Left"  VerticalAlignment="Top" 
                Margin="65,54,0,0" 
                Click="ButtonTerminar_Click"/>
    </Grid>
</Window>


↑↑↑

Código Visual Basic


' ------------------------------------------------- 
Option Explicit On 
Option Strict On 
Option Infer Off 
Option Compare Binary 

Public Class WindowPruebaNotifyIcon1 

    ''' <summary> 
    ''' Al crearse el formulario también hay que crear 
    ''' el notifyIcon y los menus contextuales 
    ''' </summary> 
    Public Sub New() 
        Call InitializeComponent() 
        Call AccionInicializarNotifyIcon() 
    End Sub 

    ''' <summary> 
    ''' Evento [Click] del botón terminar 
    ''' </summary> 
    Private Sub ButtonTerminar_Click(sender As Object, e As RoutedEventArgs) 
        Call AccionCerrarFormulario() 
    End Sub 

    ''' <summary> 
    ''' Al terminar la ejecución del programa 
    ''' hay que destruir los objetos creados 
    ''' Esta función que contiene el código necesario para 
    ''' cerrar educadamente el formulario se llama desde 
    ''' varios eventos tanto del formulario como del NotifyIcon 
    ''' </summary> 
    Private Sub AccionCerrarFormulario() 
        Call DisposeNotifyIcon() 
        Me.Close() 
    End Sub 

#Region "NotifyIcon" 

#Region "Objetos NotifyIcon y menu contextual" 

    Private WithEvents NotifyIcon1 As New System.Windows.Forms.NotifyIcon 

    Private WithEvents ContextMenu1 As System.Windows.Forms.ContextMenuStrip = New System.Windows.Forms.ContextMenuStrip 
    Private WithEvents ContextMenu1Mostrar As Windows.Forms.ToolStripMenuItem = New Windows.Forms.ToolStripMenuItem("Mostrar") 
    Private WithEvents ContextMenu1Minimizar As Windows.Forms.ToolStripMenuItem = New Windows.Forms.ToolStripMenuItem("Minimizar") 
    Private WithEvents ContextMenu1Terminar As Windows.Forms.ToolStripMenuItem = New Windows.Forms.ToolStripMenuItem("Cerrar") 
    Private WithEvents ContextMenu1Ayuda As Windows.Forms.ToolStripMenuItem = New Windows.Forms.ToolStripMenuItem("Ayuda") 

#End Region 

#Region "Eventos del NotifyIcon" 

    Private Sub ContextMenu1Mostrar_Click(sender As Object, e As EventArgs) Handles ContextMenu1Mostrar.Click 
        Call AccionMostrarFormulario() 
    End Sub 

    Private Sub ContextMenu1Minimizar_Click(sender As Object, e As EventArgs) Handles ContextMenu1Minimizar.Click 
        Me.WindowState = WindowState.Minimized 
    End Sub 

    Private Sub ContextMenu1Terminar_Click(sender As Object, e As EventArgs) Handles ContextMenu1Terminar.Click 
        Call AccionCerrarFormulario() 
    End Sub 

    Private Sub ContextMenu1Ayuda_Click(sender As Object, e As EventArgs) Handles ContextMenu1Ayuda.Click 
        Call AccionCerrarFormulario() 
    End Sub 

    Private Sub NotifyIcon1_DoubleClick(sender As Object, e As EventArgs) Handles NotifyIcon1.MouseDoubleClick 
        Call AccionMostrarFormulario() 
    End Sub 
#End Region 

    ''' <summary> 
    ''' Pasos a dar para mostrar el formulario 
    ''' </summary> 
    Private Sub AccionMostrarFormulario() 
        ' Set the WindowState to normal if the form is minimized. 
        If (Me.WindowState = WindowState.Minimized) Then 
            Me.WindowState = WindowState.Normal 
        End If 

        ' Activate the form. 
        Me.Activate() 
    End Sub 

    ''' <summary> 
    ''' Crea el objeto NotifyIcon y carga sus propiedades 
    ''' </summary> 
    Private Sub AccionInicializarNotifyIcon() 
        '----------------------------------- 

        ' el notify Icon 
        NotifyIcon1 = New System.Windows.Forms.NotifyIcon 

        '----------------------------------------------------------- 
        ' El asunto de la carga del icono de la barra de tareas 
        Try 

            '----------------------------------------------------------------- 
            ' Funciona [1] 
            ' Escribiendo directamente la ruta del fichero 
            'NotifyIcon1.Icon = New System.Drawing.Icon("D:\NET\Version2023Net70\Pruebas\WpfAppPruebaNotifyIcon\WpfAppPruebaNotifyIcon\Resources\Stopwatch.ico") 

            '----------------------------------------------------------------- 
            ' Funciona [2] 
            ' Copiando un fichero en el directorio donde esta el ejecutable 
            ' y luego montando su ruta 
            ' 
            'Dim RutaEnsablado As String 
            'Using WAI As New Util.Ensamblado.WapperFileEnsambladoInfo 
            '    RutaEnsablado = WAI.EnsambladoSoloRuta 
            'End Using 
            ' 
            'Dim rutaIcono As String 
            'rutaIcono = System.IO.Path.Combine(RutaEnsablado, "Resources") 
            'rutaIcono = System.IO.Path.Combine(rutaIcono, "Stopwatch.ico") 
            ' 
            'If System.IO.File.Exists(rutaIcono) = False Then 
            '    Throw New System.IO.FileNotFoundException("El fichero icono no se encuentra") 
            'End If 
            'NotifyIcon1.Icon = New System.Drawing.Icon(rutaIcono) 
            '----------------------------------------------------------------- 

            '----------------------------------------------------------------- 
            ' Funciona [3] 
            ' Incluyendo el icono en el archivo de recursos 
            ' y leyéndolo de recursos 
            ' 
            Dim newIcon1 As System.Drawing.Icon = My.Resources.Resource1.Stopwatch 
            NotifyIcon1.Icon = newIcon1 

        Catch ex As Exception 
            ' la aplicación no puede lanzarse porque no se vera el icono y no sera accesible 
            Dim TextoDelError As String 
            Using sw As New System.IO.StringWriter 
                sw.WriteLine("PROBLEMA") 
                sw.WriteLine("No puedo acceder (cargar) el icono de la aplicación") 
                sw.WriteLine("La aplicación no puede lanzarse porque") 
                sw.WriteLine("No se puede cargar el icono, o lo que es lo mismo,") 
                sw.WriteLine("el icono no se mostrara en la barra de tareas") 
                sw.WriteLine("Y la aplicación no sera accesible") 
                sw.WriteLine("------------------") 
                sw.WriteLine(ex.Message) 
                sw.WriteLine("------------------") 
                sw.WriteLine("SOLUCIÓN") 
                sw.WriteLine("Se carga el icono [SystemIcons.Exclamation] del sistema") 
                sw.WriteLine("------------------") 

                TextoDelError = sw.ToString 
            End Using 
            ' avisar de lo que pasa 
            MessageBox.Show(TextoDelError) 

            ' cargar un icono del sistema 
            Dim icon2 As New System.Drawing.Icon(System.Drawing.SystemIcons.Exclamation, 40, 40) 
            NotifyIcon1.Icon = icon2 

            ' Alternativamente disparar un error 
            'Throw New System.IO.FileNotFoundException(TextoDelError, ex) 
        End Try 

        '----------------------------------------------------------- 
        ' El Balloon del inicio cuando se muestra por primera vez el form 
        Dim NombreEnsamblado As String 
        Using WAI As New Util.Ensamblado.WapperFileEnsambladoInfo 
            NombreEnsamblado = WAI.EnsambladoSoloNombreSinExtension 
        End Using 
        NotifyIcon1.BalloonTipTitle = String.Format("[{0}]e", NombreEnsamblado) 
        NotifyIcon1.BalloonTipText = "La Aplicación está ejecutándose" 
        NotifyIcon1.BalloonTipIcon = System.Windows.Forms.ToolTipIcon.Info 

        '----------------------------------------------------------- 
        ' El texto ToolTip 
        Using sw As New System.IO.StringWriter 
            sw.WriteLine("[Botón derecho del ratón] abre el menú contextual") 
            sw.WriteLine("[Doble Clic] para mostrar el formulario") 
            NotifyIcon1.Text = sw.ToString 
        End Using 

        '----------------------------------------------------------- 
        ' Marcar que el icono (el control) notify Icon se muestra, en la barra de tareas 
        NotifyIcon1.Visible = True 

        '----------------------------------------------------------- 
        ' Montar el contextMenu del control 
        ContextMenu1.Items.Add(ContextMenu1Mostrar) 
        ContextMenu1.Items.Add(ContextMenu1Minimizar) 
        ContextMenu1.Items.Add(ContextMenu1Terminar) 
        ContextMenu1.Items.Add(ContextMenu1Ayuda) 

        NotifyIcon1.ContextMenuStrip = ContextMenu1 

        '------------------- 
        ' Mostrar un aviso de que NotifyIcon esta funcionando 
        Me.WindowState = WindowState.Minimized 
        NotifyIcon1.ShowBalloonTip(50) 
    End Sub 

    ''' <summary> 
    ''' Destruir los objetos utilizados 
    ''' </summary> 
    Private Sub DisposeNotifyIcon() 

        If ContextMenu1Mostrar IsNot Nothing Then 
            ContextMenu1Mostrar = Nothing 
        End If 
        If ContextMenu1Minimizar IsNot Nothing Then 
            ContextMenu1Minimizar = Nothing 
        End If 
        If ContextMenu1Terminar IsNot Nothing Then 
            ContextMenu1Terminar = Nothing 
        End If 
        If ContextMenu1Ayuda IsNot Nothing Then 
            ContextMenu1Ayuda = Nothing 
        End If 

        If ContextMenu1 IsNot Nothing Then 
            ContextMenu1 = Nothing 
        End If 

        If NotifyIcon1 IsNot Nothing Then 
            NotifyIcon1 = Nothing 
        End If 
    End Sub 

#End Region 

End Class