public void GetLocationPrepare() { // Get a screenshot of the notification area... Rectangle notifyAreaRect = NotifyAreaUtility.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 = NotifyAreaUtility.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); }
public Point?GetLocation2(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 var notifyAreaRect = NotifyAreaUtility.GetRectangle(); if (notifyAreaRect.IsEmpty) { return(null); } // Back up the NotifyIcon's icon so we can reset it later on var notifyIconIcon = _notifyIcon.Icon; // Have we got a colour we could base the find pixel off? if (!nearColorSet) { GetLocationPrepare(); } // Blah var 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); } }
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 = NotifyAreaUtility.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); }