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