Server/NotifyIconAdv.cs
changeset 94 fe939a729030
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/Server/NotifyIconAdv.cs	Sun Jan 18 18:11:32 2015 +0100
     1.3 @@ -0,0 +1,969 @@
     1.4 +/*
     1.5 +
     1.6 +  This Source Code Form is subject to the terms of the Mozilla Public
     1.7 +  License, v. 2.0. If a copy of the MPL was not distributed with this
     1.8 +  file, You can obtain one at http://mozilla.org/MPL/2.0/.
     1.9 +
    1.10 +  Copyright (C) 2012 Michael Möller <mmoeller@openhardwaremonitor.org>
    1.11 +
    1.12 +*/
    1.13 +
    1.14 +using System;
    1.15 +using System.ComponentModel;
    1.16 +using System.Drawing;
    1.17 +using System.Reflection;
    1.18 +using System.Runtime.InteropServices;
    1.19 +using System.Windows.Forms;
    1.20 +
    1.21 +namespace SharpDisplayManager
    1.22 +{
    1.23 +	public class NotifyIconAdv : IDisposable
    1.24 +	{
    1.25 +		private NotifyIcon genericNotifyIcon;
    1.26 +		private NotifyIconWindowsImplementation windowsNotifyIcon;
    1.27 +
    1.28 +		public NotifyIconAdv()
    1.29 +		{
    1.30 +			int p = (int)Environment.OSVersion.Platform;
    1.31 +			if ((p == 4) || (p == 128))
    1.32 +			{ // Unix
    1.33 +				genericNotifyIcon = new NotifyIcon();
    1.34 +			}
    1.35 +			else
    1.36 +			{ // Windows
    1.37 +				windowsNotifyIcon = new NotifyIconWindowsImplementation();
    1.38 +			}
    1.39 +		}
    1.40 +
    1.41 +		public event EventHandler BalloonTipClicked
    1.42 +		{
    1.43 +			add
    1.44 +			{
    1.45 +				if (genericNotifyIcon != null)
    1.46 +					genericNotifyIcon.BalloonTipClicked += value;
    1.47 +				else
    1.48 +					windowsNotifyIcon.BalloonTipClicked += value;
    1.49 +			}
    1.50 +			remove
    1.51 +			{
    1.52 +				if (genericNotifyIcon != null)
    1.53 +					genericNotifyIcon.BalloonTipClicked -= value;
    1.54 +				else
    1.55 +					windowsNotifyIcon.BalloonTipClicked -= value;
    1.56 +			}
    1.57 +		}
    1.58 +
    1.59 +		public event EventHandler BalloonTipClosed
    1.60 +		{
    1.61 +			add
    1.62 +			{
    1.63 +				if (genericNotifyIcon != null)
    1.64 +					genericNotifyIcon.BalloonTipClosed += value;
    1.65 +				else
    1.66 +					windowsNotifyIcon.BalloonTipClosed += value;
    1.67 +			}
    1.68 +			remove
    1.69 +			{
    1.70 +				if (genericNotifyIcon != null)
    1.71 +					genericNotifyIcon.BalloonTipClosed -= value;
    1.72 +				else
    1.73 +					windowsNotifyIcon.BalloonTipClosed -= value;
    1.74 +			}
    1.75 +		}
    1.76 +
    1.77 +		public event EventHandler BalloonTipShown
    1.78 +		{
    1.79 +			add
    1.80 +			{
    1.81 +				if (genericNotifyIcon != null)
    1.82 +					genericNotifyIcon.BalloonTipShown += value;
    1.83 +				else
    1.84 +					windowsNotifyIcon.BalloonTipShown += value;
    1.85 +			}
    1.86 +			remove
    1.87 +			{
    1.88 +				if (genericNotifyIcon != null)
    1.89 +					genericNotifyIcon.BalloonTipShown -= value;
    1.90 +				else
    1.91 +					windowsNotifyIcon.BalloonTipShown -= value;
    1.92 +			}
    1.93 +		}
    1.94 +
    1.95 +		public event EventHandler Click
    1.96 +		{
    1.97 +			add
    1.98 +			{
    1.99 +				if (genericNotifyIcon != null)
   1.100 +					genericNotifyIcon.Click += value;
   1.101 +				else
   1.102 +					windowsNotifyIcon.Click += value;
   1.103 +			}
   1.104 +			remove
   1.105 +			{
   1.106 +				if (genericNotifyIcon != null)
   1.107 +					genericNotifyIcon.Click -= value;
   1.108 +				else
   1.109 +					windowsNotifyIcon.Click -= value;
   1.110 +			}
   1.111 +		}
   1.112 +
   1.113 +		public event EventHandler DoubleClick
   1.114 +		{
   1.115 +			add
   1.116 +			{
   1.117 +				if (genericNotifyIcon != null)
   1.118 +					genericNotifyIcon.DoubleClick += value;
   1.119 +				else
   1.120 +					windowsNotifyIcon.DoubleClick += value;
   1.121 +			}
   1.122 +			remove
   1.123 +			{
   1.124 +				if (genericNotifyIcon != null)
   1.125 +					genericNotifyIcon.DoubleClick -= value;
   1.126 +				else
   1.127 +					windowsNotifyIcon.DoubleClick -= value;
   1.128 +			}
   1.129 +		}
   1.130 +
   1.131 +		public event MouseEventHandler MouseClick
   1.132 +		{
   1.133 +			add
   1.134 +			{
   1.135 +				if (genericNotifyIcon != null)
   1.136 +					genericNotifyIcon.MouseClick += value;
   1.137 +				else
   1.138 +					windowsNotifyIcon.MouseClick += value;
   1.139 +			}
   1.140 +			remove
   1.141 +			{
   1.142 +				if (genericNotifyIcon != null)
   1.143 +					genericNotifyIcon.MouseClick -= value;
   1.144 +				else
   1.145 +					windowsNotifyIcon.MouseClick -= value;
   1.146 +			}
   1.147 +		}
   1.148 +
   1.149 +		public event MouseEventHandler MouseDoubleClick
   1.150 +		{
   1.151 +			add
   1.152 +			{
   1.153 +				if (genericNotifyIcon != null)
   1.154 +					genericNotifyIcon.MouseDoubleClick += value;
   1.155 +				else
   1.156 +					windowsNotifyIcon.MouseDoubleClick += value;
   1.157 +			}
   1.158 +			remove
   1.159 +			{
   1.160 +				if (genericNotifyIcon != null)
   1.161 +					genericNotifyIcon.MouseDoubleClick -= value;
   1.162 +				else
   1.163 +					windowsNotifyIcon.MouseDoubleClick -= value;
   1.164 +			}
   1.165 +		}
   1.166 +
   1.167 +		public event MouseEventHandler MouseDown
   1.168 +		{
   1.169 +			add
   1.170 +			{
   1.171 +				if (genericNotifyIcon != null)
   1.172 +					genericNotifyIcon.MouseDown += value;
   1.173 +				else
   1.174 +					windowsNotifyIcon.MouseDown += value;
   1.175 +			}
   1.176 +			remove
   1.177 +			{
   1.178 +				if (genericNotifyIcon != null)
   1.179 +					genericNotifyIcon.MouseDown -= value;
   1.180 +				else
   1.181 +					windowsNotifyIcon.MouseDown -= value;
   1.182 +			}
   1.183 +		}
   1.184 +
   1.185 +		public event MouseEventHandler MouseMove
   1.186 +		{
   1.187 +			add
   1.188 +			{
   1.189 +				if (genericNotifyIcon != null)
   1.190 +					genericNotifyIcon.MouseMove += value;
   1.191 +				else
   1.192 +					windowsNotifyIcon.MouseMove += value;
   1.193 +			}
   1.194 +			remove
   1.195 +			{
   1.196 +				if (genericNotifyIcon != null)
   1.197 +					genericNotifyIcon.MouseMove -= value;
   1.198 +				else
   1.199 +					windowsNotifyIcon.MouseMove -= value;
   1.200 +			}
   1.201 +		}
   1.202 +
   1.203 +		public event MouseEventHandler MouseUp
   1.204 +		{
   1.205 +			add
   1.206 +			{
   1.207 +				if (genericNotifyIcon != null)
   1.208 +					genericNotifyIcon.MouseUp += value;
   1.209 +				else
   1.210 +					windowsNotifyIcon.MouseUp += value;
   1.211 +			}
   1.212 +			remove
   1.213 +			{
   1.214 +				if (genericNotifyIcon != null)
   1.215 +					genericNotifyIcon.MouseUp -= value;
   1.216 +				else
   1.217 +					windowsNotifyIcon.MouseUp -= value;
   1.218 +			}
   1.219 +		}
   1.220 +
   1.221 +		public string BalloonTipText
   1.222 +		{
   1.223 +			get
   1.224 +			{
   1.225 +				if (genericNotifyIcon != null)
   1.226 +					return genericNotifyIcon.BalloonTipText;
   1.227 +				else
   1.228 +					return windowsNotifyIcon.BalloonTipText;
   1.229 +			}
   1.230 +			set
   1.231 +			{
   1.232 +				if (genericNotifyIcon != null)
   1.233 +					genericNotifyIcon.BalloonTipText = value;
   1.234 +				else
   1.235 +					windowsNotifyIcon.BalloonTipText = value;
   1.236 +			}
   1.237 +		}
   1.238 +
   1.239 +		public ToolTipIcon BalloonTipIcon
   1.240 +		{
   1.241 +			get
   1.242 +			{
   1.243 +				if (genericNotifyIcon != null)
   1.244 +					return genericNotifyIcon.BalloonTipIcon;
   1.245 +				else
   1.246 +					return windowsNotifyIcon.BalloonTipIcon;
   1.247 +			}
   1.248 +			set
   1.249 +			{
   1.250 +				if (genericNotifyIcon != null)
   1.251 +					genericNotifyIcon.BalloonTipIcon = value;
   1.252 +				else
   1.253 +					windowsNotifyIcon.BalloonTipIcon = value;
   1.254 +			}
   1.255 +		}
   1.256 +
   1.257 +		public string BalloonTipTitle
   1.258 +		{
   1.259 +			get
   1.260 +			{
   1.261 +				if (genericNotifyIcon != null)
   1.262 +					return genericNotifyIcon.BalloonTipTitle;
   1.263 +				else
   1.264 +					return windowsNotifyIcon.BalloonTipTitle;
   1.265 +			}
   1.266 +			set
   1.267 +			{
   1.268 +				if (genericNotifyIcon != null)
   1.269 +					genericNotifyIcon.BalloonTipTitle = value;
   1.270 +				else
   1.271 +					windowsNotifyIcon.BalloonTipTitle = value;
   1.272 +			}
   1.273 +		}
   1.274 +
   1.275 +		public ContextMenu ContextMenu
   1.276 +		{
   1.277 +			get
   1.278 +			{
   1.279 +				if (genericNotifyIcon != null)
   1.280 +					return genericNotifyIcon.ContextMenu;
   1.281 +				else
   1.282 +					return windowsNotifyIcon.ContextMenu;
   1.283 +			}
   1.284 +			set
   1.285 +			{
   1.286 +				if (genericNotifyIcon != null)
   1.287 +					genericNotifyIcon.ContextMenu = value;
   1.288 +				else
   1.289 +					windowsNotifyIcon.ContextMenu = value;
   1.290 +			}
   1.291 +		}
   1.292 +
   1.293 +		public ContextMenuStrip ContextMenuStrip
   1.294 +		{
   1.295 +			get
   1.296 +			{
   1.297 +				if (genericNotifyIcon != null)
   1.298 +					return genericNotifyIcon.ContextMenuStrip;
   1.299 +				else
   1.300 +					return windowsNotifyIcon.ContextMenuStrip;
   1.301 +			}
   1.302 +			set
   1.303 +			{
   1.304 +				if (genericNotifyIcon != null)
   1.305 +					genericNotifyIcon.ContextMenuStrip = value;
   1.306 +				else
   1.307 +					windowsNotifyIcon.ContextMenuStrip = value;
   1.308 +			}
   1.309 +		}
   1.310 +
   1.311 +		public object Tag { get; set; }
   1.312 +
   1.313 +		public Icon Icon
   1.314 +		{
   1.315 +			get
   1.316 +			{
   1.317 +				if (genericNotifyIcon != null)
   1.318 +					return genericNotifyIcon.Icon;
   1.319 +				else
   1.320 +					return windowsNotifyIcon.Icon;
   1.321 +			}
   1.322 +			set
   1.323 +			{
   1.324 +				if (genericNotifyIcon != null)
   1.325 +					genericNotifyIcon.Icon = value;
   1.326 +				else
   1.327 +					windowsNotifyIcon.Icon = value;
   1.328 +			}
   1.329 +		}
   1.330 +
   1.331 +		public string Text
   1.332 +		{
   1.333 +			get
   1.334 +			{
   1.335 +				if (genericNotifyIcon != null)
   1.336 +					return genericNotifyIcon.Text;
   1.337 +				else
   1.338 +					return windowsNotifyIcon.Text;
   1.339 +			}
   1.340 +			set
   1.341 +			{
   1.342 +				if (genericNotifyIcon != null)
   1.343 +					genericNotifyIcon.Text = value;
   1.344 +				else
   1.345 +					windowsNotifyIcon.Text = value;
   1.346 +			}
   1.347 +		}
   1.348 +
   1.349 +		public bool Visible
   1.350 +		{
   1.351 +			get
   1.352 +			{
   1.353 +				if (genericNotifyIcon != null)
   1.354 +					return genericNotifyIcon.Visible;
   1.355 +				else
   1.356 +					return windowsNotifyIcon.Visible;
   1.357 +			}
   1.358 +			set
   1.359 +			{
   1.360 +				if (genericNotifyIcon != null)
   1.361 +					genericNotifyIcon.Visible = value;
   1.362 +				else
   1.363 +					windowsNotifyIcon.Visible = value;
   1.364 +			}
   1.365 +		}
   1.366 +
   1.367 +		public void Dispose()
   1.368 +		{
   1.369 +			if (genericNotifyIcon != null)
   1.370 +				genericNotifyIcon.Dispose();
   1.371 +			else
   1.372 +				windowsNotifyIcon.Dispose();
   1.373 +		}
   1.374 +
   1.375 +		public void ShowBalloonTip(int timeout)
   1.376 +		{
   1.377 +			ShowBalloonTip(timeout, BalloonTipTitle, BalloonTipText, BalloonTipIcon);
   1.378 +		}
   1.379 +
   1.380 +		public void ShowBalloonTip(int timeout, string tipTitle, string tipText,
   1.381 +		  ToolTipIcon tipIcon)
   1.382 +		{
   1.383 +			if (genericNotifyIcon != null)
   1.384 +				genericNotifyIcon.ShowBalloonTip(timeout, tipTitle, tipText, tipIcon);
   1.385 +			else
   1.386 +				windowsNotifyIcon.ShowBalloonTip(timeout, tipTitle, tipText, tipIcon);
   1.387 +		}
   1.388 +
   1.389 +		private class NotifyIconWindowsImplementation : Component
   1.390 +		{
   1.391 +			private static int nextId = 0;
   1.392 +
   1.393 +			private object syncObj = new object();
   1.394 +			private Icon icon;
   1.395 +			private string text = "";
   1.396 +			private int id;
   1.397 +			private bool created;
   1.398 +			private NotifyIconNativeWindow window;
   1.399 +			private bool doubleClickDown;
   1.400 +			private bool visible;
   1.401 +			private MethodInfo commandDispatch;
   1.402 +
   1.403 +			public event EventHandler BalloonTipClicked;
   1.404 +
   1.405 +			public event EventHandler BalloonTipClosed;
   1.406 +
   1.407 +			public event EventHandler BalloonTipShown;
   1.408 +
   1.409 +			public event EventHandler Click;
   1.410 +
   1.411 +			public event EventHandler DoubleClick;
   1.412 +
   1.413 +			public event MouseEventHandler MouseClick;
   1.414 +
   1.415 +			public event MouseEventHandler MouseDoubleClick;
   1.416 +
   1.417 +			public event MouseEventHandler MouseDown;
   1.418 +
   1.419 +			public event MouseEventHandler MouseMove;
   1.420 +
   1.421 +			public event MouseEventHandler MouseUp;
   1.422 +
   1.423 +			public string BalloonTipText { get; set; }
   1.424 +
   1.425 +			public ToolTipIcon BalloonTipIcon { get; set; }
   1.426 +
   1.427 +			public string BalloonTipTitle { get; set; }
   1.428 +
   1.429 +			public ContextMenu ContextMenu { get; set; }
   1.430 +
   1.431 +			public ContextMenuStrip ContextMenuStrip { get; set; }
   1.432 +
   1.433 +			public object Tag { get; set; }
   1.434 +
   1.435 +			public Icon Icon
   1.436 +			{
   1.437 +				get
   1.438 +				{
   1.439 +					return icon;
   1.440 +				}
   1.441 +				set
   1.442 +				{
   1.443 +					if (icon != value)
   1.444 +					{
   1.445 +						icon = value;
   1.446 +						UpdateNotifyIcon(visible);
   1.447 +					}
   1.448 +				}
   1.449 +			}
   1.450 +
   1.451 +			public string Text
   1.452 +			{
   1.453 +				get
   1.454 +				{
   1.455 +					return text;
   1.456 +				}
   1.457 +				set
   1.458 +				{
   1.459 +					if (value == null)
   1.460 +						value = "";
   1.461 +
   1.462 +					if (value.Length > 63)
   1.463 +						throw new ArgumentOutOfRangeException();
   1.464 +
   1.465 +					if (!value.Equals(text))
   1.466 +					{
   1.467 +						text = value;
   1.468 +
   1.469 +						if (visible)
   1.470 +							UpdateNotifyIcon(visible);
   1.471 +					}
   1.472 +				}
   1.473 +			}
   1.474 +
   1.475 +			public bool Visible
   1.476 +			{
   1.477 +				get
   1.478 +				{
   1.479 +					return visible;
   1.480 +				}
   1.481 +				set
   1.482 +				{
   1.483 +					if (visible != value)
   1.484 +					{
   1.485 +						visible = value;
   1.486 +						UpdateNotifyIcon(visible);
   1.487 +					}
   1.488 +				}
   1.489 +			}
   1.490 +
   1.491 +			public NotifyIconWindowsImplementation()
   1.492 +			{
   1.493 +				BalloonTipText = "";
   1.494 +				BalloonTipTitle = "";
   1.495 +
   1.496 +				commandDispatch = typeof(Form).Assembly.
   1.497 +				  GetType("System.Windows.Forms.Command").GetMethod("DispatchID",
   1.498 +				  BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public,
   1.499 +				  null, new Type[] { typeof(int) }, null);
   1.500 +
   1.501 +				id = ++NotifyIconWindowsImplementation.nextId;
   1.502 +				window = new NotifyIconNativeWindow(this);
   1.503 +				UpdateNotifyIcon(visible);
   1.504 +			}
   1.505 +
   1.506 +			protected override void Dispose(bool disposing)
   1.507 +			{
   1.508 +				if (disposing)
   1.509 +				{
   1.510 +					if (window != null)
   1.511 +					{
   1.512 +						icon = null;
   1.513 +						text = "";
   1.514 +						UpdateNotifyIcon(false);
   1.515 +						window.DestroyHandle();
   1.516 +						window = null;
   1.517 +						ContextMenu = null;
   1.518 +						ContextMenuStrip = null;
   1.519 +					}
   1.520 +				}
   1.521 +				else
   1.522 +				{
   1.523 +					if (window != null && window.Handle != IntPtr.Zero)
   1.524 +					{
   1.525 +						NativeMethods.PostMessage(
   1.526 +						  new HandleRef(window, window.Handle), WM_CLOSE, 0, 0);
   1.527 +						window.ReleaseHandle();
   1.528 +					}
   1.529 +				}
   1.530 +				base.Dispose(disposing);
   1.531 +			}
   1.532 +
   1.533 +			public void ShowBalloonTip(int timeout)
   1.534 +			{
   1.535 +				ShowBalloonTip(timeout, BalloonTipTitle, BalloonTipText, BalloonTipIcon);
   1.536 +			}
   1.537 +
   1.538 +			public void ShowBalloonTip(int timeout, string tipTitle, string tipText,
   1.539 +			  ToolTipIcon tipIcon)
   1.540 +			{
   1.541 +				if (timeout < 0)
   1.542 +					throw new ArgumentOutOfRangeException("timeout");
   1.543 +
   1.544 +				if (string.IsNullOrEmpty(tipText))
   1.545 +					throw new ArgumentException("tipText");
   1.546 +
   1.547 +				if (DesignMode)
   1.548 +					return;
   1.549 +
   1.550 +				if (created)
   1.551 +				{
   1.552 +					NativeMethods.NotifyIconData data = new NativeMethods.NotifyIconData();
   1.553 +					if (window.Handle == IntPtr.Zero)
   1.554 +						window.CreateHandle(new CreateParams());
   1.555 +
   1.556 +					data.Window = window.Handle;
   1.557 +					data.ID = id;
   1.558 +					data.Flags = NativeMethods.NotifyIconDataFlags.Info;
   1.559 +					data.TimeoutOrVersion = timeout;
   1.560 +					data.InfoTitle = tipTitle;
   1.561 +					data.Info = tipText;
   1.562 +					data.InfoFlags = (int)tipIcon;
   1.563 +
   1.564 +					NativeMethods.Shell_NotifyIcon(
   1.565 +					  NativeMethods.NotifyIconMessage.Modify, data);
   1.566 +				}
   1.567 +			}
   1.568 +
   1.569 +			private void ShowContextMenu()
   1.570 +			{
   1.571 +				if (ContextMenu == null && ContextMenuStrip == null)
   1.572 +					return;
   1.573 +
   1.574 +				NativeMethods.Point p = new NativeMethods.Point();
   1.575 +				NativeMethods.GetCursorPos(ref p);
   1.576 +				NativeMethods.SetForegroundWindow(
   1.577 +				  new HandleRef(window, window.Handle));
   1.578 +
   1.579 +				if (ContextMenu != null)
   1.580 +				{
   1.581 +					ContextMenu.GetType().InvokeMember("OnPopup",
   1.582 +					  BindingFlags.NonPublic | BindingFlags.InvokeMethod |
   1.583 +					  BindingFlags.Instance, null, ContextMenu,
   1.584 +					  new Object[] { System.EventArgs.Empty });
   1.585 +
   1.586 +					NativeMethods.TrackPopupMenuEx(
   1.587 +					  new HandleRef(ContextMenu, ContextMenu.Handle), 72,
   1.588 +					  p.x, p.y, new HandleRef(window, window.Handle),
   1.589 +					  IntPtr.Zero);
   1.590 +
   1.591 +					NativeMethods.PostMessage(
   1.592 +					  new HandleRef(window, window.Handle), WM_NULL, 0, 0);
   1.593 +					return;
   1.594 +				}
   1.595 +
   1.596 +				if (ContextMenuStrip != null)
   1.597 +					ContextMenuStrip.GetType().InvokeMember("ShowInTaskbar",
   1.598 +					  BindingFlags.NonPublic | BindingFlags.InvokeMethod |
   1.599 +					  BindingFlags.Instance, null, ContextMenuStrip,
   1.600 +					  new Object[] { p.x, p.y });
   1.601 +			}
   1.602 +
   1.603 +			private void UpdateNotifyIcon(bool showNotifyIcon)
   1.604 +			{
   1.605 +				if (DesignMode)
   1.606 +					return;
   1.607 +
   1.608 +				lock (syncObj)
   1.609 +				{
   1.610 +					window.LockReference(showNotifyIcon);
   1.611 +
   1.612 +					NativeMethods.NotifyIconData data = new NativeMethods.NotifyIconData();
   1.613 +					data.CallbackMessage = WM_TRAYMOUSEMESSAGE;
   1.614 +					data.Flags = NativeMethods.NotifyIconDataFlags.Message;
   1.615 +
   1.616 +					if (showNotifyIcon && window.Handle == IntPtr.Zero)
   1.617 +						window.CreateHandle(new CreateParams());
   1.618 +
   1.619 +					data.Window = window.Handle;
   1.620 +					data.ID = id;
   1.621 +
   1.622 +					if (icon != null)
   1.623 +					{
   1.624 +						data.Flags |= NativeMethods.NotifyIconDataFlags.Icon;
   1.625 +						data.Icon = icon.Handle;
   1.626 +					}
   1.627 +
   1.628 +					data.Flags |= NativeMethods.NotifyIconDataFlags.Tip;
   1.629 +					data.Tip = text;
   1.630 +
   1.631 +					if (showNotifyIcon && icon != null)
   1.632 +					{
   1.633 +						if (!created)
   1.634 +						{
   1.635 +							int i = 0;
   1.636 +							do
   1.637 +							{
   1.638 +								created = NativeMethods.Shell_NotifyIcon(
   1.639 +								  NativeMethods.NotifyIconMessage.Add, data);
   1.640 +								if (!created)
   1.641 +								{
   1.642 +									System.Threading.Thread.Sleep(200);
   1.643 +									i++;
   1.644 +								}
   1.645 +							} while (!created && i < 40);
   1.646 +						}
   1.647 +						else
   1.648 +						{
   1.649 +							NativeMethods.Shell_NotifyIcon(
   1.650 +							  NativeMethods.NotifyIconMessage.Modify, data);
   1.651 +						}
   1.652 +					}
   1.653 +					else
   1.654 +					{
   1.655 +						if (created)
   1.656 +						{
   1.657 +							int i = 0;
   1.658 +							bool deleted = false;
   1.659 +							do
   1.660 +							{
   1.661 +								deleted = NativeMethods.Shell_NotifyIcon(
   1.662 +								  NativeMethods.NotifyIconMessage.Delete, data);
   1.663 +								if (!deleted)
   1.664 +								{
   1.665 +									System.Threading.Thread.Sleep(200);
   1.666 +									i++;
   1.667 +								}
   1.668 +							} while (!deleted && i < 40);
   1.669 +							created = false;
   1.670 +						}
   1.671 +					}
   1.672 +				}
   1.673 +			}
   1.674 +
   1.675 +			private void ProcessMouseDown(ref Message message, MouseButtons button,
   1.676 +			  bool doubleClick)
   1.677 +			{
   1.678 +				if (doubleClick)
   1.679 +				{
   1.680 +					if (DoubleClick != null)
   1.681 +						DoubleClick(this, new MouseEventArgs(button, 2, 0, 0, 0));
   1.682 +
   1.683 +					if (MouseDoubleClick != null)
   1.684 +						MouseDoubleClick(this, new MouseEventArgs(button, 2, 0, 0, 0));
   1.685 +
   1.686 +					doubleClickDown = true;
   1.687 +				}
   1.688 +
   1.689 +				if (MouseDown != null)
   1.690 +					MouseDown(this,
   1.691 +					  new MouseEventArgs(button, doubleClick ? 2 : 1, 0, 0, 0));
   1.692 +			}
   1.693 +
   1.694 +			private void ProcessMouseUp(ref Message message, MouseButtons button)
   1.695 +			{
   1.696 +				if (MouseUp != null)
   1.697 +					MouseUp(this, new MouseEventArgs(button, 0, 0, 0, 0));
   1.698 +
   1.699 +				if (!doubleClickDown)
   1.700 +				{
   1.701 +					if (Click != null)
   1.702 +						Click(this, new MouseEventArgs(button, 0, 0, 0, 0));
   1.703 +
   1.704 +					if (MouseClick != null)
   1.705 +						MouseClick(this, new MouseEventArgs(button, 0, 0, 0, 0));
   1.706 +				}
   1.707 +				doubleClickDown = false;
   1.708 +			}
   1.709 +
   1.710 +			private void ProcessInitMenuPopup(ref Message message)
   1.711 +			{
   1.712 +				if (ContextMenu != null &&
   1.713 +				  (bool)ContextMenu.GetType().InvokeMember("ProcessInitMenuPopup",
   1.714 +					BindingFlags.NonPublic | BindingFlags.InvokeMethod |
   1.715 +					BindingFlags.Instance, null, ContextMenu,
   1.716 +					new Object[] { message.WParam }))
   1.717 +				{
   1.718 +					return;
   1.719 +				}
   1.720 +				window.DefWndProc(ref message);
   1.721 +			}
   1.722 +
   1.723 +			private void WndProc(ref Message message)
   1.724 +			{
   1.725 +				switch (message.Msg)
   1.726 +				{
   1.727 +					case WM_DESTROY:
   1.728 +						UpdateNotifyIcon(false);
   1.729 +						return;
   1.730 +
   1.731 +					case WM_COMMAND:
   1.732 +						if (message.LParam != IntPtr.Zero)
   1.733 +						{
   1.734 +							window.DefWndProc(ref message);
   1.735 +							return;
   1.736 +						}
   1.737 +						commandDispatch.Invoke(null, new object[] {
   1.738 +            message.WParam.ToInt32() & 0xFFFF });
   1.739 +						return;
   1.740 +
   1.741 +					case WM_INITMENUPOPUP:
   1.742 +						ProcessInitMenuPopup(ref message);
   1.743 +						return;
   1.744 +
   1.745 +					case WM_TRAYMOUSEMESSAGE:
   1.746 +						switch ((int)message.LParam)
   1.747 +						{
   1.748 +							case WM_MOUSEMOVE:
   1.749 +								if (MouseMove != null)
   1.750 +									MouseMove(this,
   1.751 +									  new MouseEventArgs(Control.MouseButtons, 0, 0, 0, 0));
   1.752 +								return;
   1.753 +
   1.754 +							case WM_LBUTTONDOWN:
   1.755 +								ProcessMouseDown(ref message, MouseButtons.Left, false);
   1.756 +								return;
   1.757 +
   1.758 +							case WM_LBUTTONUP:
   1.759 +								ProcessMouseUp(ref message, MouseButtons.Left);
   1.760 +								return;
   1.761 +
   1.762 +							case WM_LBUTTONDBLCLK:
   1.763 +								ProcessMouseDown(ref message, MouseButtons.Left, true);
   1.764 +								return;
   1.765 +
   1.766 +							case WM_RBUTTONDOWN:
   1.767 +								ProcessMouseDown(ref message, MouseButtons.Right, false);
   1.768 +								return;
   1.769 +
   1.770 +							case WM_RBUTTONUP:
   1.771 +								if (ContextMenu != null || ContextMenuStrip != null)
   1.772 +									ShowContextMenu();
   1.773 +								ProcessMouseUp(ref message, MouseButtons.Right);
   1.774 +								return;
   1.775 +
   1.776 +							case WM_RBUTTONDBLCLK:
   1.777 +								ProcessMouseDown(ref message, MouseButtons.Right, true);
   1.778 +								return;
   1.779 +
   1.780 +							case WM_MBUTTONDOWN:
   1.781 +								ProcessMouseDown(ref message, MouseButtons.Middle, false);
   1.782 +								return;
   1.783 +
   1.784 +							case WM_MBUTTONUP:
   1.785 +								ProcessMouseUp(ref message, MouseButtons.Middle);
   1.786 +								return;
   1.787 +
   1.788 +							case WM_MBUTTONDBLCLK:
   1.789 +								ProcessMouseDown(ref message, MouseButtons.Middle, true);
   1.790 +								return;
   1.791 +
   1.792 +							case NIN_BALLOONSHOW:
   1.793 +								if (BalloonTipShown != null)
   1.794 +									BalloonTipShown(this, EventArgs.Empty);
   1.795 +								return;
   1.796 +
   1.797 +							case NIN_BALLOONHIDE:
   1.798 +							case NIN_BALLOONTIMEOUT:
   1.799 +								if (BalloonTipClosed != null)
   1.800 +									BalloonTipClosed(this, EventArgs.Empty);
   1.801 +								return;
   1.802 +
   1.803 +							case NIN_BALLOONUSERCLICK:
   1.804 +								if (BalloonTipClicked != null)
   1.805 +									BalloonTipClicked(this, EventArgs.Empty);
   1.806 +								return;
   1.807 +
   1.808 +							default:
   1.809 +								return;
   1.810 +						}
   1.811 +				}
   1.812 +
   1.813 +				if (message.Msg == NotifyIconWindowsImplementation.WM_TASKBARCREATED)
   1.814 +				{
   1.815 +					lock (syncObj)
   1.816 +					{
   1.817 +						created = false;
   1.818 +					}
   1.819 +					UpdateNotifyIcon(visible);
   1.820 +				}
   1.821 +
   1.822 +				window.DefWndProc(ref message);
   1.823 +			}
   1.824 +
   1.825 +			private class NotifyIconNativeWindow : NativeWindow
   1.826 +			{
   1.827 +				private NotifyIconWindowsImplementation reference;
   1.828 +				private GCHandle referenceHandle;
   1.829 +
   1.830 +				internal NotifyIconNativeWindow(NotifyIconWindowsImplementation component)
   1.831 +				{
   1.832 +					this.reference = component;
   1.833 +				}
   1.834 +
   1.835 +				~NotifyIconNativeWindow()
   1.836 +				{
   1.837 +					if (base.Handle != IntPtr.Zero)
   1.838 +						NativeMethods.PostMessage(
   1.839 +						  new HandleRef(this, base.Handle), WM_CLOSE, 0, 0);
   1.840 +				}
   1.841 +
   1.842 +				public void LockReference(bool locked)
   1.843 +				{
   1.844 +					if (locked)
   1.845 +					{
   1.846 +						if (!referenceHandle.IsAllocated)
   1.847 +						{
   1.848 +							referenceHandle = GCHandle.Alloc(reference, GCHandleType.Normal);
   1.849 +							return;
   1.850 +						}
   1.851 +					}
   1.852 +					else
   1.853 +					{
   1.854 +						if (referenceHandle.IsAllocated)
   1.855 +							referenceHandle.Free();
   1.856 +					}
   1.857 +				}
   1.858 +
   1.859 +				protected override void OnThreadException(Exception e)
   1.860 +				{
   1.861 +					Application.OnThreadException(e);
   1.862 +				}
   1.863 +
   1.864 +				protected override void WndProc(ref Message m)
   1.865 +				{
   1.866 +					reference.WndProc(ref m);
   1.867 +				}
   1.868 +			}
   1.869 +
   1.870 +			private const int WM_NULL = 0x00;
   1.871 +			private const int WM_DESTROY = 0x02;
   1.872 +			private const int WM_CLOSE = 0x10;
   1.873 +			private const int WM_COMMAND = 0x111;
   1.874 +			private const int WM_INITMENUPOPUP = 0x117;
   1.875 +			private const int WM_MOUSEMOVE = 0x200;
   1.876 +			private const int WM_LBUTTONDOWN = 0x201;
   1.877 +			private const int WM_LBUTTONUP = 0x202;
   1.878 +			private const int WM_LBUTTONDBLCLK = 0x203;
   1.879 +			private const int WM_RBUTTONDOWN = 0x204;
   1.880 +			private const int WM_RBUTTONUP = 0x205;
   1.881 +			private const int WM_RBUTTONDBLCLK = 0x206;
   1.882 +			private const int WM_MBUTTONDOWN = 0x207;
   1.883 +			private const int WM_MBUTTONUP = 0x208;
   1.884 +			private const int WM_MBUTTONDBLCLK = 0x209;
   1.885 +			private const int WM_TRAYMOUSEMESSAGE = 0x800;
   1.886 +
   1.887 +			private const int NIN_BALLOONSHOW = 0x402;
   1.888 +			private const int NIN_BALLOONHIDE = 0x403;
   1.889 +			private const int NIN_BALLOONTIMEOUT = 0x404;
   1.890 +			private const int NIN_BALLOONUSERCLICK = 0x405;
   1.891 +
   1.892 +			private static int WM_TASKBARCREATED =
   1.893 +			  NativeMethods.RegisterWindowMessage("TaskbarCreated");
   1.894 +
   1.895 +			private static class NativeMethods
   1.896 +			{
   1.897 +				[DllImport("user32.dll", CharSet = CharSet.Auto)]
   1.898 +				public static extern IntPtr PostMessage(HandleRef hwnd, int msg,
   1.899 +				  int wparam, int lparam);
   1.900 +
   1.901 +				[DllImport("user32.dll", CharSet = CharSet.Auto)]
   1.902 +				public static extern int RegisterWindowMessage(string msg);
   1.903 +
   1.904 +				[Flags]
   1.905 +				public enum NotifyIconDataFlags : int
   1.906 +				{
   1.907 +					Message = 0x1,
   1.908 +					Icon = 0x2,
   1.909 +					Tip = 0x4,
   1.910 +					State = 0x8,
   1.911 +					Info = 0x10
   1.912 +				}
   1.913 +
   1.914 +				[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
   1.915 +				public class NotifyIconData
   1.916 +				{
   1.917 +					private int Size = Marshal.SizeOf(typeof(NotifyIconData));
   1.918 +					public IntPtr Window;
   1.919 +					public int ID;
   1.920 +					public NotifyIconDataFlags Flags;
   1.921 +					public int CallbackMessage;
   1.922 +					public IntPtr Icon;
   1.923 +
   1.924 +					[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)]
   1.925 +					public string Tip;
   1.926 +
   1.927 +					public int State;
   1.928 +					public int StateMask;
   1.929 +
   1.930 +					[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
   1.931 +					public string Info;
   1.932 +
   1.933 +					public int TimeoutOrVersion;
   1.934 +
   1.935 +					[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 64)]
   1.936 +					public string InfoTitle;
   1.937 +
   1.938 +					public int InfoFlags;
   1.939 +				}
   1.940 +
   1.941 +				public enum NotifyIconMessage : int
   1.942 +				{
   1.943 +					Add = 0x0,
   1.944 +					Modify = 0x1,
   1.945 +					Delete = 0x2
   1.946 +				}
   1.947 +
   1.948 +				[DllImport("shell32.dll", CharSet = CharSet.Auto)]
   1.949 +				[return: MarshalAs(UnmanagedType.Bool)]
   1.950 +				public static extern bool Shell_NotifyIcon(NotifyIconMessage message,
   1.951 +				  NotifyIconData pnid);
   1.952 +
   1.953 +				[DllImport("user32.dll", CharSet = CharSet.Auto, ExactSpelling = true)]
   1.954 +				public static extern bool TrackPopupMenuEx(HandleRef hmenu, int fuFlags,
   1.955 +				  int x, int y, HandleRef hwnd, IntPtr tpm);
   1.956 +
   1.957 +				[StructLayout(LayoutKind.Sequential)]
   1.958 +				public struct Point
   1.959 +				{
   1.960 +					public int x;
   1.961 +					public int y;
   1.962 +				}
   1.963 +
   1.964 +				[DllImport("user32.dll", CharSet = CharSet.Auto, ExactSpelling = true)]
   1.965 +				public static extern bool GetCursorPos(ref Point point);
   1.966 +
   1.967 +				[DllImport("user32.dll", CharSet = CharSet.Auto, ExactSpelling = true)]
   1.968 +				public static extern bool SetForegroundWindow(HandleRef hWnd);
   1.969 +			}
   1.970 +		}
   1.971 +	}
   1.972 +}
   1.973 \ No newline at end of file