private static void FixTrayDataAnyCPU(ref Native.SysTrayData trayData)
 {
     if (!Is64Bits())
     {
         trayData.nMsg   = (uint)trayData.wParam;
         trayData.wParam = trayData.uID;
     }
 }
        /// <summary>
        /// Double click on notification icon
        /// </summary>
        public static void DefaultAction(Native.SysTrayData trayData)
        {
            int y   = Cursor.Position.Y;
            int x   = Cursor.Position.X;
            int pos = (y << 16) | x;

            // double click
            Native.SendMessage((IntPtr)(trayData.hwnd), trayData.nMsg, (IntPtr)pos, (IntPtr)((trayData.wParam << 16) | (int)Native.WindowMessage.WM_LBUTTONDBLCLK));
            Native.SendMessage((IntPtr)(trayData.hwnd), trayData.nMsg, (IntPtr)trayData.wParam, (IntPtr)(int)Native.WindowMessage.WM_LBUTTONDBLCLK);
            Native.SendMessage((IntPtr)(trayData.hwnd), trayData.nMsg, (IntPtr)trayData.wParam, (IntPtr)0x200);
        }
        /// <summary>
        /// Right click on notification icon - context menu
        /// </summary>
        public static void RightClickIcon(Native.SysTrayData trayData)
        {
            int y   = Cursor.Position.Y;
            int x   = Cursor.Position.X;
            int pos = (y << 16) | x;

            // context menu
            Native.SendMessage((IntPtr)(trayData.hwnd), trayData.nMsg, (IntPtr)trayData.wParam, (IntPtr)Native.WindowMessage.WM_RBUTTONDOWN);
            Native.SendMessage((IntPtr)(trayData.hwnd), trayData.nMsg, (IntPtr)trayData.wParam, (IntPtr)Native.WindowMessage.WM_RBUTTONUP);
            Native.SendMessage((IntPtr)(trayData.hwnd), trayData.nMsg, (IntPtr)pos, (IntPtr)((trayData.wParam << 16) | 0x7B));
        }
        /// <summary>
        /// Left click on notification icon
        /// </summary>
        public static void LeftClickIcon(Native.SysTrayData trayData)
        {
            int y   = Cursor.Position.Y;
            int x   = Cursor.Position.X;
            int pos = (y << 16) | x;

            Native.SendMessage((IntPtr)(trayData.hwnd), trayData.nMsg, (IntPtr)pos, (IntPtr)((trayData.wParam << 16) | (int)Native.WindowMessage.WM_LBUTTONDOWN));
            Native.SendMessage((IntPtr)(trayData.hwnd), trayData.nMsg, (IntPtr)trayData.wParam, (IntPtr)Native.WindowMessage.WM_LBUTTONDOWN);
            Native.SendMessage((IntPtr)(trayData.hwnd), trayData.nMsg, (IntPtr)trayData.wParam, (IntPtr)Native.WindowMessage.WM_LBUTTONUP);
            Native.SendMessage((IntPtr)(trayData.hwnd), trayData.nMsg, (IntPtr)trayData.wParam, (IntPtr)0x400);
        }
        /// <summary>
        /// Get information about all icons
        /// </summary>
        public static List <NotificationIconInfo> GetVisibleIcons()
        {
            try
            {
                var toolbarWindow = GetUserToolbar();
                var result        = new List <NotificationIconInfo>();
                if (toolbarWindow.Handle == IntPtr.Zero)
                {
                    return(result);
                }

                int count = (int)Native.SendMessage(toolbarWindow.Handle, (uint)Native.WindowMessage.TB_BUTTONCOUNT, IntPtr.Zero, IntPtr.Zero);
                if (count == 0)
                {
                    return(result);
                }

                uint pid;
                Native.GetWindowThreadProcessId(toolbarWindow.Handle, out pid);

                bool   hr;
                IntPtr hproc = IPCNative.OpenProcess(IPCNative.ProcessAccess.AllAccess, false, (int)pid);

                for (int i = 0; i < count; i++)
                {
                    int sizeOfTbButton = Marshal.SizeOf(Is64Bits() ? typeof(Native.TBBUTTON64) : typeof(Native.TBBUTTON32));

                    // Allocate memory for TBBUTTON structure
                    IntPtr pTBBUTTON = IPCNative.VirtualAllocEx(hproc, IntPtr.Zero, (uint)sizeOfTbButton,
                                                                IPCNative.AllocationType.Commit, IPCNative.MemoryProtection.ReadWrite);

                    // Ask explorer.exe to fill the structure we just allocated
                    Native.SendMessage(toolbarWindow.Handle, (uint)Native.WindowMessage.TB_GETBUTTON, new IntPtr(i), pTBBUTTON);

                    // Read the structure from explorer.exe's memory
                    int    read;
                    object obj;
                    if (Is64Bits())
                    {
                        obj = new Native.TBBUTTON64();
                    }
                    else
                    {
                        obj = new Native.TBBUTTON32();
                    }
                    hr = IPCNative.ReadProcessMemory(hproc, pTBBUTTON, obj, sizeOfTbButton, out read);
                    Native.TBBUTTON32 tbbutton = ConvertToTBButton32(obj);

                    hr = IPCNative.VirtualFreeEx(hproc, pTBBUTTON, sizeOfTbButton, IPCNative.FreeType.Decommit | IPCNative.FreeType.Release);

                    // Get data associated with icon
                    IntPtr data = new IntPtr((int)tbbutton.dwData);

                    obj = new Native.SysTrayData();
                    IPCNative.ReadProcessMemory(hproc, data, obj, Marshal.SizeOf(typeof(Native.SysTrayData)), out read);
                    Native.SysTrayData trayData = (Native.SysTrayData)obj;

                    FixTrayDataAnyCPU(ref trayData);

                    if (trayData.wParam < 0)
                    {
                        continue;
                    }

                    // Get tooltip length
                    int size = (int)Native.SendMessage(toolbarWindow.Handle, (uint)Native.WindowMessage.TB_GETBUTTONTEXT, (IntPtr)tbbutton.idCommand, IntPtr.Zero);
                    size *= 2; // because it is unicode

                    // Alloc memory for explorer.exe to write tooltip to
                    IntPtr pText = IPCNative.VirtualAllocEx(hproc, IntPtr.Zero, (uint)size, IPCNative.AllocationType.Commit, IPCNative.MemoryProtection.ReadWrite);
                    Native.SendMessage(toolbarWindow.Handle, (uint)Native.WindowMessage.TB_GETBUTTONTEXT, (IntPtr)tbbutton.idCommand, pText);

                    // Read tooltip from memory
                    byte[] objstr = new byte[size];
                    IPCNative.ReadProcessMemory(hproc, pText, objstr, size, out read);

                    hr = IPCNative.VirtualFreeEx(hproc, pText, size, IPCNative.FreeType.Decommit | IPCNative.FreeType.Release);

                    string tooltip = UnicodeEncoding.Unicode.GetString(objstr);

                    NotificationIconInfo icon = new NotificationIconInfo
                    {
                        BitmapIndex    = tbbutton.iBitmap,
                        DataIdentifier = tbbutton.dwData,
                        Data           = trayData,
                        Tooltip        = tooltip
                    };

                    result.Add(icon);
                }

                hr = IPCNative.CloseHandle(hproc);

                return(result);
            }
            catch (OverflowException)
            {
                return(new List <NotificationIconInfo>());
            }
        }