• c# 任务栏托盘图标鼠标进入MouseEnter和鼠标离开MouseLeave实现


    c#的任务栏托盘图标控件NotifyIcon只有MouseMove事件,MouseMove事件刷新很快,很不好用,而且我们有时需要鼠标进入和离开的事件,但是不知道c#怎么回事,没有提供,那么就只能自己来处理了。

    解决鼠标进入和离开的思路是:

    1.通过MouseMove事件确定当前鼠标已经进入托盘图标的范围

    2.进入后启动检测timer

    3.定时检测托盘图标的位置和当前鼠标的位置,判断鼠标是否在托盘图标的范围内

    主要难点:获取当前托盘图标的位置

    获取托盘图标位置的思路:

    1.查找到托盘图标所在的窗口

    private IntPtr FindTrayToolbarWindow()
            {
                IntPtr hWnd = FindWindow("Shell_TrayWnd", null);
                if (hWnd != IntPtr.Zero)
                {
                    hWnd = FindWindowEx(hWnd, IntPtr.Zero, "TrayNotifyWnd", null);
                    if (hWnd != IntPtr.Zero)
                    {
    
                        hWnd = FindWindowEx(hWnd, IntPtr.Zero, "SysPager", null);
                        if (hWnd != IntPtr.Zero)
                        {
                            hWnd = FindWindowEx(hWnd, IntPtr.Zero, "ToolbarWindow32", null);
    
                        }
                    }
                }
                return hWnd;
            }
    View Code

    2.遍历窗口内的托盘图标

    3.获取当前托盘图标的句柄,通过句柄得到这个托盘图标所关联的进程id

    4.通过进程id比较获取到当前程序的托盘图标

    5.拖过api获取当前托盘图标相对于它所在窗口的位置

    6.获取窗口在整个屏幕中的位置,在计算出托盘图标相对于屏幕的位置

       2-6代码:

    private bool FindNotifyIcon(IntPtr hTrayWnd, ref Rect rectNotify)
            {
                UInt32 trayPid = 0;
                Rect rectTray = new Rect();
                GetWindowRect(hTrayWnd, out rectTray);
                int count = (int) SendMessage(hTrayWnd, TB_BUTTONCOUNT, 0, IntPtr.Zero); //给托盘窗口发消息,得到托盘里图标
    
                bool isFind = false;
                if (count > 0)
                {
                    GetWindowThreadProcessId(hTrayWnd, out trayPid); //取得托盘窗口对应的进程id
                    //获取托盘图标的位置
    
    
                    IntPtr hProcess = OpenProcess(ProcessAccess.VMOperation | ProcessAccess.VMRead | ProcessAccess.VMWrite,
                        false, trayPid); //打开进程,取得进程句柄
    
                    IntPtr address = VirtualAllocEx(hProcess, //在目标进程中申请一块内存,放TBBUTTON信息
                        IntPtr.Zero,
                        1024,
                        AllocationType.Commit,
                        MemoryProtection.ReadWrite);
    
    
                    TBBUTTON btnData = new TBBUTTON();
                    TRAYDATA trayData = new TRAYDATA();
    
                    //  Console.WriteLine("Count:"+count);
    
                    var handel = Process.GetCurrentProcess().Id;
                    //  Console.WriteLine("curHandel:" + handel);
                    for (uint j = 0; j < count; j++)
                    {
                        //   Console.WriteLine("j:"+j);
                        var i = j;
                        SendMessage(hTrayWnd, TB_GETBUTTON, i, address); //取得TBBUTTON结构到本地
                        int iTmp = 0;
                        var isTrue = ReadProcessMemory(hProcess,
                            address,
                            out btnData,
                            Marshal.SizeOf(btnData),
                            out iTmp);
                        if (isTrue == false) continue;
                        //这一步至关重要,不能省略
                        //主要解决64位系统电脑运行的是x86的程序
                        if (btnData.dwData == IntPtr.Zero)
                        {
                            btnData.dwData = btnData.iString;
                        }
                        ReadProcessMemory(hProcess, //从目标进程address处存放的是TBBUTTON
                            btnData.dwData, //取dwData字段指向的TRAYDATA结构
                            out trayData,
                            Marshal.SizeOf(trayData),
                            out iTmp);
    
                        UInt32 dwProcessId = 0;
                        GetWindowThreadProcessId(trayData.hwnd, //通过TRAYDATA里的hwnd字段取得本图标的进程id
                            out dwProcessId);
                        //获取当前进程id
                        //  StringBuilder sb = new StringBuilder(256);
                        //  GetModuleFileNameEx(OpenProcess(ProcessAccess.AllAccess, false, dwProcessId), IntPtr.Zero, sb, 256);
                        //  Console.WriteLine(sb.ToString());
                        if (dwProcessId == (UInt32) handel)
                        {
    
                            Rect rect = new Rect();
                            IntPtr lngRect = VirtualAllocEx(hProcess, //在目标进程中申请一块内存,放TBBUTTON信息
                                IntPtr.Zero,
                                Marshal.SizeOf(typeof (Rect)),
                                AllocationType.Commit,
                                MemoryProtection.ReadWrite);
                            i = j;
                            SendMessage(hTrayWnd, TB_GETITEMRECT, i, lngRect);
                            isTrue = ReadProcessMemory(hProcess, lngRect, out rect, Marshal.SizeOf(rect), out iTmp);
    
                            //释放内存
                            VirtualFreeEx(hProcess, lngRect, Marshal.SizeOf(rect), FreeType.Decommit);
                            VirtualFreeEx(hProcess, lngRect, 0, FreeType.Release);
    
                            int left = rectTray.Left + rect.Left;
                            int top = rectTray.Top + rect.Top;
                            int botton = rectTray.Top + rect.Bottom;
                            int right = rectTray.Left + rect.Right;
                            rectNotify = new Rect();
                            rectNotify.Left = left;
                            rectNotify.Right = right;
                            rectNotify.Top = top;
                            rectNotify.Bottom = botton;
                            isFind = true;
                            break;
                        } 
                    }
                    VirtualFreeEx(hProcess, address, 0x4096, FreeType.Decommit);
                    VirtualFreeEx(hProcess, address, 0, FreeType.Release);
                    CloseHandle(hProcess);
                }
                return isFind;
            }
    View Code

    7.如果没有找到,那么需要用相同的方法在托盘溢出区域内查找

       private IntPtr FindTrayToolbarOverFlowWindow()
            {
                IntPtr hWnd = FindWindow("NotifyIconOverflowWindow", null);
                if (hWnd != IntPtr.Zero)
                {
                    hWnd = FindWindowEx(hWnd, IntPtr.Zero, "ToolbarWindow32", null);
                }
                return hWnd;
            }
    View Code

    在查找中的难点:

    1.对于32位操作系统和64位操作系统,系统内部处理方式不一样,所以许多时候当去取TBBUTTON结构到本地的时候得到的地址为0,这里查询了一些资料,网上一些资料TBBUTTON的结构体如下:

      [StructLayout(LayoutKind.Sequential, Pack = 1)]
            public struct TBBUTTON
            {
                public int iBitmap;
                public int idCommand;
                public byte fsState;
                public byte fsStyle;
                public byte bReserved0;
                public byte bReserved1;
                public IntPtr dwData;
                public IntPtr iString;
            }
    View Code

    这个在32位下面没有问题,但是在64位系统下就出现了问题,后面参考网上一些资料,原来问题出在中间4个byte中,由于32位系统中4个byte刚好32位,但是在64位中这里就不对,所以就修改为如下:

    [StructLayout(LayoutKind.Sequential, Pack = 1)]
            public struct TBBUTTON
            {
                public int iBitmap;
                public int idCommand;
                public IntPtr fsStateStylePadding;
                public IntPtr dwData;
                public IntPtr iString;
            }
    View Code

    修改过后在64位系统中运行通过了,在这样一位问题解决了,但是当我将解决方案迁移到程序当中的时候,却出了问题,一直不能得到地址,查找了很多原因,原来是在我程序编译的时候,生成的平台是X86,那么就造成了64位系统中使用32位平台时出现问题:

    到这里我就猜想是不是 public IntPtr fsStateStylePadding;这一句出了问题,当时x86平台的时候,这个只占用了32位,但是实际64位系统这个位置应该要占用64位,造成地址不对,出错了。

    那么接下来我就证实了下这个问题,在我获取地址的时候在public IntPtr dwData;字段中没有获取到,但是在public IntPtr iString;字段中获取到了,那么证明我的猜想是对的(真正是否正确还需要指正),

    那么解决方案就来了,为了更好的兼容性,结构体不变,当获取dwData地址没有获取到的时候,我们查找iString字段就好了,方法在这里:

    //这一步至关重要,不能省略
                        //主要解决64位系统电脑运行的是x86的程序
                        if (btnData.dwData == IntPtr.Zero)
                        {
                            btnData.dwData = btnData.iString;
                        }
    View Code

    把这个主要的解决了,后面就是查找当前托盘图标相对于父窗体的位置了,使用了很多方法:

    GetWindowRect

    ScreenToClient

    GetClientRect

    这些方法都没有成功,最后发现网上有这么一种方法。

     SendMessage(hTrayWnd, TB_GETITEMRECT, i, lngRect);
                            isTrue = ReadProcessMemory(hProcess, lngRect, out rect, Marshal.SizeOf(rect), out iTmp);
    View Code

    在这里真正感受到c++的强大。

    在解决这个问题的过程中,参考了很多方案,通过整合才解决了这个问题,如下:

    http://blog.163.com/zjlovety@126/blog/static/22418624201142763542917/

    http://blog.csdn.net/wzsy/article/details/47980317

    http://www.cnblogs.com/hanf/archive/2011/08/09/2131641.html

    等。

    以下是调用方法:

      private void Load()
            {
                this._notifyIcon.MouseDoubleClick += notifyIcon_MouseDoubleClick;
                _notifyIcon.MouseMove += new MouseEventHandler(notifyIcon_MouseMove);
                CreateNotifyMouseHelper();
            }
    
     private NotifyIconMouseHelper notifyHelper;
            private Timer timer = null;
     private void CreateNotifyMouseHelper()
            {
                notifyHelper=new NotifyIconMouseHelper();
                notifyHelper.MouseEnterNotifyStatusChanged+= MouseEnterNotifyStatusChanged;
            }
     private void MouseEnterNotifyStatusChanged(object sender, bool isEnter)
            {
               
                if (isEnter)
                {
                  Console.WriteLine("鼠标进入");
                }
                else
                {
                  Console.WriteLine("鼠标离开");
                }
            }
    View Code

    以下是检测的源代码:

    using System;
    using System.Collections.Generic;
    using System.Data.Entity.Core.Metadata.Edm;
    using System.Diagnostics;
    using System.Linq;
    using System.Runtime.InteropServices;
    using System.Text;
    using System.Timers;
    using System.Windows;
    
    namespace NotifyTest
    {
        /*托盘图标鼠标进入离开事件
         */
    
        public delegate void MouseEnterNotifyStatusChangedHandel(object sender, bool isEnter);
    
        public class NotifyIconMouseHelper
        {
            #region win32类库 
    
            [Flags()]
            public enum ProcessAccess : int
            {
                /// <summary>Specifies all possible access flags for the process object.</summary>
                AllAccess =
                    CreateThread | DuplicateHandle | QueryInformation | SetInformation | Terminate | VMOperation | VMRead |
                    VMWrite | Synchronize,
    
                /// <summary>Enables usage of the process handle in the CreateRemoteThread function to create a thread in the process.</summary>
                CreateThread = 0x2,
    
                /// <summary>Enables usage of the process handle as either the source or target process in the DuplicateHandle function to duplicate a handle.</summary>
                DuplicateHandle = 0x40,
    
                /// <summary>Enables usage of the process handle in the GetExitCodeProcess and GetPriorityClass functions to read information from the process object.</summary>
                QueryInformation = 0x400,
    
                /// <summary>Enables usage of the process handle in the SetPriorityClass function to set the priority class of the process.</summary>
                SetInformation = 0x200,
    
                /// <summary>Enables usage of the process handle in the TerminateProcess function to terminate the process.</summary>
                Terminate = 0x1,
    
                /// <summary>Enables usage of the process handle in the VirtualProtectEx and WriteProcessMemory functions to modify the virtual memory of the process.</summary>
                VMOperation = 0x8,
    
                /// <summary>Enables usage of the process handle in the ReadProcessMemory function to' read from the virtual memory of the process.</summary>
                VMRead = 0x10,
    
                /// <summary>Enables usage of the process handle in the WriteProcessMemory function to write to the virtual memory of the process.</summary>
                VMWrite = 0x20,
    
                /// <summary>Enables usage of the process handle in any of the wait functions to wait for the process to terminate.</summary>
                Synchronize = 0x100000
            }
    
            [StructLayout(LayoutKind.Sequential)]
            private struct TRAYDATA
            {
                public IntPtr hwnd;
                public UInt32 uID;
                public UInt32 uCallbackMessage;
                public UInt32 bReserved0;
                public UInt32 bReserved1;
                public IntPtr hIcon;
            }
    
            [StructLayout(LayoutKind.Sequential, Pack = 1)]
            public struct TBBUTTON
            {
                public int iBitmap;
                public int idCommand;
                public IntPtr fsStateStylePadding;
                public IntPtr dwData;
                public IntPtr iString;
            }
    
            [Flags]
            public enum AllocationType
            {
                Commit = 0x1000,
                Reserve = 0x2000,
                Decommit = 0x4000,
                Release = 0x8000,
                Reset = 0x80000,
                Physical = 0x400000,
                TopDown = 0x100000,
                WriteWatch = 0x200000,
                LargePages = 0x20000000
            }
    
            [Flags]
            public enum MemoryProtection
            {
                Execute = 0x10,
                ExecuteRead = 0x20,
                ExecuteReadWrite = 0x40,
                ExecuteWriteCopy = 0x80,
                NoAccess = 0x01,
                ReadOnly = 0x02,
                ReadWrite = 0x04,
                WriteCopy = 0x08,
                GuardModifierflag = 0x100,
                NoCacheModifierflag = 0x200,
                WriteCombineModifierflag = 0x400
            }
    
            [DllImport("user32.dll", SetLastError = true)]
            private static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
    
            [DllImport("user32.dll", SetLastError = true)]
            private static extern IntPtr FindWindowEx(IntPtr hwndParent, IntPtr hwndChildAfter, string lpszClass,
                string lpszWindow);
    
            [DllImport("user32.dll", SetLastError = true)]
            private static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint lpdwProcessId);
    
            [DllImport("kernel32.dll")]
            private static extern IntPtr OpenProcess(ProcessAccess dwDesiredAccess,
                [MarshalAs(UnmanagedType.Bool)] bool bInheritHandle, uint dwProcessId);
    
            [DllImport("user32.dll", CharSet = CharSet.Auto)]
            private static extern UInt32 SendMessage(IntPtr hWnd, UInt32 Msg, UInt32 wParam, IntPtr lParam);
    
            [DllImport("kernel32.dll", SetLastError = true, ExactSpelling = true)]
            private static extern IntPtr VirtualAllocEx(IntPtr hProcess, IntPtr lpAddress,
                int dwSize, AllocationType flAllocationType, MemoryProtection flProtect);
    
            [DllImport("kernel32.dll", SetLastError = true)]
            private static extern bool ReadProcessMemory(
                IntPtr hProcess,
                IntPtr lpBaseAddress,
                out TBBUTTON lpBuffer,
                int dwSize,
                out int lpNumberOfBytesRead
                );
    
            [DllImport("kernel32.dll", SetLastError = true)]
            private static extern bool ReadProcessMemory(
                IntPtr hProcess,
                IntPtr lpBaseAddress,
                out Rect lpBuffer,
                int dwSize,
                out int lpNumberOfBytesRead
                );
    
            [DllImport("kernel32.dll", SetLastError = true)]
            private static extern bool ReadProcessMemory(
                IntPtr hProcess,
                IntPtr lpBaseAddress,
                out TRAYDATA lpBuffer,
                int dwSize,
                out int lpNumberOfBytesRead
                );
    
            [DllImport("psapi.dll")]
            private static extern uint GetModuleFileNameEx(IntPtr hProcess, IntPtr hModule, [Out] StringBuilder lpBaseName,
                [In] [MarshalAs(UnmanagedType.U4)] int nSize);
    
            [Flags]
            public enum FreeType
            {
                Decommit = 0x4000,
                Release = 0x8000,
            }
    
            [DllImport("kernel32.dll")]
            private static extern bool VirtualFreeEx(IntPtr hProcess, IntPtr lpAddress, int dwSize, FreeType dwFreeType);
    
            [DllImport("kernel32.dll")]
            [return: MarshalAs(UnmanagedType.Bool)]
            private static extern bool CloseHandle(IntPtr hObject);
    
            [StructLayout(LayoutKind.Sequential)]
            public struct POINT
            {
                public int X;
                public int Y;
    
                public POINT(int x, int y)
                {
                    this.X = x;
                    this.Y = y;
                }
    
                public override string ToString()
                {
                    return ("X:" + X + ", Y:" + Y);
                }
            }
    
            [DllImport("user32")]
            public static extern bool GetClientRect(
                IntPtr hwnd,
                out Rect lpRect
                );
    
            [DllImport("user32.dll", CharSet = CharSet.Auto)]
            public static extern bool GetCursorPos(out POINT pt);
    
    
            [StructLayout(LayoutKind.Sequential)]
            public struct Rect
            {
                public int Left;
                public int Top;
                public int Right;
                public int Bottom;
            }
    
            [DllImport("user32.dll")]
            private static extern int GetWindowRect(IntPtr hwnd, out Rect lpRect);
    
            public const int WM_USER = 0x0400;
            public const int TB_BUTTONCOUNT = WM_USER + 24;
            public const int TB_GETBUTTON = WM_USER + 23;
            public const int TB_GETBUTTONINFOW = WM_USER + 63;
            public const int TB_GETITEMRECT = WM_USER + 29;
    
            #endregion
    
            #region 检测托盘图标相对于屏幕位置
    
            private bool FindNotifyIcon(ref Rect rect)
            {
                Rect rectNotify = new Rect();
                IntPtr hTrayWnd = FindTrayToolbarWindow(); //找到托盘窗口句柄
                var isTrue = FindNotifyIcon(hTrayWnd, ref rectNotify);
                if (isTrue == false)
                {
                    hTrayWnd = FindTrayToolbarOverFlowWindow(); //找到托盘窗口句柄
                    isTrue = FindNotifyIcon(hTrayWnd, ref rectNotify);
                }
                rect = rectNotify;
                return isTrue;
            }
    
            private IntPtr FindTrayToolbarWindow()
            {
                IntPtr hWnd = FindWindow("Shell_TrayWnd", null);
                if (hWnd != IntPtr.Zero)
                {
                    hWnd = FindWindowEx(hWnd, IntPtr.Zero, "TrayNotifyWnd", null);
                    if (hWnd != IntPtr.Zero)
                    {
    
                        hWnd = FindWindowEx(hWnd, IntPtr.Zero, "SysPager", null);
                        if (hWnd != IntPtr.Zero)
                        {
                            hWnd = FindWindowEx(hWnd, IntPtr.Zero, "ToolbarWindow32", null);
    
                        }
                    }
                }
                return hWnd;
            }
    
            private IntPtr FindTrayToolbarOverFlowWindow()
            {
                IntPtr hWnd = FindWindow("NotifyIconOverflowWindow", null);
                if (hWnd != IntPtr.Zero)
                {
                    hWnd = FindWindowEx(hWnd, IntPtr.Zero, "ToolbarWindow32", null);
                }
                return hWnd;
            }
    
            private bool FindNotifyIcon(IntPtr hTrayWnd, ref Rect rectNotify)
            {
                UInt32 trayPid = 0;
                Rect rectTray = new Rect();
                GetWindowRect(hTrayWnd, out rectTray);
                int count = (int) SendMessage(hTrayWnd, TB_BUTTONCOUNT, 0, IntPtr.Zero); //给托盘窗口发消息,得到托盘里图标
    
                bool isFind = false;
                if (count > 0)
                {
                    GetWindowThreadProcessId(hTrayWnd, out trayPid); //取得托盘窗口对应的进程id
                    //获取托盘图标的位置
    
    
                    IntPtr hProcess = OpenProcess(ProcessAccess.VMOperation | ProcessAccess.VMRead | ProcessAccess.VMWrite,
                        false, trayPid); //打开进程,取得进程句柄
    
                    IntPtr address = VirtualAllocEx(hProcess, //在目标进程中申请一块内存,放TBBUTTON信息
                        IntPtr.Zero,
                        1024,
                        AllocationType.Commit,
                        MemoryProtection.ReadWrite);
    
    
                    TBBUTTON btnData = new TBBUTTON();
                    TRAYDATA trayData = new TRAYDATA();
    
                    //  Console.WriteLine("Count:"+count);
    
                    var handel = Process.GetCurrentProcess().Id;
                    //  Console.WriteLine("curHandel:" + handel);
                    for (uint j = 0; j < count; j++)
                    {
                        //   Console.WriteLine("j:"+j);
                        var i = j;
                        SendMessage(hTrayWnd, TB_GETBUTTON, i, address); //取得TBBUTTON结构到本地
                        int iTmp = 0;
                        var isTrue = ReadProcessMemory(hProcess,
                            address,
                            out btnData,
                            Marshal.SizeOf(btnData),
                            out iTmp);
                        if (isTrue == false) continue;
                        //这一步至关重要,不能省略
                        //主要解决64位系统电脑运行的是x86的程序
                        if (btnData.dwData == IntPtr.Zero)
                        {
                            btnData.dwData = btnData.iString;
                        }
                        ReadProcessMemory(hProcess, //从目标进程address处存放的是TBBUTTON
                            btnData.dwData, //取dwData字段指向的TRAYDATA结构
                            out trayData,
                            Marshal.SizeOf(trayData),
                            out iTmp);
    
                        UInt32 dwProcessId = 0;
                        GetWindowThreadProcessId(trayData.hwnd, //通过TRAYDATA里的hwnd字段取得本图标的进程id
                            out dwProcessId);
                        //获取当前进程id
                        //  StringBuilder sb = new StringBuilder(256);
                        //  GetModuleFileNameEx(OpenProcess(ProcessAccess.AllAccess, false, dwProcessId), IntPtr.Zero, sb, 256);
                        //  Console.WriteLine(sb.ToString());
                        if (dwProcessId == (UInt32) handel)
                        {
    
                            Rect rect = new Rect();
                            IntPtr lngRect = VirtualAllocEx(hProcess, //在目标进程中申请一块内存,放TBBUTTON信息
                                IntPtr.Zero,
                                Marshal.SizeOf(typeof (Rect)),
                                AllocationType.Commit,
                                MemoryProtection.ReadWrite);
                            i = j;
                            SendMessage(hTrayWnd, TB_GETITEMRECT, i, lngRect);
                            isTrue = ReadProcessMemory(hProcess, lngRect, out rect, Marshal.SizeOf(rect), out iTmp);
    
                            //释放内存
                            VirtualFreeEx(hProcess, lngRect, Marshal.SizeOf(rect), FreeType.Decommit);
                            VirtualFreeEx(hProcess, lngRect, 0, FreeType.Release);
    
                            int left = rectTray.Left + rect.Left;
                            int top = rectTray.Top + rect.Top;
                            int botton = rectTray.Top + rect.Bottom;
                            int right = rectTray.Left + rect.Right;
                            rectNotify = new Rect();
                            rectNotify.Left = left;
                            rectNotify.Right = right;
                            rectNotify.Top = top;
                            rectNotify.Bottom = botton;
                            isFind = true;
                            break;
                        } 
                    }
                    VirtualFreeEx(hProcess, address, 0x4096, FreeType.Decommit);
                    VirtualFreeEx(hProcess, address, 0, FreeType.Release);
                    CloseHandle(hProcess);
                }
                return isFind;
            }
    
            #endregion
    
    
            public MouseEnterNotifyStatusChangedHandel MouseEnterNotifyStatusChanged;
            private object moveObject = new object();
            private bool isOver = false;
            private Timer timer = null;
    
            public void MouseEnter()
            {
                lock (moveObject)
                {
                    if (isOver) return;
    
                    //加载鼠标进入事件
                    MouseEnter(true);
                    CreateCheckTimer();
                    timer.Enabled = true;
                }
            }
    
            private void CreateCheckTimer()
            {
                if (timer != null) return;
                timer = new Timer();
                timer.Interval = 120;
                timer.Elapsed += TimerOnElapsed;
            }
    
            private void TimerOnElapsed(object sender, ElapsedEventArgs arg)
            {
                //300毫秒检测一次
                //判断鼠标是否在托盘图标内
                //如果在,那么就不管
                //如果不在,就加载鼠标离开事件,同时停止timer
                var isEnter = CheckMouseIsEnter();
                if (isEnter) return;
                timer.Enabled = false;
                MouseEnter(false);
            }
    
            private void MouseEnter(bool isEnter)
            {
                isOver = isEnter;
                if (MouseEnterNotifyStatusChanged == null) return;
                MouseEnterNotifyStatusChanged(this, isEnter);
            }
    
            public Point Point { get; set; }
    
            private bool CheckMouseIsEnter()
            {
                //这里怎么检测呢
                //我很无语啊 
                //第一步:获取当前鼠标的坐标
                //第二步:获取托盘图标的坐标
                //   ???? 难难难难难难难难难难
                try
                {
    
                    Rect rectNotify = new Rect();
                    var isTrue = FindNotifyIcon(ref rectNotify);
                    if (isTrue == false) return false;
                    POINT point = new POINT();
                    GetCursorPos(out point);
    //            Console.WriteLine(string.Format(@"
    //Left={0} Top={1} Right={2} Bottom={3}", rectNotify.Left, rectNotify.Top, rectNotify.Right, rectNotify.Bottom));
    //            Console.WriteLine(point.X + "  " + point.Y);
                    //第三步:比较鼠标图标是否在托盘图标的范围内
                    if (point.X >= rectNotify.Left && point.X <= rectNotify.Right &&
                        point.Y >= rectNotify.Top && point.Y <= rectNotify.Bottom)
                    {
                        Point = new Point(point.X, point.Y);
                        return true;
                    }
                    else
                    {
                        return false;
                    }
                }
                catch (Exception)
                {
                    return false;
                }
            }
        }
    }
    View Code
  • 相关阅读:
    hiberate关系映射大全
    SpringMVC+RestFul详细示例实战教程
    [转]为什么大型网站前端使用 PHP 后台逻辑用 Java?
    offsetWidthoffsetleft 等图文解释
    理解jquery的$.extend()、$.fn和$.fn.extend()
    使用jquery获取url及url参数的方法
    构建高并发高可用的电商平台架构实践
    jquery实现多条件筛选特效代码分享
    【转载】“活在当下”是什么含义呢?
    UL LI 布局 TAB 切换条
  • 原文地址:https://www.cnblogs.com/sczmzx/p/5158127.html
Copyright © 2020-2023  润新知