예제 #1
0
        public void GetLocationPrepare()
        {
            // Get a screenshot of the notification area...
            Rectangle notifyAreaRect = NotifyArea.GetRectangle();
            Size      notifyAreaSize = notifyAreaRect.Size;

            using (Bitmap notifyAreaBitmap = GetNotifyAreaScreenshot())
            {
                // Something gone wrong? Give up.
                if (notifyAreaBitmap == null)
                {
                    return;
                }

                // Determine a good spot...
                if (notifyAreaSize.Width > notifyAreaSize.Height)
                {
                    nearColor = notifyAreaBitmap.GetPixel(notifyAreaSize.Width - 3, notifyAreaSize.Height / 2);
                }
                else
                {
                    nearColor = notifyAreaBitmap.GetPixel(notifyAreaSize.Width / 2, notifyAreaSize.Height - 3);
                }

                // And now we have our base colour!
                nearColorSet = true;
            }
        }
예제 #2
0
        private static Bitmap GetNotifyAreaScreenshot()
        {
            Rectangle notifyAreaRect   = NotifyArea.GetRectangle();
            Bitmap    notifyAreaBitmap = new Bitmap(notifyAreaRect.Width, notifyAreaRect.Height);

            using (Graphics notifyAreaGraphics = Graphics.FromImage(notifyAreaBitmap))
            {
                try
                {
                    notifyAreaGraphics.CopyFromScreen(notifyAreaRect.X, notifyAreaRect.Y, 0, 0, notifyAreaRect.Size);
                }
                catch (System.ComponentModel.Win32Exception)
                {
                    return(null);
                }
            }
            return(notifyAreaBitmap);
        }
