Link to home
Start Free TrialLog in
Avatar of Knossos
Knossos

asked on

[c#] NotifyIcon - Detect MouseOut

Hi :)

A very simple question, but one I cannot seem to find an answer to.

I need to make my Form show when the mouse goes over the NotifyIcon. It then needs to hide once the mouse has left the NotifyIcon.

I'm fairly sure I'm missing something simple, but the only method for that seems to be MouseMove. Which, as far as I can tell, has no property to determine if it has entered or left the icon area.

Thanks.
Avatar of MogalManic
MogalManic
Flag of United States of America image

Avatar of Knossos
Knossos

ASKER

Those events do not exist in NotifyIcon.
Avatar of Mike Tomlinson
There is NO built-in API at the operating system level for EASILY asking the location of an icon in the system tray.

There are several "solutions" out there that involve interrogating the tray based on the known messages for its class type but nothing that works rock solid for all possible conditions.  Additionally, this approach relies on knowing the "ID" of the icon beforehand...something that you only have when you create icons manually via the WinAPIs (not using the .Net NotifyIcon).  Other approaches include attempting to find an image match in the tray or drawing your icon temporarily as a solid color that can be more easily detected.
See: http://www.codeproject.com/KB/shell/ctrayiconposition.aspx
ASKER CERTIFIED SOLUTION
Avatar of Mike Tomlinson
Mike Tomlinson
Flag of United States of America image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of Knossos

ASKER

That works great :)

I converted it to C# and setup Delegates and it works like a charm now.

I've attached as a snippet for anyone who sees this in the future.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
using System.Windows.Forms;
using System.Drawing;
 
namespace OgameChecker.Library
{
    class TrayHelper
    {
        Timer trayTimer;
        public delegate void MouseInDelegate(object sender, MouseEventArgs e);
        public delegate void MouseOutDelegate();
        public MouseInDelegate mouseInDelegate;
        public MouseOutDelegate mouseOutDelegate;
 
        public TrayHelper(NotifyIcon icon)
        {
            trayTimer = new Timer();
            trayTimer.Interval = 100;
            trayTimer.Enabled = false;
 
            icon.MouseMove += new MouseEventHandler(icon_MouseMove);
            trayTimer.Tick += new EventHandler(trayTimer_Tick);
        }
 
        void icon_MouseMove(object sender, MouseEventArgs e)
        {
 	        trayTimer.Start();
            mouseInDelegate(sender, e);
        }
 
        void trayTimer_Tick(object sender, EventArgs e)
        {
 	        if(!WinAPI.GetTrayRectangle().Contains(Cursor.Position))
            {
                trayTimer.Stop();
                mouseOutDelegate();
            }
        }
    }
}
 
public class WinAPI
{
    public struct RECT
    {
        public int left;
        public int top;
        public int right;
        public int bottom;
 
        public override string ToString()
        {
            return "(" + left + ", " + top + ") --> (" + right + ", " + bottom + ")";
        }
    }
 
    [DllImport("user32.dll", CharSet=CharSet.Auto)]
    public static extern IntPtr FindWindow(string strClassName, string strWindowName);
    
    [DllImport("user32.dll", SetLastError = true)]
    public static extern IntPtr FindWindowEx(IntPtr parentHandle, IntPtr childAfter, string className,  IntPtr windowTitle);
    
    [DllImport("user32.dll")]
    [return: MarshalAs(UnmanagedType.Bool)]
    static extern bool GetWindowRect(IntPtr hWnd, out RECT lpRect);
 
 
    public static IntPtr GetTrayHandle()
    {
        IntPtr taskBarHandle = WinAPI.FindWindow("Shell_TrayWnd", null);
        if(!taskBarHandle.Equals(IntPtr.Zero))
        {
            return WinAPI.FindWindowEx(taskBarHandle, IntPtr.Zero, "TrayNotifyWnd", IntPtr.Zero);
        }
        return IntPtr.Zero;
    }
 
    public static Rectangle GetTrayRectangle()
    {
        WinAPI.RECT rect;
        WinAPI.GetWindowRect(WinAPI.GetTrayHandle(), out rect);
        return new Rectangle(new Point(rect.left, rect.top), new Size((rect.right - rect.left) + 1, (rect.bottom - rect.top) + 1));
    }
}

Open in new window