示例#1
0
 private static bool MouseInNotifyArea()
 {
     return(NotifyArea.GetRectangle().Contains(Cursor.Position));
 }
示例#2
0
        private static Rectangle?GetNotifyIconRectangleLegacy(NotifyIcon notifyIcon, bool returnIfHidden)
        {
            Rectangle?nirect = null;

            NativeMethods.NOTIFYICONIDENTIFIER niidentifier;
            if (!CanGetNotifyIconIdentifier(notifyIcon, out niidentifier))
            {
                return(null);
            }

            // find the handle of the task bar
            IntPtr taskbarparenthandle = NativeMethods.FindWindow("Shell_TrayWnd", null);

            if (taskbarparenthandle == IntPtr.Zero)
            {
                return(null);
            }

            // find the handle of the notification area
            IntPtr naparenthandle = NativeMethods.FindWindowEx(taskbarparenthandle, IntPtr.Zero, "TrayNotifyWnd", null);

            if (naparenthandle == IntPtr.Zero)
            {
                return(null);
            }

            // make a list of toolbars in the notification area (one of them should contain the icon)
            List <IntPtr> natoolbarwindows = NativeMethods.GetChildToolbarWindows(naparenthandle);

            bool found = false;

            for (int i = 0; !found && i < natoolbarwindows.Count; i++)
            {
                IntPtr natoolbarhandle = natoolbarwindows[i];

                // retrieve the number of toolbar buttons (i.e. notify icons)
                int buttoncount = NativeMethods.SendMessage(natoolbarhandle, NativeMethods.TB_BUTTONCOUNT, IntPtr.Zero, IntPtr.Zero).ToInt32();

                // get notification area's process id
                uint naprocessid;
                NativeMethods.GetWindowThreadProcessId(natoolbarhandle, out naprocessid);

                // get handle to notification area's process
                IntPtr naprocesshandle = NativeMethods.OpenProcess(NativeMethods.ProcessAccessFlags.All, false, naprocessid);

                if (naprocesshandle == IntPtr.Zero)
                {
                    return(null);
                }

                // allocate enough memory within the notification area's process to store the button info we want
                IntPtr toolbarmemoryptr = NativeMethods.VirtualAllocEx(naprocesshandle, (IntPtr)null, (uint)Marshal.SizeOf(typeof(NativeMethods.TBBUTTON)), NativeMethods.AllocationType.Commit, NativeMethods.MemoryProtection.ReadWrite);

                if (toolbarmemoryptr == IntPtr.Zero)
                {
                    return(null);
                }

                try
                {
                    // loop through the toolbar's buttons until we find our notify icon
                    for (int j = 0; !found && j < buttoncount; j++)
                    {
                        int bytesread = -1;

                        // ask the notification area to give us information about the current button
                        NativeMethods.SendMessage(natoolbarhandle, NativeMethods.TB_GETBUTTON, new IntPtr(j), toolbarmemoryptr);

                        // retrieve that information from the notification area's process
                        NativeMethods.TBBUTTON buttoninfo = new NativeMethods.TBBUTTON();
                        NativeMethods.ReadProcessMemory(naprocesshandle, toolbarmemoryptr, out buttoninfo, Marshal.SizeOf(buttoninfo), out bytesread);

                        if (bytesread != Marshal.SizeOf(buttoninfo) || buttoninfo.dwData == IntPtr.Zero)
                        {
                            return(null);
                        }

                        // the dwData field contains a pointer to information about the notify icon:
                        // the handle of the notify icon (an 4/8 bytes) and the id of the notify icon (4 bytes)
                        IntPtr niinfopointer = buttoninfo.dwData;

                        // read the notify icon handle
                        IntPtr nihandlenew;
                        NativeMethods.ReadProcessMemory(naprocesshandle, niinfopointer, out nihandlenew, Marshal.SizeOf(typeof(IntPtr)), out bytesread);

                        if (bytesread != Marshal.SizeOf(typeof(IntPtr)))
                        {
                            return(null);
                        }

                        // read the notify icon id
                        uint niidnew;
                        NativeMethods.ReadProcessMemory(naprocesshandle, (IntPtr)((int)niinfopointer + (int)Marshal.SizeOf(typeof(IntPtr))), out niidnew, Marshal.SizeOf(typeof(uint)), out bytesread);

                        if (bytesread != Marshal.SizeOf(typeof(uint)))
                        {
                            return(null);
                        }

                        // if we've found a match
                        if (nihandlenew == niidentifier.hWnd && niidnew == niidentifier.uID)
                        {
                            // check if the button is hidden: if it is, return the rectangle of the 'show hidden icons' button
                            if ((byte)(buttoninfo.fsState & NativeMethods.TBSTATE_HIDDEN) != 0)
                            {
                                if (returnIfHidden)
                                {
                                    nirect = NotifyArea.GetButtonRectangle();
                                }
                                else
                                {
                                    return(null);
                                }
                            }
                            else
                            {
                                NativeMethods.RECT result = new NativeMethods.RECT();

                                // get the relative rectangle of the toolbar button (notify icon)
                                NativeMethods.SendMessage(natoolbarhandle, NativeMethods.TB_GETITEMRECT, new IntPtr(j), toolbarmemoryptr);

                                NativeMethods.ReadProcessMemory(naprocesshandle, toolbarmemoryptr, out result, Marshal.SizeOf(result), out bytesread);

                                if (bytesread != Marshal.SizeOf(result))
                                {
                                    return(null);
                                }

                                // find where the rectangle lies in relation to the screen
                                NativeMethods.MapWindowPoints(natoolbarhandle, (IntPtr)null, ref result, 2);

                                nirect = result;
                            }

                            found = true;
                        }
                    }
                }
                finally
                {
                    // free memory within process
                    NativeMethods.VirtualFreeEx(naprocesshandle, toolbarmemoryptr, 0, NativeMethods.FreeType.Release);

                    // close handle to process
                    NativeMethods.CloseHandle(naprocesshandle);
                }
            }

            return(nirect);
        }