예제 #3
0
        /// <summary>
        /// Returns the optimum window position in relation to the specified notify icon.
        /// </summary>
        /// <param name="notifyicon">The notify icon that the window should be aligned to.</param>
        /// <param name="windowwidth">The width of the window.</param>
        /// <param name="windowheight">The height of the window.</param>
        /// <param name="dpi">The system's DPI (in relative units: 1.0 = 96 DPI, 1.25 = 120 DPI, etc.).</param>
        /// <param name="pinned">Whether the window is pinned open or not. Affects positioning in Windows 7 only.</param>
        /// <returns>A Point specifying the suggested location of the window (top left point).</returns>
        public static Point GetWindowPosition(NotifyIcon notifyicon, double windowwidth, double windowheight, double dpi, bool pinned)
        {
            // retrieve taskbar rect
            Rectangle taskbarRectangle = Taskbar.GetTaskbarRectangle();

            // retrieve notify icon location
            Rectangle nipositiontemp = NotifyIconHelpers.GetNotifyIconRectangle(notifyicon, true);

            // if our functions can't find the rectangle, align it to a corner of the screen
            Rectangle niposition;

            if (nipositiontemp == Rectangle.Empty)
            {
                switch (Taskbar.GetTaskbarEdge())
                {
                case Taskbar.TaskbarEdge.Bottom:     // bottom right corner
                    niposition = new Rectangle(taskbarRectangle.Right - 1, taskbarRectangle.Bottom - 1, 1, 1);
                    break;

                case Taskbar.TaskbarEdge.Top:     // top right corner
                    niposition = new Rectangle(taskbarRectangle.Right - 1, taskbarRectangle.Top, 1, 1);
                    break;

                case Taskbar.TaskbarEdge.Right:     // bottom right corner
                    niposition = new Rectangle(taskbarRectangle.Right - 1, taskbarRectangle.Bottom - 1, 1, 1);
                    break;

                case Taskbar.TaskbarEdge.Left:     // bottom left corner
                    niposition = new Rectangle(taskbarRectangle.Left, taskbarRectangle.Bottom - 1, 1, 1);
                    break;

                default:
                    goto case Taskbar.TaskbarEdge.Bottom;
                }
            }
            else
            {
                niposition = (Rectangle)nipositiontemp;
            }

            // check if notify icon is in the fly-out
            bool inflyout = NotifyIconHelpers.IsRectangleInFlyOut(niposition);

            // if the window is pinned open and in the fly-out (Windows 7 only),
            // we should position the window above the 'show hidden icons' button
            if (inflyout && pinned)
            {
                niposition = (Rectangle)NotifyArea.GetButtonRectangle();
            }

            // determine centre of notify icon
            Point nicentre = new Point(niposition.Left + (niposition.Width / 2), niposition.Top + (niposition.Height / 2));

            // get window offset from edge
            double edgeoffset = WindowEdgeOffset * dpi;

            // get working area bounds
            Rectangle workarea = GetWorkingArea(niposition);

            // calculate window position
            double windowleft = 0, windowtop = 0;

            switch (Taskbar.GetTaskbarEdge())
            {
            case Taskbar.TaskbarEdge.Bottom:
                // horizontally centre above icon
                windowleft = nicentre.X - (windowwidth / 2);
                if (inflyout)
                {
                    windowtop = niposition.Top - windowheight - edgeoffset;
                }
                else
                {
                    windowtop = taskbarRectangle.Top - windowheight - edgeoffset;
                }

                break;

            case Taskbar.TaskbarEdge.Top:
                // horizontally centre below icon
                windowleft = nicentre.X - (windowwidth / 2);
                if (inflyout)
                {
                    windowtop = niposition.Bottom + edgeoffset;
                }
                else
                {
                    windowtop = taskbarRectangle.Bottom + edgeoffset;
                }

                break;

            case Taskbar.TaskbarEdge.Left:
                // vertically centre to the right of icon (or above icon if in flyout and not pinned)
                if (inflyout && !pinned)
                {
                    windowleft = nicentre.X - (windowwidth / 2);
                    windowtop  = niposition.Top - windowheight - edgeoffset;
                }
                else
                {
                    windowleft = taskbarRectangle.Right + edgeoffset;
                    windowtop  = nicentre.Y - (windowheight / 2);
                }

                break;

            case Taskbar.TaskbarEdge.Right:
                // vertically centre to the left of icon (or above icon if in flyout and not pinned)
                if (inflyout && !pinned)
                {
                    windowleft = nicentre.X - (windowwidth / 2);
                    windowtop  = niposition.Top - windowheight - edgeoffset;
                }
                else
                {
                    windowleft = taskbarRectangle.Left - windowwidth - edgeoffset;
                    windowtop  = nicentre.Y - (windowheight / 2);
                }

                break;

            default:
                goto case Taskbar.TaskbarEdge.Bottom;     // should be unreachable
            }

            //// check that the window is within the working area
            //// if not, put it next to the closest edge

            if (windowleft + windowwidth + edgeoffset > workarea.Right) // too far right
            {
                windowleft = workarea.Right - windowwidth - edgeoffset;
            }
            else if (windowleft < workarea.Left) // too far left
            {
                windowleft = workarea.Left + edgeoffset;
            }

            if (windowtop + windowheight + edgeoffset > workarea.Bottom) // too far down
            {
                windowtop = workarea.Bottom - windowheight - edgeoffset;
            }
            //// the window should never be too far up, so we can skip checking for that

            return(new Point((int)windowleft, (int)windowtop));
        }
