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