• 一个新的NotifyIcon


        2003的NotifyIcon没有气泡提示功能,所以扩展了一个新的,能达到2005的NotifyIcon的同样功能,并且提供了两个新的功能。
        静态方法 FindNotifyIcon 在系统托盘里查找提示文本相同的托盘句柄,以便以向它发送消息。
        事件 DoWndProc 托盘WndProc时触发。
        下面是程序清单:
    using System;
    using System.ComponentModel;
    using System.Drawing;
    using System.Reflection;
    using System.Runtime.InteropServices;
    using System.Windows.Forms;

    namespace FaibClass.Windows.Forms
    {
        
    public sealed class NotifyIcon : Component
        
    {
            
    private bool added;
            
    private ContextMenu contextMenu;
            
    private bool doubleClick;
            
    private ToolTipIcon balloonTipIcon;
            
    private string balloonTipText;
            
    private string balloonTipTitle;
            
    private IntPtr handle = IntPtr.Zero;

            
    private Icon icon;
            
    private int id;
            
    private static int nextId = 0;
            
    private string text;
            
    private bool visible = true;
            
    private NotifyIconNativeWindow window;
            
    private static int WM_TASKBARCREATED = RegisterWindowMessage("TaskbarCreated");
            
    private const int WM_USER = 0x400;
            
    private const int WM_TRAYMOUSEMESSAGE = 2048;
            
    private const int WM_MOUSEMOVE = 0x200;
            
    private const int WM_LBUTTONDOWN = 0x201;
            
    private const int WM_LBUTTONUP = 0x202;
            
    private const int WM_LBUTTONDBLCLK = 0x203;
            
    private const int WM_RBUTTONDOWN = 0x204;
            
    private const int WM_RBUTTONUP = 0x205;
            
    private const int WM_RBUTTONDBLCLK = 0x206;
            
    private const int WM_MBUTTONDOWN = 0x207;
            
    private const int WM_MBUTTONUP = 0x208;
            
    private const int WM_MBUTTONDBLCLK = 0x209;
            
    private const int NIN_BALLOONSHOW = 0x402;
            
    private const int NIN_BALLOONHIDE = 0x403;
            
    private const int NIN_BALLOONTIMEOUT = 0x404;
            
    private const int NIN_BALLOONUSERCLICK = 0x405;

            
    private const int READ_CONTROL = 0x20000;
            
    private const int STANDARD_RIGHTS_REQUIRED = 0xF0000;
            
    private const int STANDARD_RIGHTS_READ = READ_CONTROL;
            
    private const int STANDARD_RIGHTS_EXECUTE = READ_CONTROL;
            
    private const int STANDARD_RIGHTS_ALL = 0x1F0000;
            
    private const int STANDARD_RIGHTS_WRITE = READ_CONTROL;
            
    private const int SYNCHRONIZE = 0x100000;
            
    private const int PROCESS_ALL_ACCESS = STANDARD_RIGHTS_REQUIRED | SYNCHRONIZE | 0xFFF;
            
    private const int PROCESS_TERMINATE = 0x1;

            
    private const int PROCESS_VM_OPERATION = 0x8;
            
    private const int PROCESS_VM_READ = 0x10;
            
    private const int PROCESS_VM_WRITE = 0x20;
            
    private const int MEM_RESERVE = 0x2000;
            
    private const int MEM_COMMIT = 0x1000;
            
    private const int MEM_RELEASE = 0x8000;
            
    private const int PAGE_READWRITE = 0x4;

            
    private const int TB_BUTTONCOUNT = (WM_USER + 24);
            
    private const int TB_HIDEBUTTON = (WM_USER + 4);
            
    private const int TB_GETBUTTON = (WM_USER + 23);
            
    private const int TB_GETBITMAP = (WM_USER + 44);
            
    private const int TB_DELETEBUTTON = (WM_USER + 22);
            
    private const int TB_ADDBUTTONS = (WM_USER + 20);
            
    private const int TB_INSERTBUTTON = (WM_USER + 21);
            
    private const int TB_ISBUTTONHIDDEN = (WM_USER + 12);
            
    private const int ILD_NORMAL = 0x0;

            
    private const int TPM_NONOTIFY = 0x80;

            
    枚举

            
    结构

            
    Win32 API 引用

            
    public event EventHandler Click;
            
    public event EventHandler DoubleClick;
            
    public event MouseEventHandler MouseDown;
            
    public event MouseEventHandler MouseMove;
            
    public event MouseEventHandler MouseUp;
            
    public event EventHandler BalloonTipClicked;
            
    public event EventHandler BalloonTipClosed;
            
    public event EventHandler BalloonTipShown;
            
    public event WndProcEventHandler DoWndProc;

            
    public NotifyIcon()
            
    {
                icon 
    = null;
                text 
    = "";
                id 
    = 0;
                added 
    = false;
                window 
    = null;
                contextMenu 
    = null;
                doubleClick 
    = false;
                id 
    = ++nextId;
                window 
    = new NotifyIconNativeWindow(this);
                
    //UpdateIcon(visible);
            }


            
    public NotifyIcon(IContainer container) : this()
            
    {
                container.Add(
    this);
            }


            
    属性

            
    protected override void Dispose(bool disposing)
            
    {
                
    if (disposing)
                
    {
                    
    if (window != null)
                    
    {
                        icon 
    = null;
                        Text 
    = "";
                        UpdateIcon(
    false);
                        window.DestroyHandle();
                        window 
    = null;
                        contextMenu 
    = null;
                    }

                }

                
    else if ((window != null&& (window.Handle != IntPtr.Zero))
                
    {
                    PostMessage(
    new HandleRef(window, window.Handle), 1600);
                    window.ReleaseHandle();
                }

                
    base.Dispose(disposing);
            }


            
    private void OnBalloonTipClicked()
            
    {
                
    if (BalloonTipClicked != null)
                    BalloonTipClicked(
    this, EventArgs.Empty);
            }


            
    private void OnBalloonTipClosed()
            
    {
                
    if (BalloonTipClosed != null)
                    BalloonTipClosed(
    this, EventArgs.Empty);
            }


            
    private void OnBalloonTipShown()
            
    {
                
    if (BalloonTipShown != null)
                    BalloonTipShown(
    this, EventArgs.Empty);
            }


            
    private void OnClick(EventArgs e)
            
    {
                
    if (Click != null)
                    Click(
    this, e);
            }


            
    private void OnDoubleClick(EventArgs e)
            
    {
                
    if (DoubleClick != null)
                    DoubleClick(
    this, e);
            }


            
    private void OnMouseDown(MouseEventArgs e)
            
    {
                
    if (MouseDown != null)
                    MouseDown(
    this, e);
            }


            
    private void OnMouseMove(MouseEventArgs e)
            
    {
                
    if (MouseMove != null)
                    MouseMove(
    this, e);
            }


            
    private void OnMouseUp(MouseEventArgs e)
            
    {
                
    if (MouseUp != null)
                    MouseUp(
    this, e);
            }


            
    private bool OnDoWndProc(ref Message m)
            
    {
                
    if (DoWndProc != null)
                    
    return DoWndProc(thisref m);
                
    return true;
            }


            
    private void ShowContextMenu()
            
    {
                
    if (contextMenu != null)
                
    {
                    POINT pt 
    = new POINT();
                    GetCursorPos(
    ref pt);
                    SetForegroundWindow(
    new HandleRef(window, window.Handle));
                    contextMenu.GetType().InvokeMember(
    "OnPopup",
                        BindingFlags.NonPublic 
    | BindingFlags.InvokeMethod | BindingFlags.Instance,
                        
    null, contextMenu, new Object[] {new EventArgs()});
                    TrackPopupMenuEx(
    new HandleRef(contextMenu, contextMenu.Handle), TPM_NONOTIFY, pt.x, pt.y, new HandleRef(window, window.Handle), null);
                    PostMessage(
    new HandleRef(window, window.Handle), 0, IntPtr.Zero, IntPtr.Zero);
                }

            }


            
    private void UpdateIcon(bool showIconInTray)
            
    {
                
    lock (this)
                
    {
                    
    if (!base.DesignMode)
                    
    {
                        window.LockReference(showIconInTray);
                        NotifyIconData pnid 
    = new NotifyIconData();
                        pnid.uCallbackMessage 
    = 0x800;
                        pnid.uFlags 
    = NotifyFlags.Message;
                        
    if (showIconInTray && (window.Handle == IntPtr.Zero))
                        
    {
                            window.CreateHandle(
    new CreateParams());
                        }

                        pnid.cbSize 
    =Marshal.SizeOf(pnid);
                        pnid.hWnd 
    = window.Handle;
                        pnid.uID 
    = id;
                        pnid.hIcon 
    = IntPtr.Zero;
                        pnid.szTip 
    = null;
                        
    if (icon != null)
                        
    {
                            pnid.uFlags 
    |= NotifyFlags.Icon;
                            pnid.hIcon 
    = icon.Handle;
                        }

                        pnid.uFlags 
    |= NotifyFlags.Tip;
                        pnid.szTip 
    = text;
                        
    if (showIconInTray && (icon != null))
                        
    {
                            
    if (!added)
                            
    {
                                Shell_NotifyIcon(NotifyCommand.Add, 
    ref pnid);
                                added 
    = true;
                            }

                            
    else
                            
    {
                                Shell_NotifyIcon(NotifyCommand.Modify, 
    ref pnid);
                            }

                        }

                        
    else if (added)
                        
    {
                            Shell_NotifyIcon(NotifyCommand.Delete, 
    ref pnid);
                            added 
    = false;
                        }

                    }

                }

            }


            
    public static IntPtr FindNotifyIcon(string TipTitle)
            
    {
                
    if(TipTitle.Length == 0)return IntPtr.Zero;
                IntPtr pid 
    = IntPtr.Zero;
                IntPtr ipHandle 
    = IntPtr.Zero; //图标句柄
                IntPtr lTextAdr = IntPtr.Zero; //文本内存地址
                IntPtr ipTemp = FindWindow("Shell_TrayWnd"null);
                
    //找到托盘
                ipTemp = FindWindowEx(ipTemp, IntPtr.Zero, "TrayNotifyWnd"null);
                ipTemp 
    = FindWindowEx(ipTemp, IntPtr.Zero, "SysPager"null);
                IntPtr ipTray 
    = FindWindowEx(ipTemp, IntPtr.Zero, "ToolbarWindow32"null);
                
                GetWindowThreadProcessId(ipTray, 
    ref pid);
                
    if(pid.Equals(0))return ipHandle;

                IntPtr hProcess 
    = OpenProcess(PROCESS_ALL_ACCESS | PROCESS_VM_OPERATION | PROCESS_VM_READ | PROCESS_VM_WRITE, IntPtr.Zero, pid);
                IntPtr lAddress 
    = VirtualAllocEx(hProcess, 04096, MEM_COMMIT, PAGE_READWRITE);

                
    //得到图标个数
                int lButton = SendMessage(ipTray, TB_BUTTONCOUNT, 00);
                
    for(int i = 0; i < lButton; i++)
                
    {
                    SendMessage(ipTray, TB_GETBUTTON, i, lAddress);
                    
    //读文本地址
                    ReadProcessMemory(hProcess, (IntPtr)(lAddress.ToInt32() + 16), ref lTextAdr, 40);
                    
    if(!lTextAdr.Equals(-1))
                    
    {
                        
    byte[] buff = new byte[1024];
                        
    //读文本
                        ReadProcessMemory(hProcess, lTextAdr, buff, 10240);
                        
    string title = System.Text.ASCIIEncoding.Unicode.GetString(buff);
                        
    // 从字符0处截断
                        int nullindex = title.IndexOf("\0");
                        
    if(nullindex > 0)
                        
    {
                            title 
    = title.Substring(0, nullindex);
                        }

                        
    //ReadProcessMemory(hProcess, lAddress, ref ipButtonID, 4, 0);
                        
    //判断是不是要找的图标
                        if(title.Equals(TipTitle))
                        
    {
                            IntPtr ipHandleAdr 
    = IntPtr.Zero;
                            
    //读句柄地址
                            ReadProcessMemory(hProcess, (IntPtr)(lAddress.ToInt32() + 12), ref ipHandleAdr, 40);
                            ReadProcessMemory(hProcess, ipHandleAdr, 
    ref ipHandle, 40);
                            
    break;
                        }

                    }

                }

                VirtualFreeEx(hProcess, lAddress, 
    4096, MEM_RELEASE);
                CloseHandle(hProcess);
                
    return ipHandle;
            }


            
    public void ShowBalloonTip(int timeout)
            
    {
                ShowBalloonTip(balloonTipTitle, balloonTipText, balloonTipIcon, timeout);
            }


            
    public void ShowBalloonTip(string tipTitle, string tipText, ToolTipIcon tipIcon, int timeout)
            
    {
                
    if (timeout < 0)
                
    {
                    
    throw new ArgumentOutOfRangeException("timeout""超时时间不错误");
                }

                
    if (tipText == null || tipText.Length == 0)
                
    {
                    
    throw new ArgumentException("显示的信息不能为空");
                }

                
    if (added && !base.DesignMode)
                
    {
                    NotifyIconData pnid 
    = new NotifyIconData();
                    
    if (window.Handle == IntPtr.Zero)
                    
    {
                        
    //创建窗体
                        window.CreateHandle(new CreateParams());
                    }

                    pnid.cbSize 
    =Marshal.SizeOf(pnid);
                    pnid.hWnd 
    = window.Handle;
                    pnid.uID 
    = id;
                    pnid.uFlags 
    = NotifyFlags.Info;
                    pnid.uTimeoutOrVersion 
    = timeout;
                    pnid.szInfoTitle 
    = tipTitle;
                    pnid.szInfo 
    = tipText;
                    pnid.dwInfoFlags 
    = tipIcon;
                    Shell_NotifyIcon(NotifyCommand.Modify, 
    ref pnid);
                }

                
    //延时后更新图标
                System.Threading.Thread.Sleep(50);
                UpdateIcon(visible);
            }


            
    private void WmMouseDown(ref Message m, MouseButtons button, int clicks)
            
    {
                
    if (clicks == 2//双击
                {
                    OnDoubleClick(EventArgs.Empty);
                    doubleClick 
    = true;
                }

                OnMouseDown(
    new MouseEventArgs(button, clicks, 000));
            }


            
    private void WmMouseMove(ref Message m)
            
    {
                OnMouseMove(
    new MouseEventArgs(Control.MouseButtons, 0000));
            }


            
    private void WmMouseUp(ref Message m, MouseButtons button)
            
    {
                OnMouseUp(
    new MouseEventArgs(button, 0000));
                
    if (!doubleClick)
                
    {
                    OnClick(EventArgs.Empty);
                }

                doubleClick 
    = false;
            }


            
    private void WmTaskbarCreated(ref Message m)
            
    {
                added 
    = false;
                UpdateIcon(visible);
            }


            
    private void WndProc(ref Message msg)
            
    {
                
    if(!OnDoWndProc(ref msg))return//中断消息
                Console.WriteLine(msg.Msg);
                
    switch (msg.Msg)
                
    {
                    
    case 0x2b://WM_DRAWITEM
                        break;
                    
    case 0x2c://WM_MEASUREITEM
                        break;
                    
    case 0x111://WM_COMMAND
                        if (IntPtr.Zero == msg.LParam)
                        
    {
                            Type typeCmd 
    = typeof(Form).Assembly.GetType("System.Windows.Forms.Command");
                            MethodInfo methodDispId 
    = typeCmd.GetMethod("DispatchID", BindingFlags.Static | BindingFlags.Public);
                            
    int code = ((int)msg.WParam) & 0xffff;
                            
    bool res = (bool)methodDispId.Invoke(nullnew object[]{code});
                            
    break;
                        }

                        window.DefWndProc(
    ref msg);
                        
    return;
                    
    case 0x800://WM_TRAYMOUSEMESSAGE:
                        switch ((int)msg.LParam)
                        
    {
                            
    case WM_MOUSEMOVE:
                                
    this.WmMouseMove(ref msg);
                                
    return;

                            
    case WM_LBUTTONDOWN:
                                
    this.WmMouseDown(ref msg, MouseButtons.Left, 1);
                                
    return;

                            
    case WM_LBUTTONUP:
                                
    this.WmMouseUp(ref msg, MouseButtons.Left);
                                
    return;

                            
    case WM_LBUTTONDBLCLK:
                                
    this.WmMouseDown(ref msg, MouseButtons.Left, 2);
                                
    return;

                            
    case WM_RBUTTONDOWN:
                                
    this.WmMouseDown(ref msg, MouseButtons.Right, 1);
                                
    return;

                            
    case WM_RBUTTONUP:
                                
    if (this.contextMenu != null)
                                
    {
                                    
    this.ShowContextMenu();
                                }

                                
    this.WmMouseUp(ref msg, MouseButtons.Right);
                                
    return;

                            
    case WM_RBUTTONDBLCLK:
                                
    this.WmMouseDown(ref msg, MouseButtons.Right, 2);
                                
    return;

                            
    case WM_MBUTTONDOWN:
                                
    this.WmMouseDown(ref msg, MouseButtons.Middle, 1);
                                
    return;

                            
    case WM_MBUTTONUP:
                                
    this.WmMouseUp(ref msg, MouseButtons.Middle);
                                
    return;

                            
    case WM_MBUTTONDBLCLK:
                                
    this.WmMouseDown(ref msg, MouseButtons.Middle, 2);
                                
    return;

                            
    case NIN_BALLOONSHOW:
                                
    this.OnBalloonTipShown();
                                
    return;

                            
    case NIN_BALLOONHIDE:
                                
    this.OnBalloonTipClosed();
                                
    return;

                            
    case NIN_BALLOONTIMEOUT:
                                
    this.OnBalloonTipClosed();
                                
    return;

                            
    case NIN_BALLOONUSERCLICK:
                                
    this.OnBalloonTipClicked();
                                
    return;

                            }

                        
    return;
                    
    default:
                        
    if (msg.Msg == WM_TASKBARCREATED)
                        
    {
                            WmTaskbarCreated(
    ref msg);
                        }

                        window.DefWndProc(
    ref msg);
                        
    break;
                }

            }


            
    private class NotifyIconNativeWindow : NativeWindow
            
    {
                
    internal NotifyIcon reference;
                
    private GCHandle rootRef;

                
    internal NotifyIconNativeWindow(NotifyIcon control)
                
    {
                    reference 
    = control;
                }


                
    ~ NotifyIconNativeWindow()
                
    {
                    
    if (base.Handle != IntPtr.Zero)
                    
    {
                        PostMessage(
    new HandleRef(thisbase.Handle), 1600);
                    }

                }


                
    public void LockReference(bool locked)
                
    {
                    
    if (locked)
                    
    {
                        
    if (!rootRef.IsAllocated)
                        
    {
                            rootRef 
    = GCHandle.Alloc(reference, GCHandleType.Normal);
                        }

                    }

                    
    else if (rootRef.IsAllocated)
                    
    {
                        rootRef.Free();
                    }

                }


                
    protected override void OnThreadException(Exception e)
                
    {
                    Application.OnThreadException(e);
                }


                
    protected override void WndProc(ref Message m)
                
    {
                    reference.WndProc(
    ref m);
                }

            }

        }

        
        [Flags]
        
    public enum ToolTipIcon
        
    {
            None 
    = 0,
            Info 
    = 1,
            Warning 
    = 2,
            Error 
    = 3
        }


        
    public delegate bool WndProcEventHandler (object sender, ref Message m);

    }

    比如使用它可以使程序只运行一个实例:
    [STAThread]  
    static void Main(params string[] pars)   
    {  
    //确保只有一个实例运行  
    Process current = Process.GetCurrentProcess();  
    Process[] ps 
    = Process.GetProcessesByName(current.ProcessName);  
    foreach(Process process in ps)  
    {  
    if(!process.Id.Equals(current.Id))  
    {  
    IntPtr nti 
    = FbSoft.Assistant.Controls.NotifyIcon.FindNotifyIcon("NotifyIcon标题");  
    if(nti != IntPtr.Zero)  
    {  
    //向托盘发送自定消息 WM_USER + 0x33;  
    Win32.SendMessage(nti, 0x400 + 0x3300);  
    }
      
    Application.Exit();  
    return;  
    }
      
    }
     frmMain里触发事件:
    private bool ntiMain_DoWndProc(object sender, ref System.Windows.Forms.Message m)  
    {  
    if(m.Msg == 0x400 + 0x33)  
    {  
    ntiMain_DoubleClick(
    nullnull);  
    return false;  
    }
      
    return true;  
    }
      

    private void ntiMain_DoubleClick(object sender, System.EventArgs e)  
    {  
    if(Visible)return;  
    Thread.Sleep(
    100);  
    isLoad 
    = true;  
    if(!ShowInTaskbar)  
    {  
    ShowInTaskbar 
    = true;  
    }
      
    isLoad 
    = false;  
    Win32.SetForegroundWindow(Handle);  
    Win32.SetActiveWindow(Handle);  
    WindowState 
    = FormWindowState.Maximized;  
    Show();  
    }
  • 相关阅读:
    跳出iframe
    leetcode 225. Implement Stack using Queues
    leetcode 206. Reverse Linked List
    leetcode 205. Isomorphic Strings
    leetcode 203. Remove Linked List Elements
    leetcode 198. House Robber
    leetcode 190. Reverse Bits
    leetcode leetcode 783. Minimum Distance Between BST Nodes
    leetcode 202. Happy Number
    leetcode 389. Find the Difference
  • 原文地址:https://www.cnblogs.com/faib/p/1048641.html
Copyright © 2020-2023  润新知