예제 #4
0
        public Point?GetLocation(int accuracy)
        {
            // Got something fullscreen running? Of course we can't find our icon!
            if (SysInfo.ForegroundWindowIsFullScreen)
            {
                return(null);
            }

            // The accuracy can't be below 0!
            if (accuracy < 0)
            {
                throw new ArgumentOutOfRangeException("accuracy", "The accuracy value provided can't be negative!");
            }

            // The notification area
            Rectangle notifyAreaRect = NotifyArea.GetRectangle();

            if (notifyAreaRect.IsEmpty)
            {
                return(null);
            }

            // Back up the NotifyIcon's icon so we can reset it later on
            Icon notifyIconIcon = _notifyIcon.Icon;

            // Have we got a colour we could base the find pixel off?
            if (!nearColorSet)
            {
                GetLocationPrepare();
            }

            // Blah
            List <int> colMatchIndexes = new List <int>();
            Point      last            = new Point(-1, -1);
            int        hits            = 0;
            int        hitsMax         = accuracy + 1;

            // Our wonderful loop
            for (int attempt = 0; attempt < 5 && hits < hitsMax; attempt++)
            {
                // Set the notify icon thingy to a random colour
                Random random   = new Random();
                int    rgbRange = 32;
                Color  col;
                if (nearColorSet)
                {
                    col = Color.FromArgb(
                        SafeColourVal(nearColor.R + random.Next(rgbRange) - 8),
                        SafeColourVal(nearColor.G + random.Next(rgbRange) - 8),
                        SafeColourVal(nearColor.B + random.Next(rgbRange) - 8));
                }
                else
                {
                    col = Color.FromArgb(
                        SafeColourVal(255 - random.Next(rgbRange)),
                        SafeColourVal(255 - random.Next(rgbRange)),
                        SafeColourVal(255 - random.Next(rgbRange)));
                }

                // Set the find colour...
                SetFindColour(col);

                // Take a screenshot...
                Color[] taskbarPixels;
                using (Bitmap notifyAreaBitmap = GetNotifyAreaScreenshot())
                {
                    // If something goes wrong, let's just assume we don't know where we should be
                    if (notifyAreaBitmap == null)
                    {
                        return(null);
                    }

                    // We can reset the NotifyIcon now, and then...
                    _notifyIcon.Icon = notifyIconIcon;

                    // Grab the pixels of the taskbar using my very own Pfz-derived bitmap to pixel array awesomeness
                    taskbarPixels = BitmapToPixelArray(notifyAreaBitmap);
                }

                // Get every occurence of our lovely colour next to something the same...
                bool colMatched    = false;
                int  colMatchIndex = -1;
                int  colAttempt    = 0; // this determines whether we -1 any of the RGB
                while (true)
                {
                    Color col2 = Color.FromArgb(0, 0, 0);
                    //int colModAmount = colAttempt < 8 ? -1 : 1;
                    int colMod1 = (colAttempt % 8) < 4 ? 0 : -1;
                    int colMod2 = (colAttempt % 8) < 4 ? -1 : 0;

                    switch (colAttempt % 4)
                    {
                    case 0: col2 = Color.FromArgb(SafeColourVal(col.R + colMod1), SafeColourVal(col.G + colMod1), SafeColourVal(col.B + colMod1)); break;

                    case 1: col2 = Color.FromArgb(SafeColourVal(col.R + colMod1), SafeColourVal(col.G + colMod1), SafeColourVal(col.B + colMod2)); break;

                    case 2: col2 = Color.FromArgb(SafeColourVal(col.R + colMod1), SafeColourVal(col.G + colMod2), SafeColourVal(col.B + colMod1)); break;

                    case 3: col2 = Color.FromArgb(SafeColourVal(col.R + colMod1), SafeColourVal(col.G + colMod2), SafeColourVal(col.B + colMod2)); break;
                    }

                    colAttempt++;

                    colMatchIndex = Array.FindIndex <Color>(taskbarPixels, colMatchIndex + 1, (Color c) => { return(c == col2); });

                    if (colMatchIndex == -1)
                    {
                        if (colAttempt < 8)
                        {
                            continue;
                        }
                        else
                        {
                            break;
                        }
                    }
                    else
                    {
                        if (taskbarPixels[colMatchIndex + 1] == col2)
                        {
                            colMatched = true;
                            break;
                        }
                    }
                }

                if (colMatched)
                {
                    hits++;
                    last.X = colMatchIndex % notifyAreaRect.Width;
                    last.Y = colMatchIndex / notifyAreaRect.Width; // Integer rounding is always downwards
                }
                else
                {
                    hits   = 0;
                    last.X = -1;
                    last.Y = -1;
                }
            }

            // Don't forget, our current values are relative to the notification area and are at the bottom right of the icon!
            Point location = new Point(last.X, last.Y);

            if (location != new Point(-1, -1))
            {
                return(new Point(notifyAreaRect.X + (last.X - 16), notifyAreaRect.Y + (last.Y - 14)));
            }
            else
            {
                return(null);
            }
        }