# .NET and More > WPF, WCF, WF >  [RESOLVED] NotifyIcon and ContextMenu without using System.Windows.Forms

## dee-u

What is the alternative to use without using System.Windows.Forms?

TIA

----------


## RobDog888

Shell_NotifyIcon APIs? I dont have my laptop with me so no .net

----------


## dee-u

So it will be okay to use the old VB6.0 Shell_NotifyIcon for it?

----------


## RobDog888

As windows have handles like forms then I dont see why not.

----------


## chris128

http://www.hardcodet.net/projects/wpf-notifyicon

----------


## RobDog888

> http://www.hardcodet.net/projects/wpf-notifyicon


Awesome Chris!  :Thumb:

----------


## dee-u

> http://www.hardcodet.net/projects/wpf-notifyicon


I have actually seen that and tried it before starting a thread but somehow for this simple requirement I can just opt for the System.Windows.Forms equivalent rather than trying to understand how that code can be applied to my project. Somehow the contextmenu implementation is not perfect so I would prefer the System.Windows.Forms.

Is there any problems at all if I will reference System.Windows.Forms in WPF?

----------


## dee-u

In lieu of using System.Windows.Forms I have come up with the following class which uses API for the NotifyIcon and Balloon. You can get the source code in this WPF-based chatting system.


csharp Code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
using System.Windows.Media;
using System.Drawing;
using System.Windows.Interop;
using System.Windows;
 namespace NetVerser
{
    public static class Notify
    {
        private static WindowHwndSource source;        
        private const int NIM_ADD = 0;
        private const int NIM_MODIFY = 1;
        private const int NIM_DELETE = 2;
        //messages to trap
        public const int PK_TRAYICON = 1025;
        public const int RButtonUp = 0x0205;
        public const int NIN_BALLOONUSERCLICK = 1029;
        public const int WM_LBUTTONDBLCLK = 515;
         [Flags]
        public enum NotifyIconFlags
        {
            // The hIcon member is valid.
            Icon = 2,
            // The uCallbackMessage member is valid.
            Message = 1,
            // The szTip member is valid.
            ToolTip = 4,
            // The dwState and dwStateMask members are valid.
            State = 8,
            // Use a balloon ToolTip instead of a standard ToolTip. The szInfo, uTimeout, szInfoTitle, and dwInfoFlags members are valid.
            Balloon = 0x10,
        }
         public enum NotifyBalloonIcon
        {
            // No icon.
            None,
            // An information icon.
            Info,
            // A warning icon.
            Warning,
            // An error icon.
            Error,
        }
         [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
        public class NOTIFYICONDATA
        {
            public int cbSize = Marshal.SizeOf(typeof(NOTIFYICONDATA));
            public IntPtr hWnd;
            public int uID;
            public int uFlags;
            public int uCallbackMessage;
            public IntPtr hIcon;
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 0x80)]
            public string szTip;
            public int dwState;
            public int dwStateMask;
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 0x100)]
            public string szInfo;
            public int uTimeoutOrVersion;
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 0x40)]
            public string szInfoTitle;
            public int dwInfoFlags;
        }
        
        [DllImport("shell32", CharSet = CharSet.Auto)]
        public static extern int Shell_NotifyIcon(int message, NOTIFYICONDATA pnid);
         public static IntPtr AddToTray(Window window, string stringTip)
        {
            //hook window
            source = new WindowHwndSource((winChat)window);    
        
            //get icon
            Icon icon = new System.Drawing.Icon(global::NetVerser.Properties.Resources.Comment, 16, 16);
             //uID is the same uID used in ShowBallon
            NOTIFYICONDATA pnid = new NOTIFYICONDATA
            {
                hWnd = source.Handle,
                uID = 999,
                uFlags = (int)NotifyIconFlags.Message | (int)NotifyIconFlags.ToolTip | (int)NotifyIconFlags.Icon,
                uCallbackMessage = PK_TRAYICON,
                szTip = stringTip,
                hIcon = (IntPtr)icon.Handle,
            };
            //add icon
            Shell_NotifyIcon(NIM_ADD, pnid);
             //return source handle to be used in SetForegroundWindow
            return source.Handle;
        }
         public static void RemoveFromTray()
        {
            NOTIFYICONDATA pnid = new NOTIFYICONDATA
            {
                hWnd = source.Handle,
                uID = 999
            };
            //remove icon from tray
            Shell_NotifyIcon(NIM_DELETE, pnid);
        }
         public static IntPtr ShowBallon(int timeout, string stringTip, string tipTitle, string tipText, NotifyBalloonIcon tipIcon)
        {
            //get icon
            Icon icon = new System.Drawing.Icon(global::NetVerser.Properties.Resources.Comment, 16, 16);
            //uID is the same uID used in AddToTray 
            NOTIFYICONDATA pnid = new NOTIFYICONDATA
            {
                hWnd = source.Handle,
                uID = 999,
                uFlags = (int)NotifyIconFlags.Balloon | (int)NotifyIconFlags.Message | (int)NotifyIconFlags.ToolTip | (int)NotifyIconFlags.Icon,
                uTimeoutOrVersion = timeout,
                szInfoTitle = tipTitle,
                szInfo = tipText,
                dwInfoFlags = (int)tipIcon,
                hIcon = (IntPtr)icon.Handle,
                uCallbackMessage = PK_TRAYICON,
                szTip = stringTip,
            };
            //modify icon
            Shell_NotifyIcon(NIM_MODIFY, pnid);
            //return source handle to be used in SetForegroundWindow
            return source.Handle;
        }
    }
     //this is to hook WPF window messages
    public class WindowHwndSource : HwndSource
    {
        [DllImport("user32", CharSet = CharSet.Auto)]
        public static extern bool PostMessage(HandleRef hwnd, int msg, IntPtr wparam, IntPtr lparam);
         private winChat _reference;
        private const int Close = 0x10;
         internal WindowHwndSource(winChat component) : base(0, 0, 0, 0, 0, null, IntPtr.Zero)
        {
            _reference = component;
            AddHook(_reference.WndProc);
        }
         ~WindowHwndSource()
        {
            if (Handle != IntPtr.Zero)
            {
                PostMessage(new HandleRef(this, Handle), Close, IntPtr.Zero, IntPtr.Zero);
            }
        }
    }
}

----------


## chris128

but thats exactly what that link that I posted originally does isnt it?

----------


## dee-u

I did not check thoroughly but I have seen it uses the same API but I did not look how they have implemented it, and it is not up to my liking, for example when you press Escape while the context menu is shown then it will not go away.

----------

