sl@94: /* sl@94: sl@94: This Source Code Form is subject to the terms of the Mozilla Public sl@94: License, v. 2.0. If a copy of the MPL was not distributed with this sl@94: file, You can obtain one at http://mozilla.org/MPL/2.0/. sl@94: sl@94: Copyright (C) 2012 Michael Möller sl@94: sl@94: */ sl@94: sl@94: using System; sl@94: using System.ComponentModel; sl@94: using System.Drawing; sl@94: using System.Reflection; sl@94: using System.Runtime.InteropServices; sl@94: using System.Windows.Forms; sl@94: sl@94: namespace SharpDisplayManager sl@94: { sl@94: public class NotifyIconAdv : IDisposable sl@94: { sl@94: private NotifyIcon genericNotifyIcon; sl@94: private NotifyIconWindowsImplementation windowsNotifyIcon; sl@94: sl@94: public NotifyIconAdv() sl@94: { sl@94: int p = (int)Environment.OSVersion.Platform; sl@94: if ((p == 4) || (p == 128)) sl@94: { // Unix sl@94: genericNotifyIcon = new NotifyIcon(); sl@94: } sl@94: else sl@94: { // Windows sl@94: windowsNotifyIcon = new NotifyIconWindowsImplementation(); sl@94: } sl@94: } sl@94: sl@94: public event EventHandler BalloonTipClicked sl@94: { sl@94: add sl@94: { sl@94: if (genericNotifyIcon != null) sl@94: genericNotifyIcon.BalloonTipClicked += value; sl@94: else sl@94: windowsNotifyIcon.BalloonTipClicked += value; sl@94: } sl@94: remove sl@94: { sl@94: if (genericNotifyIcon != null) sl@94: genericNotifyIcon.BalloonTipClicked -= value; sl@94: else sl@94: windowsNotifyIcon.BalloonTipClicked -= value; sl@94: } sl@94: } sl@94: sl@94: public event EventHandler BalloonTipClosed sl@94: { sl@94: add sl@94: { sl@94: if (genericNotifyIcon != null) sl@94: genericNotifyIcon.BalloonTipClosed += value; sl@94: else sl@94: windowsNotifyIcon.BalloonTipClosed += value; sl@94: } sl@94: remove sl@94: { sl@94: if (genericNotifyIcon != null) sl@94: genericNotifyIcon.BalloonTipClosed -= value; sl@94: else sl@94: windowsNotifyIcon.BalloonTipClosed -= value; sl@94: } sl@94: } sl@94: sl@94: public event EventHandler BalloonTipShown sl@94: { sl@94: add sl@94: { sl@94: if (genericNotifyIcon != null) sl@94: genericNotifyIcon.BalloonTipShown += value; sl@94: else sl@94: windowsNotifyIcon.BalloonTipShown += value; sl@94: } sl@94: remove sl@94: { sl@94: if (genericNotifyIcon != null) sl@94: genericNotifyIcon.BalloonTipShown -= value; sl@94: else sl@94: windowsNotifyIcon.BalloonTipShown -= value; sl@94: } sl@94: } sl@94: sl@94: public event EventHandler Click sl@94: { sl@94: add sl@94: { sl@94: if (genericNotifyIcon != null) sl@94: genericNotifyIcon.Click += value; sl@94: else sl@94: windowsNotifyIcon.Click += value; sl@94: } sl@94: remove sl@94: { sl@94: if (genericNotifyIcon != null) sl@94: genericNotifyIcon.Click -= value; sl@94: else sl@94: windowsNotifyIcon.Click -= value; sl@94: } sl@94: } sl@94: sl@94: public event EventHandler DoubleClick sl@94: { sl@94: add sl@94: { sl@94: if (genericNotifyIcon != null) sl@94: genericNotifyIcon.DoubleClick += value; sl@94: else sl@94: windowsNotifyIcon.DoubleClick += value; sl@94: } sl@94: remove sl@94: { sl@94: if (genericNotifyIcon != null) sl@94: genericNotifyIcon.DoubleClick -= value; sl@94: else sl@94: windowsNotifyIcon.DoubleClick -= value; sl@94: } sl@94: } sl@94: sl@94: public event MouseEventHandler MouseClick sl@94: { sl@94: add sl@94: { sl@94: if (genericNotifyIcon != null) sl@94: genericNotifyIcon.MouseClick += value; sl@94: else sl@94: windowsNotifyIcon.MouseClick += value; sl@94: } sl@94: remove sl@94: { sl@94: if (genericNotifyIcon != null) sl@94: genericNotifyIcon.MouseClick -= value; sl@94: else sl@94: windowsNotifyIcon.MouseClick -= value; sl@94: } sl@94: } sl@94: sl@94: public event MouseEventHandler MouseDoubleClick sl@94: { sl@94: add sl@94: { sl@94: if (genericNotifyIcon != null) sl@94: genericNotifyIcon.MouseDoubleClick += value; sl@94: else sl@94: windowsNotifyIcon.MouseDoubleClick += value; sl@94: } sl@94: remove sl@94: { sl@94: if (genericNotifyIcon != null) sl@94: genericNotifyIcon.MouseDoubleClick -= value; sl@94: else sl@94: windowsNotifyIcon.MouseDoubleClick -= value; sl@94: } sl@94: } sl@94: sl@94: public event MouseEventHandler MouseDown sl@94: { sl@94: add sl@94: { sl@94: if (genericNotifyIcon != null) sl@94: genericNotifyIcon.MouseDown += value; sl@94: else sl@94: windowsNotifyIcon.MouseDown += value; sl@94: } sl@94: remove sl@94: { sl@94: if (genericNotifyIcon != null) sl@94: genericNotifyIcon.MouseDown -= value; sl@94: else sl@94: windowsNotifyIcon.MouseDown -= value; sl@94: } sl@94: } sl@94: sl@94: public event MouseEventHandler MouseMove sl@94: { sl@94: add sl@94: { sl@94: if (genericNotifyIcon != null) sl@94: genericNotifyIcon.MouseMove += value; sl@94: else sl@94: windowsNotifyIcon.MouseMove += value; sl@94: } sl@94: remove sl@94: { sl@94: if (genericNotifyIcon != null) sl@94: genericNotifyIcon.MouseMove -= value; sl@94: else sl@94: windowsNotifyIcon.MouseMove -= value; sl@94: } sl@94: } sl@94: sl@94: public event MouseEventHandler MouseUp sl@94: { sl@94: add sl@94: { sl@94: if (genericNotifyIcon != null) sl@94: genericNotifyIcon.MouseUp += value; sl@94: else sl@94: windowsNotifyIcon.MouseUp += value; sl@94: } sl@94: remove sl@94: { sl@94: if (genericNotifyIcon != null) sl@94: genericNotifyIcon.MouseUp -= value; sl@94: else sl@94: windowsNotifyIcon.MouseUp -= value; sl@94: } sl@94: } sl@94: sl@94: public string BalloonTipText sl@94: { sl@94: get sl@94: { sl@94: if (genericNotifyIcon != null) sl@94: return genericNotifyIcon.BalloonTipText; sl@94: else sl@94: return windowsNotifyIcon.BalloonTipText; sl@94: } sl@94: set sl@94: { sl@94: if (genericNotifyIcon != null) sl@94: genericNotifyIcon.BalloonTipText = value; sl@94: else sl@94: windowsNotifyIcon.BalloonTipText = value; sl@94: } sl@94: } sl@94: sl@94: public ToolTipIcon BalloonTipIcon sl@94: { sl@94: get sl@94: { sl@94: if (genericNotifyIcon != null) sl@94: return genericNotifyIcon.BalloonTipIcon; sl@94: else sl@94: return windowsNotifyIcon.BalloonTipIcon; sl@94: } sl@94: set sl@94: { sl@94: if (genericNotifyIcon != null) sl@94: genericNotifyIcon.BalloonTipIcon = value; sl@94: else sl@94: windowsNotifyIcon.BalloonTipIcon = value; sl@94: } sl@94: } sl@94: sl@94: public string BalloonTipTitle sl@94: { sl@94: get sl@94: { sl@94: if (genericNotifyIcon != null) sl@94: return genericNotifyIcon.BalloonTipTitle; sl@94: else sl@94: return windowsNotifyIcon.BalloonTipTitle; sl@94: } sl@94: set sl@94: { sl@94: if (genericNotifyIcon != null) sl@94: genericNotifyIcon.BalloonTipTitle = value; sl@94: else sl@94: windowsNotifyIcon.BalloonTipTitle = value; sl@94: } sl@94: } sl@94: sl@94: public ContextMenu ContextMenu sl@94: { sl@94: get sl@94: { sl@94: if (genericNotifyIcon != null) sl@94: return genericNotifyIcon.ContextMenu; sl@94: else sl@94: return windowsNotifyIcon.ContextMenu; sl@94: } sl@94: set sl@94: { sl@94: if (genericNotifyIcon != null) sl@94: genericNotifyIcon.ContextMenu = value; sl@94: else sl@94: windowsNotifyIcon.ContextMenu = value; sl@94: } sl@94: } sl@94: sl@94: public ContextMenuStrip ContextMenuStrip sl@94: { sl@94: get sl@94: { sl@94: if (genericNotifyIcon != null) sl@94: return genericNotifyIcon.ContextMenuStrip; sl@94: else sl@94: return windowsNotifyIcon.ContextMenuStrip; sl@94: } sl@94: set sl@94: { sl@94: if (genericNotifyIcon != null) sl@94: genericNotifyIcon.ContextMenuStrip = value; sl@94: else sl@94: windowsNotifyIcon.ContextMenuStrip = value; sl@94: } sl@94: } sl@94: sl@94: public object Tag { get; set; } sl@94: sl@94: public Icon Icon sl@94: { sl@94: get sl@94: { sl@94: if (genericNotifyIcon != null) sl@94: return genericNotifyIcon.Icon; sl@94: else sl@94: return windowsNotifyIcon.Icon; sl@94: } sl@94: set sl@94: { sl@94: if (genericNotifyIcon != null) sl@94: genericNotifyIcon.Icon = value; sl@94: else sl@94: windowsNotifyIcon.Icon = value; sl@94: } sl@94: } sl@94: sl@94: public string Text sl@94: { sl@94: get sl@94: { sl@94: if (genericNotifyIcon != null) sl@94: return genericNotifyIcon.Text; sl@94: else sl@94: return windowsNotifyIcon.Text; sl@94: } sl@94: set sl@94: { sl@94: if (genericNotifyIcon != null) sl@94: genericNotifyIcon.Text = value; sl@94: else sl@94: windowsNotifyIcon.Text = value; sl@94: } sl@94: } sl@94: sl@94: public bool Visible sl@94: { sl@94: get sl@94: { sl@94: if (genericNotifyIcon != null) sl@94: return genericNotifyIcon.Visible; sl@94: else sl@94: return windowsNotifyIcon.Visible; sl@94: } sl@94: set sl@94: { sl@94: if (genericNotifyIcon != null) sl@94: genericNotifyIcon.Visible = value; sl@94: else sl@94: windowsNotifyIcon.Visible = value; sl@94: } sl@94: } sl@94: sl@94: public void Dispose() sl@94: { sl@94: if (genericNotifyIcon != null) sl@94: genericNotifyIcon.Dispose(); sl@94: else sl@94: windowsNotifyIcon.Dispose(); sl@94: } sl@94: sl@94: public void ShowBalloonTip(int timeout) sl@94: { sl@94: ShowBalloonTip(timeout, BalloonTipTitle, BalloonTipText, BalloonTipIcon); sl@94: } sl@94: sl@94: public void ShowBalloonTip(int timeout, string tipTitle, string tipText, sl@94: ToolTipIcon tipIcon) sl@94: { sl@94: if (genericNotifyIcon != null) sl@94: genericNotifyIcon.ShowBalloonTip(timeout, tipTitle, tipText, tipIcon); sl@94: else sl@94: windowsNotifyIcon.ShowBalloonTip(timeout, tipTitle, tipText, tipIcon); sl@94: } sl@94: sl@94: private class NotifyIconWindowsImplementation : Component sl@94: { sl@94: private static int nextId = 0; sl@94: sl@94: private object syncObj = new object(); sl@94: private Icon icon; sl@94: private string text = ""; sl@94: private int id; sl@94: private bool created; sl@94: private NotifyIconNativeWindow window; sl@94: private bool doubleClickDown; sl@94: private bool visible; sl@94: private MethodInfo commandDispatch; sl@94: sl@94: public event EventHandler BalloonTipClicked; sl@94: sl@94: public event EventHandler BalloonTipClosed; sl@94: sl@94: public event EventHandler BalloonTipShown; sl@94: sl@94: public event EventHandler Click; sl@94: sl@94: public event EventHandler DoubleClick; sl@94: sl@94: public event MouseEventHandler MouseClick; sl@94: sl@94: public event MouseEventHandler MouseDoubleClick; sl@94: sl@94: public event MouseEventHandler MouseDown; sl@94: sl@94: public event MouseEventHandler MouseMove; sl@94: sl@94: public event MouseEventHandler MouseUp; sl@94: sl@94: public string BalloonTipText { get; set; } sl@94: sl@94: public ToolTipIcon BalloonTipIcon { get; set; } sl@94: sl@94: public string BalloonTipTitle { get; set; } sl@94: sl@94: public ContextMenu ContextMenu { get; set; } sl@94: sl@94: public ContextMenuStrip ContextMenuStrip { get; set; } sl@94: sl@94: public object Tag { get; set; } sl@94: sl@94: public Icon Icon sl@94: { sl@94: get sl@94: { sl@94: return icon; sl@94: } sl@94: set sl@94: { sl@94: if (icon != value) sl@94: { sl@94: icon = value; sl@94: UpdateNotifyIcon(visible); sl@94: } sl@94: } sl@94: } sl@94: sl@94: public string Text sl@94: { sl@94: get sl@94: { sl@94: return text; sl@94: } sl@94: set sl@94: { sl@94: if (value == null) sl@94: value = ""; sl@94: sl@94: if (value.Length > 63) sl@94: throw new ArgumentOutOfRangeException(); sl@94: sl@94: if (!value.Equals(text)) sl@94: { sl@94: text = value; sl@94: sl@94: if (visible) sl@94: UpdateNotifyIcon(visible); sl@94: } sl@94: } sl@94: } sl@94: sl@94: public bool Visible sl@94: { sl@94: get sl@94: { sl@94: return visible; sl@94: } sl@94: set sl@94: { sl@94: if (visible != value) sl@94: { sl@94: visible = value; sl@94: UpdateNotifyIcon(visible); sl@94: } sl@94: } sl@94: } sl@94: sl@94: public NotifyIconWindowsImplementation() sl@94: { sl@94: BalloonTipText = ""; sl@94: BalloonTipTitle = ""; sl@94: sl@94: commandDispatch = typeof(Form).Assembly. sl@94: GetType("System.Windows.Forms.Command").GetMethod("DispatchID", sl@94: BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public, sl@94: null, new Type[] { typeof(int) }, null); sl@94: sl@94: id = ++NotifyIconWindowsImplementation.nextId; sl@94: window = new NotifyIconNativeWindow(this); sl@94: UpdateNotifyIcon(visible); sl@94: } sl@94: sl@94: protected override void Dispose(bool disposing) sl@94: { sl@94: if (disposing) sl@94: { sl@94: if (window != null) sl@94: { sl@94: icon = null; sl@94: text = ""; sl@94: UpdateNotifyIcon(false); sl@94: window.DestroyHandle(); sl@94: window = null; sl@94: ContextMenu = null; sl@94: ContextMenuStrip = null; sl@94: } sl@94: } sl@94: else sl@94: { sl@94: if (window != null && window.Handle != IntPtr.Zero) sl@94: { sl@94: NativeMethods.PostMessage( sl@94: new HandleRef(window, window.Handle), WM_CLOSE, 0, 0); sl@94: window.ReleaseHandle(); sl@94: } sl@94: } sl@94: base.Dispose(disposing); sl@94: } sl@94: sl@94: public void ShowBalloonTip(int timeout) sl@94: { sl@94: ShowBalloonTip(timeout, BalloonTipTitle, BalloonTipText, BalloonTipIcon); sl@94: } sl@94: sl@94: public void ShowBalloonTip(int timeout, string tipTitle, string tipText, sl@94: ToolTipIcon tipIcon) sl@94: { sl@94: if (timeout < 0) sl@94: throw new ArgumentOutOfRangeException("timeout"); sl@94: sl@94: if (string.IsNullOrEmpty(tipText)) sl@94: throw new ArgumentException("tipText"); sl@94: sl@94: if (DesignMode) sl@94: return; sl@94: sl@94: if (created) sl@94: { sl@94: NativeMethods.NotifyIconData data = new NativeMethods.NotifyIconData(); sl@94: if (window.Handle == IntPtr.Zero) sl@94: window.CreateHandle(new CreateParams()); sl@94: sl@94: data.Window = window.Handle; sl@94: data.ID = id; sl@94: data.Flags = NativeMethods.NotifyIconDataFlags.Info; sl@94: data.TimeoutOrVersion = timeout; sl@94: data.InfoTitle = tipTitle; sl@94: data.Info = tipText; sl@94: data.InfoFlags = (int)tipIcon; sl@94: sl@94: NativeMethods.Shell_NotifyIcon( sl@94: NativeMethods.NotifyIconMessage.Modify, data); sl@94: } sl@94: } sl@94: sl@94: private void ShowContextMenu() sl@94: { sl@94: if (ContextMenu == null && ContextMenuStrip == null) sl@94: return; sl@94: sl@94: NativeMethods.Point p = new NativeMethods.Point(); sl@94: NativeMethods.GetCursorPos(ref p); sl@94: NativeMethods.SetForegroundWindow( sl@94: new HandleRef(window, window.Handle)); sl@94: sl@94: if (ContextMenu != null) sl@94: { sl@94: ContextMenu.GetType().InvokeMember("OnPopup", sl@94: BindingFlags.NonPublic | BindingFlags.InvokeMethod | sl@94: BindingFlags.Instance, null, ContextMenu, sl@94: new Object[] { System.EventArgs.Empty }); sl@94: sl@94: NativeMethods.TrackPopupMenuEx( sl@94: new HandleRef(ContextMenu, ContextMenu.Handle), 72, sl@94: p.x, p.y, new HandleRef(window, window.Handle), sl@94: IntPtr.Zero); sl@94: sl@94: NativeMethods.PostMessage( sl@94: new HandleRef(window, window.Handle), WM_NULL, 0, 0); sl@94: return; sl@94: } sl@94: sl@94: if (ContextMenuStrip != null) sl@94: ContextMenuStrip.GetType().InvokeMember("ShowInTaskbar", sl@94: BindingFlags.NonPublic | BindingFlags.InvokeMethod | sl@94: BindingFlags.Instance, null, ContextMenuStrip, sl@94: new Object[] { p.x, p.y }); sl@94: } sl@94: sl@94: private void UpdateNotifyIcon(bool showNotifyIcon) sl@94: { sl@94: if (DesignMode) sl@94: return; sl@94: sl@94: lock (syncObj) sl@94: { sl@94: window.LockReference(showNotifyIcon); sl@94: sl@94: NativeMethods.NotifyIconData data = new NativeMethods.NotifyIconData(); sl@94: data.CallbackMessage = WM_TRAYMOUSEMESSAGE; sl@94: data.Flags = NativeMethods.NotifyIconDataFlags.Message; sl@94: sl@94: if (showNotifyIcon && window.Handle == IntPtr.Zero) sl@94: window.CreateHandle(new CreateParams()); sl@94: sl@94: data.Window = window.Handle; sl@94: data.ID = id; sl@94: sl@94: if (icon != null) sl@94: { sl@94: data.Flags |= NativeMethods.NotifyIconDataFlags.Icon; sl@94: data.Icon = icon.Handle; sl@94: } sl@94: sl@94: data.Flags |= NativeMethods.NotifyIconDataFlags.Tip; sl@94: data.Tip = text; sl@94: sl@94: if (showNotifyIcon && icon != null) sl@94: { sl@94: if (!created) sl@94: { sl@94: int i = 0; sl@94: do sl@94: { sl@94: created = NativeMethods.Shell_NotifyIcon( sl@94: NativeMethods.NotifyIconMessage.Add, data); sl@94: if (!created) sl@94: { sl@94: System.Threading.Thread.Sleep(200); sl@94: i++; sl@94: } sl@94: } while (!created && i < 40); sl@94: } sl@94: else sl@94: { sl@94: NativeMethods.Shell_NotifyIcon( sl@94: NativeMethods.NotifyIconMessage.Modify, data); sl@94: } sl@94: } sl@94: else sl@94: { sl@94: if (created) sl@94: { sl@94: int i = 0; sl@94: bool deleted = false; sl@94: do sl@94: { sl@94: deleted = NativeMethods.Shell_NotifyIcon( sl@94: NativeMethods.NotifyIconMessage.Delete, data); sl@94: if (!deleted) sl@94: { sl@94: System.Threading.Thread.Sleep(200); sl@94: i++; sl@94: } sl@94: } while (!deleted && i < 40); sl@94: created = false; sl@94: } sl@94: } sl@94: } sl@94: } sl@94: sl@94: private void ProcessMouseDown(ref Message message, MouseButtons button, sl@94: bool doubleClick) sl@94: { sl@94: if (doubleClick) sl@94: { sl@94: if (DoubleClick != null) sl@94: DoubleClick(this, new MouseEventArgs(button, 2, 0, 0, 0)); sl@94: sl@94: if (MouseDoubleClick != null) sl@94: MouseDoubleClick(this, new MouseEventArgs(button, 2, 0, 0, 0)); sl@94: sl@94: doubleClickDown = true; sl@94: } sl@94: sl@94: if (MouseDown != null) sl@94: MouseDown(this, sl@94: new MouseEventArgs(button, doubleClick ? 2 : 1, 0, 0, 0)); sl@94: } sl@94: sl@94: private void ProcessMouseUp(ref Message message, MouseButtons button) sl@94: { sl@94: if (MouseUp != null) sl@94: MouseUp(this, new MouseEventArgs(button, 0, 0, 0, 0)); sl@94: sl@94: if (!doubleClickDown) sl@94: { sl@94: if (Click != null) sl@94: Click(this, new MouseEventArgs(button, 0, 0, 0, 0)); sl@94: sl@94: if (MouseClick != null) sl@94: MouseClick(this, new MouseEventArgs(button, 0, 0, 0, 0)); sl@94: } sl@94: doubleClickDown = false; sl@94: } sl@94: sl@94: private void ProcessInitMenuPopup(ref Message message) sl@94: { sl@94: if (ContextMenu != null && sl@94: (bool)ContextMenu.GetType().InvokeMember("ProcessInitMenuPopup", sl@94: BindingFlags.NonPublic | BindingFlags.InvokeMethod | sl@94: BindingFlags.Instance, null, ContextMenu, sl@94: new Object[] { message.WParam })) sl@94: { sl@94: return; sl@94: } sl@94: window.DefWndProc(ref message); sl@94: } sl@94: sl@94: private void WndProc(ref Message message) sl@94: { sl@94: switch (message.Msg) sl@94: { sl@94: case WM_DESTROY: sl@94: UpdateNotifyIcon(false); sl@94: return; sl@94: sl@94: case WM_COMMAND: sl@94: if (message.LParam != IntPtr.Zero) sl@94: { sl@94: window.DefWndProc(ref message); sl@94: return; sl@94: } sl@94: commandDispatch.Invoke(null, new object[] { sl@94: message.WParam.ToInt32() & 0xFFFF }); sl@94: return; sl@94: sl@94: case WM_INITMENUPOPUP: sl@94: ProcessInitMenuPopup(ref message); sl@94: return; sl@94: sl@94: case WM_TRAYMOUSEMESSAGE: sl@94: switch ((int)message.LParam) sl@94: { sl@94: case WM_MOUSEMOVE: sl@94: if (MouseMove != null) sl@94: MouseMove(this, sl@94: new MouseEventArgs(Control.MouseButtons, 0, 0, 0, 0)); sl@94: return; sl@94: sl@94: case WM_LBUTTONDOWN: sl@94: ProcessMouseDown(ref message, MouseButtons.Left, false); sl@94: return; sl@94: sl@94: case WM_LBUTTONUP: sl@94: ProcessMouseUp(ref message, MouseButtons.Left); sl@94: return; sl@94: sl@94: case WM_LBUTTONDBLCLK: sl@94: ProcessMouseDown(ref message, MouseButtons.Left, true); sl@94: return; sl@94: sl@94: case WM_RBUTTONDOWN: sl@94: ProcessMouseDown(ref message, MouseButtons.Right, false); sl@94: return; sl@94: sl@94: case WM_RBUTTONUP: sl@94: if (ContextMenu != null || ContextMenuStrip != null) sl@94: ShowContextMenu(); sl@94: ProcessMouseUp(ref message, MouseButtons.Right); sl@94: return; sl@94: sl@94: case WM_RBUTTONDBLCLK: sl@94: ProcessMouseDown(ref message, MouseButtons.Right, true); sl@94: return; sl@94: sl@94: case WM_MBUTTONDOWN: sl@94: ProcessMouseDown(ref message, MouseButtons.Middle, false); sl@94: return; sl@94: sl@94: case WM_MBUTTONUP: sl@94: ProcessMouseUp(ref message, MouseButtons.Middle); sl@94: return; sl@94: sl@94: case WM_MBUTTONDBLCLK: sl@94: ProcessMouseDown(ref message, MouseButtons.Middle, true); sl@94: return; sl@94: sl@94: case NIN_BALLOONSHOW: sl@94: if (BalloonTipShown != null) sl@94: BalloonTipShown(this, EventArgs.Empty); sl@94: return; sl@94: sl@94: case NIN_BALLOONHIDE: sl@94: case NIN_BALLOONTIMEOUT: sl@94: if (BalloonTipClosed != null) sl@94: BalloonTipClosed(this, EventArgs.Empty); sl@94: return; sl@94: sl@94: case NIN_BALLOONUSERCLICK: sl@94: if (BalloonTipClicked != null) sl@94: BalloonTipClicked(this, EventArgs.Empty); sl@94: return; sl@94: sl@94: default: sl@94: return; sl@94: } sl@94: } sl@94: sl@94: if (message.Msg == NotifyIconWindowsImplementation.WM_TASKBARCREATED) sl@94: { sl@94: lock (syncObj) sl@94: { sl@94: created = false; sl@94: } sl@94: UpdateNotifyIcon(visible); sl@94: } sl@94: sl@94: window.DefWndProc(ref message); sl@94: } sl@94: sl@94: private class NotifyIconNativeWindow : NativeWindow sl@94: { sl@94: private NotifyIconWindowsImplementation reference; sl@94: private GCHandle referenceHandle; sl@94: sl@94: internal NotifyIconNativeWindow(NotifyIconWindowsImplementation component) sl@94: { sl@94: this.reference = component; sl@94: } sl@94: sl@94: ~NotifyIconNativeWindow() sl@94: { sl@94: if (base.Handle != IntPtr.Zero) sl@94: NativeMethods.PostMessage( sl@94: new HandleRef(this, base.Handle), WM_CLOSE, 0, 0); sl@94: } sl@94: sl@94: public void LockReference(bool locked) sl@94: { sl@94: if (locked) sl@94: { sl@94: if (!referenceHandle.IsAllocated) sl@94: { sl@94: referenceHandle = GCHandle.Alloc(reference, GCHandleType.Normal); sl@94: return; sl@94: } sl@94: } sl@94: else sl@94: { sl@94: if (referenceHandle.IsAllocated) sl@94: referenceHandle.Free(); sl@94: } sl@94: } sl@94: sl@94: protected override void OnThreadException(Exception e) sl@94: { sl@94: Application.OnThreadException(e); sl@94: } sl@94: sl@94: protected override void WndProc(ref Message m) sl@94: { sl@94: reference.WndProc(ref m); sl@94: } sl@94: } sl@94: sl@94: private const int WM_NULL = 0x00; sl@94: private const int WM_DESTROY = 0x02; sl@94: private const int WM_CLOSE = 0x10; sl@94: private const int WM_COMMAND = 0x111; sl@94: private const int WM_INITMENUPOPUP = 0x117; sl@94: private const int WM_MOUSEMOVE = 0x200; sl@94: private const int WM_LBUTTONDOWN = 0x201; sl@94: private const int WM_LBUTTONUP = 0x202; sl@94: private const int WM_LBUTTONDBLCLK = 0x203; sl@94: private const int WM_RBUTTONDOWN = 0x204; sl@94: private const int WM_RBUTTONUP = 0x205; sl@94: private const int WM_RBUTTONDBLCLK = 0x206; sl@94: private const int WM_MBUTTONDOWN = 0x207; sl@94: private const int WM_MBUTTONUP = 0x208; sl@94: private const int WM_MBUTTONDBLCLK = 0x209; sl@94: private const int WM_TRAYMOUSEMESSAGE = 0x800; sl@94: sl@94: private const int NIN_BALLOONSHOW = 0x402; sl@94: private const int NIN_BALLOONHIDE = 0x403; sl@94: private const int NIN_BALLOONTIMEOUT = 0x404; sl@94: private const int NIN_BALLOONUSERCLICK = 0x405; sl@94: sl@94: private static int WM_TASKBARCREATED = sl@94: NativeMethods.RegisterWindowMessage("TaskbarCreated"); sl@94: sl@94: private static class NativeMethods sl@94: { sl@94: [DllImport("user32.dll", CharSet = CharSet.Auto)] sl@94: public static extern IntPtr PostMessage(HandleRef hwnd, int msg, sl@94: int wparam, int lparam); sl@94: sl@94: [DllImport("user32.dll", CharSet = CharSet.Auto)] sl@94: public static extern int RegisterWindowMessage(string msg); sl@94: sl@94: [Flags] sl@94: public enum NotifyIconDataFlags : int sl@94: { sl@94: Message = 0x1, sl@94: Icon = 0x2, sl@94: Tip = 0x4, sl@94: State = 0x8, sl@94: Info = 0x10 sl@94: } sl@94: sl@94: [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)] sl@94: public class NotifyIconData sl@94: { sl@94: private int Size = Marshal.SizeOf(typeof(NotifyIconData)); sl@94: public IntPtr Window; sl@94: public int ID; sl@94: public NotifyIconDataFlags Flags; sl@94: public int CallbackMessage; sl@94: public IntPtr Icon; sl@94: sl@94: [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)] sl@94: public string Tip; sl@94: sl@94: public int State; sl@94: public int StateMask; sl@94: sl@94: [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)] sl@94: public string Info; sl@94: sl@94: public int TimeoutOrVersion; sl@94: sl@94: [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 64)] sl@94: public string InfoTitle; sl@94: sl@94: public int InfoFlags; sl@94: } sl@94: sl@94: public enum NotifyIconMessage : int sl@94: { sl@94: Add = 0x0, sl@94: Modify = 0x1, sl@94: Delete = 0x2 sl@94: } sl@94: sl@94: [DllImport("shell32.dll", CharSet = CharSet.Auto)] sl@94: [return: MarshalAs(UnmanagedType.Bool)] sl@94: public static extern bool Shell_NotifyIcon(NotifyIconMessage message, sl@94: NotifyIconData pnid); sl@94: sl@94: [DllImport("user32.dll", CharSet = CharSet.Auto, ExactSpelling = true)] sl@94: public static extern bool TrackPopupMenuEx(HandleRef hmenu, int fuFlags, sl@94: int x, int y, HandleRef hwnd, IntPtr tpm); sl@94: sl@94: [StructLayout(LayoutKind.Sequential)] sl@94: public struct Point sl@94: { sl@94: public int x; sl@94: public int y; sl@94: } sl@94: sl@94: [DllImport("user32.dll", CharSet = CharSet.Auto, ExactSpelling = true)] sl@94: public static extern bool GetCursorPos(ref Point point); sl@94: sl@94: [DllImport("user32.dll", CharSet = CharSet.Auto, ExactSpelling = true)] sl@94: public static extern bool SetForegroundWindow(HandleRef hWnd); sl@94: } sl@94: } sl@94: } sl@94: }