Q:

How to show images in Windows balloon notifications?

Is it possible to display custom image/icon in Windows balloon notification? The NotifyIcon control in .net framework supports balloon notifications but it only allows default icons like info, error etc. 
If NotifyIcon does not support this, is there another API .net framework that allows notifications with custom images?

A:

Found an answer. Windows API supports custom icons but the managed .net interface is quite bare bones. Win32 api Shell_NotifyIcon accepts a NOTIFYICONDATA structure. This structure has fields to set custom icon.
    public enum NotifyFlags
    {
        NIF_MESSAGE = 0x01, NIF_ICON = 0x02, NIF_TIP = 0x04, NIF_INFO = 0x10, NIF_STATE = 0x08,
        NIF_GUID = 0x20, NIF_SHOWTIP = 0x80, NIF_REALTIME = 0x40,
    }

    public enum NotifyCommand { NIM_ADD = 0x0, NIM_DELETE = 0x2, NIM_MODIFY = 0x1, NIM_SETVERSION = 0x4 }

    [StructLayout(LayoutKind.Sequential)]
    public struct NOTIFYICONDATA
    {
        public Int32 cbSize;
        public IntPtr hWnd;
        public Int32 uID;
        public NotifyFlags uFlags;
        public Int32 uCallbackMessage;
        public IntPtr hIcon;
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)]
        public String szTip;
        public Int32 dwState;
        public Int32 dwStateMask;
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
        public String szInfo;
        public Int32 uVersion;
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 64)]
        public String szInfoTitle;
        public Int32 dwInfoFlags;
        public Guid guidItem; //> IE 6
        public IntPtr hBalloonIcon;
    }

    [DllImport("shell32.dll")]
    public static extern System.Int32 Shell_NotifyIcon(NotifyCommand cmd, ref NOTIFYICONDATA data);

    private void AddBalloon(string title, string message, Image image)
    {
        NOTIFYICONDATA data = new NOTIFYICONDATA();

        data.cbSize = Marshal.SizeOf(data);
        data.uID = 0x01;
        data.hWnd = Handle;
        data.dwInfoFlags = NIIF_USER;
        data.hIcon = Icon.Handle;
        data.hBalloonIcon = IntPtr.Zero;
        if (message.Image != null)
        {
            data.hBalloonIcon = ((Bitmap)image).GetHicon();
            data.dwInfoFlags |= NIIF_LARGE_ICON;
        }
        data.szInfo = message;
        data.szInfoTitle = title;

        data.uFlags = NotifyFlags.NIF_INFO | NotifyFlags.NIF_SHOWTIP | NotifyFlags.NIF_REALTIME;

        Shell_NotifyIcon(NotifyCommand.NIM_MODIFY, ref data) != 1);
    }

