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; } }
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); }
/// <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)); }
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); } }