• 一个新的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();  
    }
  • 相关阅读:
    兼容ie6的mvvm框架--san
    Parsing error: The keyword 'export' is reserved && error Parsing error: Unexpected token <
    Call to undefined function openssl_decrypt()
    css 陌生属性
    获取url
    relative 和 absolute
    SSL certificate problem: unable to get local issuer certificate 的解决方法
    使用wamp扩展php时出现服务未启动的解决方法
    php判断是不是移动设备
    js:不是空字符串的空字符串引起的bug
  • 原文地址:https://www.cnblogs.com/faib/p/1048641.html
Copyright © 2020-2023  润新知