示例#3
0
        private void Init()
        {
            // Does the owner have an icon set?
            if (_owner.Icon == null)
            {
                throw new InvalidOperationException("SuperNotifyIcon: Dropping cannot be initialised without an icon set!");
            }

            // When the mouse is close
            MouseHook.MouseMove += MouseHook_MouseMove;

            // Cancel the drop refreshing below if we do an actual click on the NotifyIcon
            _owner.NotifyIcon.MouseUp += (sender, e) =>
            {
                mouseWasInNotifyArea = false;
            };

            // Refresh the drop position if we click in the notification area on Windows 7; we might've moved an icon!
            if (SysInfo.IsWindows7OrLater)
            {
                MouseHook.MouseDown += (sender, e) =>
                {
                    mouseWasInNotifyArea = MouseInNotifyArea();

                    // Shall we cancel, then?
                    if (e.Button != MouseButtons.Left)
                    {
                        mouseWasInNotifyArea = false;
                    }
                };
                MouseHook.MouseUp += (sender, e) =>
                {
                    if (MouseInNotifyArea() && mouseWasInNotifyArea)
                    {
                        // We should wait for the icon to settle in before doing anything
                        Timer wait = new Timer();
                        wait.Tick += (sender2, e2) =>
                        {
                            if (mouseWasInNotifyArea)
                            {
                                ShowDrop();
                            }
                            mouseWasInNotifyArea = false;
                            wait.Dispose();
                        };
                        wait.Interval = 200;
                        wait.Start();
                    }
                };
            }

            // Refresh the drop position if the size of the notification area changes
            Size  notifyAreaLastSize = NotifyArea.GetRectangle().Size;
            Timer notifyAreaTimer    = new Timer();

            notifyAreaTimer.Tick += (sender, e) =>
            {
                if (NotifyArea.GetRectangle().Size != notifyAreaLastSize)
                {
                    notifyAreaLastSize = NotifyArea.GetRectangle().Size;
                    ShowDrop();
                }
            };
            notifyAreaTimer.Interval = 1000;
            notifyAreaTimer.Start();

            // Is the drop even in the right place at all?
            int   unsuccessfulRefreshes = 0;
            Timer dropPlaceTimer        = new Timer();

            dropPlaceTimer.Tick += (sender, e) =>
            {
                if (!NotifyArea.GetRectangle().Contains(new Point(this.Location.X + 2, this.Location.Y + 2)))
                {
                    ShowDrop();
                    unsuccessfulRefreshes++;

                    // Don't keep refreshing every second if we can't find our icon!
                    if (unsuccessfulRefreshes >= 3)
                    {
                        dropPlaceTimer.Interval = unsuccessfulRefreshes * 1000;
                    }
                }
                else
                {
                    unsuccessfulRefreshes   = 0;
                    dropPlaceTimer.Interval = 1000;
                }
            };
            dropPlaceTimer.Interval = 1000;
            dropPlaceTimer.Start();

            // Okay... still no success? Let's fall back to the mouse timer...
            //// TODO: See whether this should only be run on WinXP/Vista systems and whether this should
            //// run even if we have a valid drop position
            MouseHoldTimed mouseHold = new MouseHoldTimed(500);

            mouseHold.MouseDown += (sender, e) =>
            {
                if (e.Button != MouseButtons.Left || OwnApplicationActive() || !lastNotifyIconPoint.HasValue)
                {
                    mouseHold.Cancel();
                }
            };
            mouseHold.MouseHoldTimeout += (sender, e) =>
            {
                if (lastNotifyIconPoint.HasValue)
                {
                    ShowDrop();
                }
            };
        }