Server/NotifyIconAdv.cs
author StephaneLenclud
Wed, 27 Jul 2016 17:09:10 +0200
changeset 224 471cb4c8a09a
permissions -rw-r--r--
Make sure action edit combo box for enums is long enough.
sl@94
     1
/*
sl@94
     2
sl@94
     3
  This Source Code Form is subject to the terms of the Mozilla Public
sl@94
     4
  License, v. 2.0. If a copy of the MPL was not distributed with this
sl@94
     5
  file, You can obtain one at http://mozilla.org/MPL/2.0/.
sl@94
     6
sl@94
     7
  Copyright (C) 2012 Michael Möller <mmoeller@openhardwaremonitor.org>
sl@94
     8
sl@94
     9
*/
sl@94
    10
sl@94
    11
using System;
sl@94
    12
using System.ComponentModel;
sl@94
    13
using System.Drawing;
sl@94
    14
using System.Reflection;
sl@94
    15
using System.Runtime.InteropServices;
sl@94
    16
using System.Windows.Forms;
sl@94
    17
sl@94
    18
namespace SharpDisplayManager
sl@94
    19
{
sl@94
    20
	public class NotifyIconAdv : IDisposable
sl@94
    21
	{
sl@94
    22
		private NotifyIcon genericNotifyIcon;
sl@94
    23
		private NotifyIconWindowsImplementation windowsNotifyIcon;
sl@94
    24
sl@94
    25
		public NotifyIconAdv()
sl@94
    26
		{
sl@94
    27
			int p = (int)Environment.OSVersion.Platform;
sl@94
    28
			if ((p == 4) || (p == 128))
sl@94
    29
			{ // Unix
sl@94
    30
				genericNotifyIcon = new NotifyIcon();
sl@94
    31
			}
sl@94
    32
			else
sl@94
    33
			{ // Windows
sl@94
    34
				windowsNotifyIcon = new NotifyIconWindowsImplementation();
sl@94
    35
			}
sl@94
    36
		}
sl@94
    37
sl@94
    38
		public event EventHandler BalloonTipClicked
sl@94
    39
		{
sl@94
    40
			add
sl@94
    41
			{
sl@94
    42
				if (genericNotifyIcon != null)
sl@94
    43
					genericNotifyIcon.BalloonTipClicked += value;
sl@94
    44
				else
sl@94
    45
					windowsNotifyIcon.BalloonTipClicked += value;
sl@94
    46
			}
sl@94
    47
			remove
sl@94
    48
			{
sl@94
    49
				if (genericNotifyIcon != null)
sl@94
    50
					genericNotifyIcon.BalloonTipClicked -= value;
sl@94
    51
				else
sl@94
    52
					windowsNotifyIcon.BalloonTipClicked -= value;
sl@94
    53
			}
sl@94
    54
		}
sl@94
    55
sl@94
    56
		public event EventHandler BalloonTipClosed
sl@94
    57
		{
sl@94
    58
			add
sl@94
    59
			{
sl@94
    60
				if (genericNotifyIcon != null)
sl@94
    61
					genericNotifyIcon.BalloonTipClosed += value;
sl@94
    62
				else
sl@94
    63
					windowsNotifyIcon.BalloonTipClosed += value;
sl@94
    64
			}
sl@94
    65
			remove
sl@94
    66
			{
sl@94
    67
				if (genericNotifyIcon != null)
sl@94
    68
					genericNotifyIcon.BalloonTipClosed -= value;
sl@94
    69
				else
sl@94
    70
					windowsNotifyIcon.BalloonTipClosed -= value;
sl@94
    71
			}
sl@94
    72
		}
sl@94
    73
sl@94
    74
		public event EventHandler BalloonTipShown
sl@94
    75
		{
sl@94
    76
			add
sl@94
    77
			{
sl@94
    78
				if (genericNotifyIcon != null)
sl@94
    79
					genericNotifyIcon.BalloonTipShown += value;
sl@94
    80
				else
sl@94
    81
					windowsNotifyIcon.BalloonTipShown += value;
sl@94
    82
			}
sl@94
    83
			remove
sl@94
    84
			{
sl@94
    85
				if (genericNotifyIcon != null)
sl@94
    86
					genericNotifyIcon.BalloonTipShown -= value;
sl@94
    87
				else
sl@94
    88
					windowsNotifyIcon.BalloonTipShown -= value;
sl@94
    89
			}
sl@94
    90
		}
sl@94
    91
sl@94
    92
		public event EventHandler Click
sl@94
    93
		{
sl@94
    94
			add
sl@94
    95
			{
sl@94
    96
				if (genericNotifyIcon != null)
sl@94
    97
					genericNotifyIcon.Click += value;
sl@94
    98
				else
sl@94
    99
					windowsNotifyIcon.Click += value;
sl@94
   100
			}
sl@94
   101
			remove
sl@94
   102
			{
sl@94
   103
				if (genericNotifyIcon != null)
sl@94
   104
					genericNotifyIcon.Click -= value;
sl@94
   105
				else
sl@94
   106
					windowsNotifyIcon.Click -= value;
sl@94
   107
			}
sl@94
   108
		}
sl@94
   109
sl@94
   110
		public event EventHandler DoubleClick
sl@94
   111
		{
sl@94
   112
			add
sl@94
   113
			{
sl@94
   114
				if (genericNotifyIcon != null)
sl@94
   115
					genericNotifyIcon.DoubleClick += value;
sl@94
   116
				else
sl@94
   117
					windowsNotifyIcon.DoubleClick += value;
sl@94
   118
			}
sl@94
   119
			remove
sl@94
   120
			{
sl@94
   121
				if (genericNotifyIcon != null)
sl@94
   122
					genericNotifyIcon.DoubleClick -= value;
sl@94
   123
				else
sl@94
   124
					windowsNotifyIcon.DoubleClick -= value;
sl@94
   125
			}
sl@94
   126
		}
sl@94
   127
sl@94
   128
		public event MouseEventHandler MouseClick
sl@94
   129
		{
sl@94
   130
			add
sl@94
   131
			{
sl@94
   132
				if (genericNotifyIcon != null)
sl@94
   133
					genericNotifyIcon.MouseClick += value;
sl@94
   134
				else
sl@94
   135
					windowsNotifyIcon.MouseClick += value;
sl@94
   136
			}
sl@94
   137
			remove
sl@94
   138
			{
sl@94
   139
				if (genericNotifyIcon != null)
sl@94
   140
					genericNotifyIcon.MouseClick -= value;
sl@94
   141
				else
sl@94
   142
					windowsNotifyIcon.MouseClick -= value;
sl@94
   143
			}
sl@94
   144
		}
sl@94
   145
sl@94
   146
		public event MouseEventHandler MouseDoubleClick
sl@94
   147
		{
sl@94
   148
			add
sl@94
   149
			{
sl@94
   150
				if (genericNotifyIcon != null)
sl@94
   151
					genericNotifyIcon.MouseDoubleClick += value;
sl@94
   152
				else
sl@94
   153
					windowsNotifyIcon.MouseDoubleClick += value;
sl@94
   154
			}
sl@94
   155
			remove
sl@94
   156
			{
sl@94
   157
				if (genericNotifyIcon != null)
sl@94
   158
					genericNotifyIcon.MouseDoubleClick -= value;
sl@94
   159
				else
sl@94
   160
					windowsNotifyIcon.MouseDoubleClick -= value;
sl@94
   161
			}
sl@94
   162
		}
sl@94
   163
sl@94
   164
		public event MouseEventHandler MouseDown
sl@94
   165
		{
sl@94
   166
			add
sl@94
   167
			{
sl@94
   168
				if (genericNotifyIcon != null)
sl@94
   169
					genericNotifyIcon.MouseDown += value;
sl@94
   170
				else
sl@94
   171
					windowsNotifyIcon.MouseDown += value;
sl@94
   172
			}
sl@94
   173
			remove
sl@94
   174
			{
sl@94
   175
				if (genericNotifyIcon != null)
sl@94
   176
					genericNotifyIcon.MouseDown -= value;
sl@94
   177
				else
sl@94
   178
					windowsNotifyIcon.MouseDown -= value;
sl@94
   179
			}
sl@94
   180
		}
sl@94
   181
sl@94
   182
		public event MouseEventHandler MouseMove
sl@94
   183
		{
sl@94
   184
			add
sl@94
   185
			{
sl@94
   186
				if (genericNotifyIcon != null)
sl@94
   187
					genericNotifyIcon.MouseMove += value;
sl@94
   188
				else
sl@94
   189
					windowsNotifyIcon.MouseMove += value;
sl@94
   190
			}
sl@94
   191
			remove
sl@94
   192
			{
sl@94
   193
				if (genericNotifyIcon != null)
sl@94
   194
					genericNotifyIcon.MouseMove -= value;
sl@94
   195
				else
sl@94
   196
					windowsNotifyIcon.MouseMove -= value;
sl@94
   197
			}
sl@94
   198
		}
sl@94
   199
sl@94
   200
		public event MouseEventHandler MouseUp
sl@94
   201
		{
sl@94
   202
			add
sl@94
   203
			{
sl@94
   204
				if (genericNotifyIcon != null)
sl@94
   205
					genericNotifyIcon.MouseUp += value;
sl@94
   206
				else
sl@94
   207
					windowsNotifyIcon.MouseUp += value;
sl@94
   208
			}
sl@94
   209
			remove
sl@94
   210
			{
sl@94
   211
				if (genericNotifyIcon != null)
sl@94
   212
					genericNotifyIcon.MouseUp -= value;
sl@94
   213
				else
sl@94
   214
					windowsNotifyIcon.MouseUp -= value;
sl@94
   215
			}
sl@94
   216
		}
sl@94
   217
sl@94
   218
		public string BalloonTipText
sl@94
   219
		{
sl@94
   220
			get
sl@94
   221
			{
sl@94
   222
				if (genericNotifyIcon != null)
sl@94
   223
					return genericNotifyIcon.BalloonTipText;
sl@94
   224
				else
sl@94
   225
					return windowsNotifyIcon.BalloonTipText;
sl@94
   226
			}
sl@94
   227
			set
sl@94
   228
			{
sl@94
   229
				if (genericNotifyIcon != null)
sl@94
   230
					genericNotifyIcon.BalloonTipText = value;
sl@94
   231
				else
sl@94
   232
					windowsNotifyIcon.BalloonTipText = value;
sl@94
   233
			}
sl@94
   234
		}
sl@94
   235
sl@94
   236
		public ToolTipIcon BalloonTipIcon
sl@94
   237
		{
sl@94
   238
			get
sl@94
   239
			{
sl@94
   240
				if (genericNotifyIcon != null)
sl@94
   241
					return genericNotifyIcon.BalloonTipIcon;
sl@94
   242
				else
sl@94
   243
					return windowsNotifyIcon.BalloonTipIcon;
sl@94
   244
			}
sl@94
   245
			set
sl@94
   246
			{
sl@94
   247
				if (genericNotifyIcon != null)
sl@94
   248
					genericNotifyIcon.BalloonTipIcon = value;
sl@94
   249
				else
sl@94
   250
					windowsNotifyIcon.BalloonTipIcon = value;
sl@94
   251
			}
sl@94
   252
		}
sl@94
   253
sl@94
   254
		public string BalloonTipTitle
sl@94
   255
		{
sl@94
   256
			get
sl@94
   257
			{
sl@94
   258
				if (genericNotifyIcon != null)
sl@94
   259
					return genericNotifyIcon.BalloonTipTitle;
sl@94
   260
				else
sl@94
   261
					return windowsNotifyIcon.BalloonTipTitle;
sl@94
   262
			}
sl@94
   263
			set
sl@94
   264
			{
sl@94
   265
				if (genericNotifyIcon != null)
sl@94
   266
					genericNotifyIcon.BalloonTipTitle = value;
sl@94
   267
				else
sl@94
   268
					windowsNotifyIcon.BalloonTipTitle = value;
sl@94
   269
			}
sl@94
   270
		}
sl@94
   271
sl@94
   272
		public ContextMenu ContextMenu
sl@94
   273
		{
sl@94
   274
			get
sl@94
   275
			{
sl@94
   276
				if (genericNotifyIcon != null)
sl@94
   277
					return genericNotifyIcon.ContextMenu;
sl@94
   278
				else
sl@94
   279
					return windowsNotifyIcon.ContextMenu;
sl@94
   280
			}
sl@94
   281
			set
sl@94
   282
			{
sl@94
   283
				if (genericNotifyIcon != null)
sl@94
   284
					genericNotifyIcon.ContextMenu = value;
sl@94
   285
				else
sl@94
   286
					windowsNotifyIcon.ContextMenu = value;
sl@94
   287
			}
sl@94
   288
		}
sl@94
   289
sl@94
   290
		public ContextMenuStrip ContextMenuStrip
sl@94
   291
		{
sl@94
   292
			get
sl@94
   293
			{
sl@94
   294
				if (genericNotifyIcon != null)
sl@94
   295
					return genericNotifyIcon.ContextMenuStrip;
sl@94
   296
				else
sl@94
   297
					return windowsNotifyIcon.ContextMenuStrip;
sl@94
   298
			}
sl@94
   299
			set
sl@94
   300
			{
sl@94
   301
				if (genericNotifyIcon != null)
sl@94
   302
					genericNotifyIcon.ContextMenuStrip = value;
sl@94
   303
				else
sl@94
   304
					windowsNotifyIcon.ContextMenuStrip = value;
sl@94
   305
			}
sl@94
   306
		}
sl@94
   307
sl@94
   308
		public object Tag { get; set; }
sl@94
   309
sl@94
   310
		public Icon Icon
sl@94
   311
		{
sl@94
   312
			get
sl@94
   313
			{
sl@94
   314
				if (genericNotifyIcon != null)
sl@94
   315
					return genericNotifyIcon.Icon;
sl@94
   316
				else
sl@94
   317
					return windowsNotifyIcon.Icon;
sl@94
   318
			}
sl@94
   319
			set
sl@94
   320
			{
sl@94
   321
				if (genericNotifyIcon != null)
sl@94
   322
					genericNotifyIcon.Icon = value;
sl@94
   323
				else
sl@94
   324
					windowsNotifyIcon.Icon = value;
sl@94
   325
			}
sl@94
   326
		}
sl@94
   327
sl@94
   328
		public string Text
sl@94
   329
		{
sl@94
   330
			get
sl@94
   331
			{
sl@94
   332
				if (genericNotifyIcon != null)
sl@94
   333
					return genericNotifyIcon.Text;
sl@94
   334
				else
sl@94
   335
					return windowsNotifyIcon.Text;
sl@94
   336
			}
sl@94
   337
			set
sl@94
   338
			{
sl@94
   339
				if (genericNotifyIcon != null)
sl@94
   340
					genericNotifyIcon.Text = value;
sl@94
   341
				else
sl@94
   342
					windowsNotifyIcon.Text = value;
sl@94
   343
			}
sl@94
   344
		}
sl@94
   345
sl@94
   346
		public bool Visible
sl@94
   347
		{
sl@94
   348
			get
sl@94
   349
			{
sl@94
   350
				if (genericNotifyIcon != null)
sl@94
   351
					return genericNotifyIcon.Visible;
sl@94
   352
				else
sl@94
   353
					return windowsNotifyIcon.Visible;
sl@94
   354
			}
sl@94
   355
			set
sl@94
   356
			{
sl@94
   357
				if (genericNotifyIcon != null)
sl@94
   358
					genericNotifyIcon.Visible = value;
sl@94
   359
				else
sl@94
   360
					windowsNotifyIcon.Visible = value;
sl@94
   361
			}
sl@94
   362
		}
sl@94
   363
sl@94
   364
		public void Dispose()
sl@94
   365
		{
sl@94
   366
			if (genericNotifyIcon != null)
sl@94
   367
				genericNotifyIcon.Dispose();
sl@94
   368
			else
sl@94
   369
				windowsNotifyIcon.Dispose();
sl@94
   370
		}
sl@94
   371
sl@94
   372
		public void ShowBalloonTip(int timeout)
sl@94
   373
		{
sl@94
   374
			ShowBalloonTip(timeout, BalloonTipTitle, BalloonTipText, BalloonTipIcon);
sl@94
   375
		}
sl@94
   376
sl@94
   377
		public void ShowBalloonTip(int timeout, string tipTitle, string tipText,
sl@94
   378
		  ToolTipIcon tipIcon)
sl@94
   379
		{
sl@94
   380
			if (genericNotifyIcon != null)
sl@94
   381
				genericNotifyIcon.ShowBalloonTip(timeout, tipTitle, tipText, tipIcon);
sl@94
   382
			else
sl@94
   383
				windowsNotifyIcon.ShowBalloonTip(timeout, tipTitle, tipText, tipIcon);
sl@94
   384
		}
sl@94
   385
sl@94
   386
		private class NotifyIconWindowsImplementation : Component
sl@94
   387
		{
sl@94
   388
			private static int nextId = 0;
sl@94
   389
sl@94
   390
			private object syncObj = new object();
sl@94
   391
			private Icon icon;
sl@94
   392
			private string text = "";
sl@94
   393
			private int id;
sl@94
   394
			private bool created;
sl@94
   395
			private NotifyIconNativeWindow window;
sl@94
   396
			private bool doubleClickDown;
sl@94
   397
			private bool visible;
sl@94
   398
			private MethodInfo commandDispatch;
sl@94
   399
sl@94
   400
			public event EventHandler BalloonTipClicked;
sl@94
   401
sl@94
   402
			public event EventHandler BalloonTipClosed;
sl@94
   403
sl@94
   404
			public event EventHandler BalloonTipShown;
sl@94
   405
sl@94
   406
			public event EventHandler Click;
sl@94
   407
sl@94
   408
			public event EventHandler DoubleClick;
sl@94
   409
sl@94
   410
			public event MouseEventHandler MouseClick;
sl@94
   411
sl@94
   412
			public event MouseEventHandler MouseDoubleClick;
sl@94
   413
sl@94
   414
			public event MouseEventHandler MouseDown;
sl@94
   415
sl@94
   416
			public event MouseEventHandler MouseMove;
sl@94
   417
sl@94
   418
			public event MouseEventHandler MouseUp;
sl@94
   419
sl@94
   420
			public string BalloonTipText { get; set; }
sl@94
   421
sl@94
   422
			public ToolTipIcon BalloonTipIcon { get; set; }
sl@94
   423
sl@94
   424
			public string BalloonTipTitle { get; set; }
sl@94
   425
sl@94
   426
			public ContextMenu ContextMenu { get; set; }
sl@94
   427
sl@94
   428
			public ContextMenuStrip ContextMenuStrip { get; set; }
sl@94
   429
sl@94
   430
			public object Tag { get; set; }
sl@94
   431
sl@94
   432
			public Icon Icon
sl@94
   433
			{
sl@94
   434
				get
sl@94
   435
				{
sl@94
   436
					return icon;
sl@94
   437
				}
sl@94
   438
				set
sl@94
   439
				{
sl@94
   440
					if (icon != value)
sl@94
   441
					{
sl@94
   442
						icon = value;
sl@94
   443
						UpdateNotifyIcon(visible);
sl@94
   444
					}
sl@94
   445
				}
sl@94
   446
			}
sl@94
   447
sl@94
   448
			public string Text
sl@94
   449
			{
sl@94
   450
				get
sl@94
   451
				{
sl@94
   452
					return text;
sl@94
   453
				}
sl@94
   454
				set
sl@94
   455
				{
sl@94
   456
					if (value == null)
sl@94
   457
						value = "";
sl@94
   458
sl@94
   459
					if (value.Length > 63)
sl@94
   460
						throw new ArgumentOutOfRangeException();
sl@94
   461
sl@94
   462
					if (!value.Equals(text))
sl@94
   463
					{
sl@94
   464
						text = value;
sl@94
   465
sl@94
   466
						if (visible)
sl@94
   467
							UpdateNotifyIcon(visible);
sl@94
   468
					}
sl@94
   469
				}
sl@94
   470
			}
sl@94
   471
sl@94
   472
			public bool Visible
sl@94
   473
			{
sl@94
   474
				get
sl@94
   475
				{
sl@94
   476
					return visible;
sl@94
   477
				}
sl@94
   478
				set
sl@94
   479
				{
sl@94
   480
					if (visible != value)
sl@94
   481
					{
sl@94
   482
						visible = value;
sl@94
   483
						UpdateNotifyIcon(visible);
sl@94
   484
					}
sl@94
   485
				}
sl@94
   486
			}
sl@94
   487
sl@94
   488
			public NotifyIconWindowsImplementation()
sl@94
   489
			{
sl@94
   490
				BalloonTipText = "";
sl@94
   491
				BalloonTipTitle = "";
sl@94
   492
sl@94
   493
				commandDispatch = typeof(Form).Assembly.
sl@94
   494
				  GetType("System.Windows.Forms.Command").GetMethod("DispatchID",
sl@94
   495
				  BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public,
sl@94
   496
				  null, new Type[] { typeof(int) }, null);
sl@94
   497
sl@94
   498
				id = ++NotifyIconWindowsImplementation.nextId;
sl@94
   499
				window = new NotifyIconNativeWindow(this);
sl@94
   500
				UpdateNotifyIcon(visible);
sl@94
   501
			}
sl@94
   502
sl@94
   503
			protected override void Dispose(bool disposing)
sl@94
   504
			{
sl@94
   505
				if (disposing)
sl@94
   506
				{
sl@94
   507
					if (window != null)
sl@94
   508
					{
sl@94
   509
						icon = null;
sl@94
   510
						text = "";
sl@94
   511
						UpdateNotifyIcon(false);
sl@94
   512
						window.DestroyHandle();
sl@94
   513
						window = null;
sl@94
   514
						ContextMenu = null;
sl@94
   515
						ContextMenuStrip = null;
sl@94
   516
					}
sl@94
   517
				}
sl@94
   518
				else
sl@94
   519
				{
sl@94
   520
					if (window != null && window.Handle != IntPtr.Zero)
sl@94
   521
					{
sl@94
   522
						NativeMethods.PostMessage(
sl@94
   523
						  new HandleRef(window, window.Handle), WM_CLOSE, 0, 0);
sl@94
   524
						window.ReleaseHandle();
sl@94
   525
					}
sl@94
   526
				}
sl@94
   527
				base.Dispose(disposing);
sl@94
   528
			}
sl@94
   529
sl@94
   530
			public void ShowBalloonTip(int timeout)
sl@94
   531
			{
sl@94
   532
				ShowBalloonTip(timeout, BalloonTipTitle, BalloonTipText, BalloonTipIcon);
sl@94
   533
			}
sl@94
   534
sl@94
   535
			public void ShowBalloonTip(int timeout, string tipTitle, string tipText,
sl@94
   536
			  ToolTipIcon tipIcon)
sl@94
   537
			{
sl@94
   538
				if (timeout < 0)
sl@94
   539
					throw new ArgumentOutOfRangeException("timeout");
sl@94
   540
sl@94
   541
				if (string.IsNullOrEmpty(tipText))
sl@94
   542
					throw new ArgumentException("tipText");
sl@94
   543
sl@94
   544
				if (DesignMode)
sl@94
   545
					return;
sl@94
   546
sl@94
   547
				if (created)
sl@94
   548
				{
sl@94
   549
					NativeMethods.NotifyIconData data = new NativeMethods.NotifyIconData();
sl@94
   550
					if (window.Handle == IntPtr.Zero)
sl@94
   551
						window.CreateHandle(new CreateParams());
sl@94
   552
sl@94
   553
					data.Window = window.Handle;
sl@94
   554
					data.ID = id;
sl@94
   555
					data.Flags = NativeMethods.NotifyIconDataFlags.Info;
sl@94
   556
					data.TimeoutOrVersion = timeout;
sl@94
   557
					data.InfoTitle = tipTitle;
sl@94
   558
					data.Info = tipText;
sl@94
   559
					data.InfoFlags = (int)tipIcon;
sl@94
   560
sl@94
   561
					NativeMethods.Shell_NotifyIcon(
sl@94
   562
					  NativeMethods.NotifyIconMessage.Modify, data);
sl@94
   563
				}
sl@94
   564
			}
sl@94
   565
sl@94
   566
			private void ShowContextMenu()
sl@94
   567
			{
sl@94
   568
				if (ContextMenu == null && ContextMenuStrip == null)
sl@94
   569
					return;
sl@94
   570
sl@94
   571
				NativeMethods.Point p = new NativeMethods.Point();
sl@94
   572
				NativeMethods.GetCursorPos(ref p);
sl@94
   573
				NativeMethods.SetForegroundWindow(
sl@94
   574
				  new HandleRef(window, window.Handle));
sl@94
   575
sl@94
   576
				if (ContextMenu != null)
sl@94
   577
				{
sl@94
   578
					ContextMenu.GetType().InvokeMember("OnPopup",
sl@94
   579
					  BindingFlags.NonPublic | BindingFlags.InvokeMethod |
sl@94
   580
					  BindingFlags.Instance, null, ContextMenu,
sl@94
   581
					  new Object[] { System.EventArgs.Empty });
sl@94
   582
sl@94
   583
					NativeMethods.TrackPopupMenuEx(
sl@94
   584
					  new HandleRef(ContextMenu, ContextMenu.Handle), 72,
sl@94
   585
					  p.x, p.y, new HandleRef(window, window.Handle),
sl@94
   586
					  IntPtr.Zero);
sl@94
   587
sl@94
   588
					NativeMethods.PostMessage(
sl@94
   589
					  new HandleRef(window, window.Handle), WM_NULL, 0, 0);
sl@94
   590
					return;
sl@94
   591
				}
sl@94
   592
sl@94
   593
				if (ContextMenuStrip != null)
sl@94
   594
					ContextMenuStrip.GetType().InvokeMember("ShowInTaskbar",
sl@94
   595
					  BindingFlags.NonPublic | BindingFlags.InvokeMethod |
sl@94
   596
					  BindingFlags.Instance, null, ContextMenuStrip,
sl@94
   597
					  new Object[] { p.x, p.y });
sl@94
   598
			}
sl@94
   599
sl@94
   600
			private void UpdateNotifyIcon(bool showNotifyIcon)
sl@94
   601
			{
sl@94
   602
				if (DesignMode)
sl@94
   603
					return;
sl@94
   604
sl@94
   605
				lock (syncObj)
sl@94
   606
				{
sl@94
   607
					window.LockReference(showNotifyIcon);
sl@94
   608
sl@94
   609
					NativeMethods.NotifyIconData data = new NativeMethods.NotifyIconData();
sl@94
   610
					data.CallbackMessage = WM_TRAYMOUSEMESSAGE;
sl@94
   611
					data.Flags = NativeMethods.NotifyIconDataFlags.Message;
sl@94
   612
sl@94
   613
					if (showNotifyIcon && window.Handle == IntPtr.Zero)
sl@94
   614
						window.CreateHandle(new CreateParams());
sl@94
   615
sl@94
   616
					data.Window = window.Handle;
sl@94
   617
					data.ID = id;
sl@94
   618
sl@94
   619
					if (icon != null)
sl@94
   620
					{
sl@94
   621
						data.Flags |= NativeMethods.NotifyIconDataFlags.Icon;
sl@94
   622
						data.Icon = icon.Handle;
sl@94
   623
					}
sl@94
   624
sl@94
   625
					data.Flags |= NativeMethods.NotifyIconDataFlags.Tip;
sl@94
   626
					data.Tip = text;
sl@94
   627
sl@94
   628
					if (showNotifyIcon && icon != null)
sl@94
   629
					{
sl@94
   630
						if (!created)
sl@94
   631
						{
sl@94
   632
							int i = 0;
sl@94
   633
							do
sl@94
   634
							{
sl@94
   635
								created = NativeMethods.Shell_NotifyIcon(
sl@94
   636
								  NativeMethods.NotifyIconMessage.Add, data);
sl@94
   637
								if (!created)
sl@94
   638
								{
sl@94
   639
									System.Threading.Thread.Sleep(200);
sl@94
   640
									i++;
sl@94
   641
								}
sl@94
   642
							} while (!created && i < 40);
sl@94
   643
						}
sl@94
   644
						else
sl@94
   645
						{
sl@94
   646
							NativeMethods.Shell_NotifyIcon(
sl@94
   647
							  NativeMethods.NotifyIconMessage.Modify, data);
sl@94
   648
						}
sl@94
   649
					}
sl@94
   650
					else
sl@94
   651
					{
sl@94
   652
						if (created)
sl@94
   653
						{
sl@94
   654
							int i = 0;
sl@94
   655
							bool deleted = false;
sl@94
   656
							do
sl@94
   657
							{
sl@94
   658
								deleted = NativeMethods.Shell_NotifyIcon(
sl@94
   659
								  NativeMethods.NotifyIconMessage.Delete, data);
sl@94
   660
								if (!deleted)
sl@94
   661
								{
sl@94
   662
									System.Threading.Thread.Sleep(200);
sl@94
   663
									i++;
sl@94
   664
								}
sl@94
   665
							} while (!deleted && i < 40);
sl@94
   666
							created = false;
sl@94
   667
						}
sl@94
   668
					}
sl@94
   669
				}
sl@94
   670
			}
sl@94
   671
sl@94
   672
			private void ProcessMouseDown(ref Message message, MouseButtons button,
sl@94
   673
			  bool doubleClick)
sl@94
   674
			{
sl@94
   675
				if (doubleClick)
sl@94
   676
				{
sl@94
   677
					if (DoubleClick != null)
sl@94
   678
						DoubleClick(this, new MouseEventArgs(button, 2, 0, 0, 0));
sl@94
   679
sl@94
   680
					if (MouseDoubleClick != null)
sl@94
   681
						MouseDoubleClick(this, new MouseEventArgs(button, 2, 0, 0, 0));
sl@94
   682
sl@94
   683
					doubleClickDown = true;
sl@94
   684
				}
sl@94
   685
sl@94
   686
				if (MouseDown != null)
sl@94
   687
					MouseDown(this,
sl@94
   688
					  new MouseEventArgs(button, doubleClick ? 2 : 1, 0, 0, 0));
sl@94
   689
			}
sl@94
   690
sl@94
   691
			private void ProcessMouseUp(ref Message message, MouseButtons button)
sl@94
   692
			{
sl@94
   693
				if (MouseUp != null)
sl@94
   694
					MouseUp(this, new MouseEventArgs(button, 0, 0, 0, 0));
sl@94
   695
sl@94
   696
				if (!doubleClickDown)
sl@94
   697
				{
sl@94
   698
					if (Click != null)
sl@94
   699
						Click(this, new MouseEventArgs(button, 0, 0, 0, 0));
sl@94
   700
sl@94
   701
					if (MouseClick != null)
sl@94
   702
						MouseClick(this, new MouseEventArgs(button, 0, 0, 0, 0));
sl@94
   703
				}
sl@94
   704
				doubleClickDown = false;
sl@94
   705
			}
sl@94
   706
sl@94
   707
			private void ProcessInitMenuPopup(ref Message message)
sl@94
   708
			{
sl@94
   709
				if (ContextMenu != null &&
sl@94
   710
				  (bool)ContextMenu.GetType().InvokeMember("ProcessInitMenuPopup",
sl@94
   711
					BindingFlags.NonPublic | BindingFlags.InvokeMethod |
sl@94
   712
					BindingFlags.Instance, null, ContextMenu,
sl@94
   713
					new Object[] { message.WParam }))
sl@94
   714
				{
sl@94
   715
					return;
sl@94
   716
				}
sl@94
   717
				window.DefWndProc(ref message);
sl@94
   718
			}
sl@94
   719
sl@94
   720
			private void WndProc(ref Message message)
sl@94
   721
			{
sl@94
   722
				switch (message.Msg)
sl@94
   723
				{
sl@94
   724
					case WM_DESTROY:
sl@94
   725
						UpdateNotifyIcon(false);
sl@94
   726
						return;
sl@94
   727
sl@94
   728
					case WM_COMMAND:
sl@94
   729
						if (message.LParam != IntPtr.Zero)
sl@94
   730
						{
sl@94
   731
							window.DefWndProc(ref message);
sl@94
   732
							return;
sl@94
   733
						}
sl@94
   734
						commandDispatch.Invoke(null, new object[] {
sl@94
   735
            message.WParam.ToInt32() & 0xFFFF });
sl@94
   736
						return;
sl@94
   737
sl@94
   738
					case WM_INITMENUPOPUP:
sl@94
   739
						ProcessInitMenuPopup(ref message);
sl@94
   740
						return;
sl@94
   741
sl@94
   742
					case WM_TRAYMOUSEMESSAGE:
sl@94
   743
						switch ((int)message.LParam)
sl@94
   744
						{
sl@94
   745
							case WM_MOUSEMOVE:
sl@94
   746
								if (MouseMove != null)
sl@94
   747
									MouseMove(this,
sl@94
   748
									  new MouseEventArgs(Control.MouseButtons, 0, 0, 0, 0));
sl@94
   749
								return;
sl@94
   750
sl@94
   751
							case WM_LBUTTONDOWN:
sl@94
   752
								ProcessMouseDown(ref message, MouseButtons.Left, false);
sl@94
   753
								return;
sl@94
   754
sl@94
   755
							case WM_LBUTTONUP:
sl@94
   756
								ProcessMouseUp(ref message, MouseButtons.Left);
sl@94
   757
								return;
sl@94
   758
sl@94
   759
							case WM_LBUTTONDBLCLK:
sl@94
   760
								ProcessMouseDown(ref message, MouseButtons.Left, true);
sl@94
   761
								return;
sl@94
   762
sl@94
   763
							case WM_RBUTTONDOWN:
sl@94
   764
								ProcessMouseDown(ref message, MouseButtons.Right, false);
sl@94
   765
								return;
sl@94
   766
sl@94
   767
							case WM_RBUTTONUP:
sl@94
   768
								if (ContextMenu != null || ContextMenuStrip != null)
sl@94
   769
									ShowContextMenu();
sl@94
   770
								ProcessMouseUp(ref message, MouseButtons.Right);
sl@94
   771
								return;
sl@94
   772
sl@94
   773
							case WM_RBUTTONDBLCLK:
sl@94
   774
								ProcessMouseDown(ref message, MouseButtons.Right, true);
sl@94
   775
								return;
sl@94
   776
sl@94
   777
							case WM_MBUTTONDOWN:
sl@94
   778
								ProcessMouseDown(ref message, MouseButtons.Middle, false);
sl@94
   779
								return;
sl@94
   780
sl@94
   781
							case WM_MBUTTONUP:
sl@94
   782
								ProcessMouseUp(ref message, MouseButtons.Middle);
sl@94
   783
								return;
sl@94
   784
sl@94
   785
							case WM_MBUTTONDBLCLK:
sl@94
   786
								ProcessMouseDown(ref message, MouseButtons.Middle, true);
sl@94
   787
								return;
sl@94
   788
sl@94
   789
							case NIN_BALLOONSHOW:
sl@94
   790
								if (BalloonTipShown != null)
sl@94
   791
									BalloonTipShown(this, EventArgs.Empty);
sl@94
   792
								return;
sl@94
   793
sl@94
   794
							case NIN_BALLOONHIDE:
sl@94
   795
							case NIN_BALLOONTIMEOUT:
sl@94
   796
								if (BalloonTipClosed != null)
sl@94
   797
									BalloonTipClosed(this, EventArgs.Empty);
sl@94
   798
								return;
sl@94
   799
sl@94
   800
							case NIN_BALLOONUSERCLICK:
sl@94
   801
								if (BalloonTipClicked != null)
sl@94
   802
									BalloonTipClicked(this, EventArgs.Empty);
sl@94
   803
								return;
sl@94
   804
sl@94
   805
							default:
sl@94
   806
								return;
sl@94
   807
						}
sl@94
   808
				}
sl@94
   809
sl@94
   810
				if (message.Msg == NotifyIconWindowsImplementation.WM_TASKBARCREATED)
sl@94
   811
				{
sl@94
   812
					lock (syncObj)
sl@94
   813
					{
sl@94
   814
						created = false;
sl@94
   815
					}
sl@94
   816
					UpdateNotifyIcon(visible);
sl@94
   817
				}
sl@94
   818
sl@94
   819
				window.DefWndProc(ref message);
sl@94
   820
			}
sl@94
   821
sl@94
   822
			private class NotifyIconNativeWindow : NativeWindow
sl@94
   823
			{
sl@94
   824
				private NotifyIconWindowsImplementation reference;
sl@94
   825
				private GCHandle referenceHandle;
sl@94
   826
sl@94
   827
				internal NotifyIconNativeWindow(NotifyIconWindowsImplementation component)
sl@94
   828
				{
sl@94
   829
					this.reference = component;
sl@94
   830
				}
sl@94
   831
sl@94
   832
				~NotifyIconNativeWindow()
sl@94
   833
				{
sl@94
   834
					if (base.Handle != IntPtr.Zero)
sl@94
   835
						NativeMethods.PostMessage(
sl@94
   836
						  new HandleRef(this, base.Handle), WM_CLOSE, 0, 0);
sl@94
   837
				}
sl@94
   838
sl@94
   839
				public void LockReference(bool locked)
sl@94
   840
				{
sl@94
   841
					if (locked)
sl@94
   842
					{
sl@94
   843
						if (!referenceHandle.IsAllocated)
sl@94
   844
						{
sl@94
   845
							referenceHandle = GCHandle.Alloc(reference, GCHandleType.Normal);
sl@94
   846
							return;
sl@94
   847
						}
sl@94
   848
					}
sl@94
   849
					else
sl@94
   850
					{
sl@94
   851
						if (referenceHandle.IsAllocated)
sl@94
   852
							referenceHandle.Free();
sl@94
   853
					}
sl@94
   854
				}
sl@94
   855
sl@94
   856
				protected override void OnThreadException(Exception e)
sl@94
   857
				{
sl@94
   858
					Application.OnThreadException(e);
sl@94
   859
				}
sl@94
   860
sl@94
   861
				protected override void WndProc(ref Message m)
sl@94
   862
				{
sl@94
   863
					reference.WndProc(ref m);
sl@94
   864
				}
sl@94
   865
			}
sl@94
   866
sl@94
   867
			private const int WM_NULL = 0x00;
sl@94
   868
			private const int WM_DESTROY = 0x02;
sl@94
   869
			private const int WM_CLOSE = 0x10;
sl@94
   870
			private const int WM_COMMAND = 0x111;
sl@94
   871
			private const int WM_INITMENUPOPUP = 0x117;
sl@94
   872
			private const int WM_MOUSEMOVE = 0x200;
sl@94
   873
			private const int WM_LBUTTONDOWN = 0x201;
sl@94
   874
			private const int WM_LBUTTONUP = 0x202;
sl@94
   875
			private const int WM_LBUTTONDBLCLK = 0x203;
sl@94
   876
			private const int WM_RBUTTONDOWN = 0x204;
sl@94
   877
			private const int WM_RBUTTONUP = 0x205;
sl@94
   878
			private const int WM_RBUTTONDBLCLK = 0x206;
sl@94
   879
			private const int WM_MBUTTONDOWN = 0x207;
sl@94
   880
			private const int WM_MBUTTONUP = 0x208;
sl@94
   881
			private const int WM_MBUTTONDBLCLK = 0x209;
sl@94
   882
			private const int WM_TRAYMOUSEMESSAGE = 0x800;
sl@94
   883
sl@94
   884
			private const int NIN_BALLOONSHOW = 0x402;
sl@94
   885
			private const int NIN_BALLOONHIDE = 0x403;
sl@94
   886
			private const int NIN_BALLOONTIMEOUT = 0x404;
sl@94
   887
			private const int NIN_BALLOONUSERCLICK = 0x405;
sl@94
   888
sl@94
   889
			private static int WM_TASKBARCREATED =
sl@94
   890
			  NativeMethods.RegisterWindowMessage("TaskbarCreated");
sl@94
   891
sl@94
   892
			private static class NativeMethods
sl@94
   893
			{
sl@94
   894
				[DllImport("user32.dll", CharSet = CharSet.Auto)]
sl@94
   895
				public static extern IntPtr PostMessage(HandleRef hwnd, int msg,
sl@94
   896
				  int wparam, int lparam);
sl@94
   897
sl@94
   898
				[DllImport("user32.dll", CharSet = CharSet.Auto)]
sl@94
   899
				public static extern int RegisterWindowMessage(string msg);
sl@94
   900
sl@94
   901
				[Flags]
sl@94
   902
				public enum NotifyIconDataFlags : int
sl@94
   903
				{
sl@94
   904
					Message = 0x1,
sl@94
   905
					Icon = 0x2,
sl@94
   906
					Tip = 0x4,
sl@94
   907
					State = 0x8,
sl@94
   908
					Info = 0x10
sl@94
   909
				}
sl@94
   910
sl@94
   911
				[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
sl@94
   912
				public class NotifyIconData
sl@94
   913
				{
sl@94
   914
					private int Size = Marshal.SizeOf(typeof(NotifyIconData));
sl@94
   915
					public IntPtr Window;
sl@94
   916
					public int ID;
sl@94
   917
					public NotifyIconDataFlags Flags;
sl@94
   918
					public int CallbackMessage;
sl@94
   919
					public IntPtr Icon;
sl@94
   920
sl@94
   921
					[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)]
sl@94
   922
					public string Tip;
sl@94
   923
sl@94
   924
					public int State;
sl@94
   925
					public int StateMask;
sl@94
   926
sl@94
   927
					[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
sl@94
   928
					public string Info;
sl@94
   929
sl@94
   930
					public int TimeoutOrVersion;
sl@94
   931
sl@94
   932
					[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 64)]
sl@94
   933
					public string InfoTitle;
sl@94
   934
sl@94
   935
					public int InfoFlags;
sl@94
   936
				}
sl@94
   937
sl@94
   938
				public enum NotifyIconMessage : int
sl@94
   939
				{
sl@94
   940
					Add = 0x0,
sl@94
   941
					Modify = 0x1,
sl@94
   942
					Delete = 0x2
sl@94
   943
				}
sl@94
   944
sl@94
   945
				[DllImport("shell32.dll", CharSet = CharSet.Auto)]
sl@94
   946
				[return: MarshalAs(UnmanagedType.Bool)]
sl@94
   947
				public static extern bool Shell_NotifyIcon(NotifyIconMessage message,
sl@94
   948
				  NotifyIconData pnid);
sl@94
   949
sl@94
   950
				[DllImport("user32.dll", CharSet = CharSet.Auto, ExactSpelling = true)]
sl@94
   951
				public static extern bool TrackPopupMenuEx(HandleRef hmenu, int fuFlags,
sl@94
   952
				  int x, int y, HandleRef hwnd, IntPtr tpm);
sl@94
   953
sl@94
   954
				[StructLayout(LayoutKind.Sequential)]
sl@94
   955
				public struct Point
sl@94
   956
				{
sl@94
   957
					public int x;
sl@94
   958
					public int y;
sl@94
   959
				}
sl@94
   960
sl@94
   961
				[DllImport("user32.dll", CharSet = CharSet.Auto, ExactSpelling = true)]
sl@94
   962
				public static extern bool GetCursorPos(ref Point point);
sl@94
   963
sl@94
   964
				[DllImport("user32.dll", CharSet = CharSet.Auto, ExactSpelling = true)]
sl@94
   965
				public static extern bool SetForegroundWindow(HandleRef hWnd);
sl@94
   966
			}
sl@94
   967
		}
sl@94
   968
	}
sl@94
   969
}