public static void GetLocationPre7Prepare() { // 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) { s_nearColor = notifyAreaBitmap.GetPixel(_notifyAreaSize.Width - 3, _notifyAreaSize.Height / 2); } else { s_nearColor = notifyAreaBitmap.GetPixel(_notifyAreaSize.Width / 2, _notifyAreaSize.Height - 3); } // And now we have our base colour! s_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 (Win32Exception) { return(null); } } return(_notifyAreaBitmap); }
private void Init() { // Does the owner have an icon set? if (m_owner.NotifyIcon.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 m_owner.NotifyIcon.MouseUp += (sender, e) => { m_mouseWasInNotifyArea = false; }; // Refresh the drop position if we click in the notification area on Windows 7; we might've moved an icon! if (OperatingSystem.GteWindows7) { MouseHook.MouseDown += (sender, e) => { m_mouseWasInNotifyArea = MouseInNotifyArea(); // Shall we cancel, then? if (e.Button != MouseButtons.Left) { m_mouseWasInNotifyArea = false; } }; MouseHook.MouseUp += (sender, e) => { if (MouseInNotifyArea() && m_mouseWasInNotifyArea) { // We should wait for the icon to settle in before doing anything Timer _wait = new Timer(); _wait.Tick += (sender2, e2) => { if (m_mouseWasInNotifyArea) { ShowDrop(); } m_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(Location.X + 2, 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() || m_lastNotifyIconPoint != new Point(-1, -1)) { _mouseHold.Cancel(); } }; _mouseHold.MouseHoldTimeout += (sender, e) => { if (m_lastNotifyIconPoint == new Point(-1, -1)) { ShowDrop(); } }; }
private static bool MouseInNotifyArea() { return(NotifyArea.GetRectangle().Contains(Cursor.Position)); }
public Point GetLocationPre7(int accuracy) { // Got something fullscreen running? Of course we can't find our icon! if (FullScreen.Detect()) { return(new Point(-1, -1)); } // 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(); // Invalid size? Don't bother doing anything. if (_notifyAreaRect.Width < 1 || _notifyAreaRect.Height < 1) { return(new Point(-1, -1)); } // 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 (!s_nearColorSet) { GetLocationPre7Prepare(); } 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 (s_nearColorSet) { _col = Color.FromArgb( SafeColourVal(s_nearColor.R + _random.Next(_rgbRange) - 8), SafeColourVal(s_nearColor.G + _random.Next(_rgbRange) - 8), SafeColourVal(s_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(new Point(-1, -1)); } // 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.From(_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 _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(_taskbarPixels, _colMatchIndex + 1, 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)) { _location = new Point(_notifyAreaRect.X + (_last.X - 16), _notifyAreaRect.Y + (_last.Y - 14)); } // And so we return the value now! return(_location); }