First system tray sensor monitor support.
authormoel.mich
Fri, 12 Feb 2010 00:36:56 +0000
changeset 402392f7402fb6
parent 39 654696eeebe8
child 41 d92bacc2116e
First system tray sensor monitor support.
GUI/MainForm.Designer.cs
GUI/MainForm.cs
GUI/MainForm.resx
GUI/SensorNotifyIcon.cs
GUI/SensorSystemTray.cs
OpenHardwareMonitor.csproj
Properties/AssemblyInfo.cs
Utilities/IconFactory.cs
     1.1 --- a/GUI/MainForm.Designer.cs	Thu Feb 11 13:22:17 2010 +0000
     1.2 +++ b/GUI/MainForm.Designer.cs	Fri Feb 12 00:36:56 2010 +0000
     1.3 @@ -102,11 +102,11 @@
     1.4        this.timer = new System.Windows.Forms.Timer(this.components);
     1.5        this.splitContainer = new System.Windows.Forms.SplitContainer();
     1.6        this.plotPanel = new OpenHardwareMonitor.GUI.PlotPanel();
     1.7 -      this.notifyIcon = new System.Windows.Forms.NotifyIcon(this.components);
     1.8        this.notifyContextMenuStrip = new System.Windows.Forms.ContextMenuStrip(this.components);
     1.9        this.restoreToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
    1.10        this.toolStripMenuItem2 = new System.Windows.Forms.ToolStripSeparator();
    1.11        this.exitToolStripMenuItem1 = new System.Windows.Forms.ToolStripMenuItem();
    1.12 +      this.sensorContextMenuStrip = new System.Windows.Forms.ContextMenuStrip(this.components);
    1.13        this.columnsContextMenuStrip.SuspendLayout();
    1.14        this.menuStrip.SuspendLayout();
    1.15        this.splitContainer.Panel1.SuspendLayout();
    1.16 @@ -490,13 +490,6 @@
    1.17        this.plotPanel.Size = new System.Drawing.Size(478, 198);
    1.18        this.plotPanel.TabIndex = 0;
    1.19        // 
    1.20 -      // notifyIcon
    1.21 -      // 
    1.22 -      this.notifyIcon.ContextMenuStrip = this.notifyContextMenuStrip;
    1.23 -      this.notifyIcon.Icon = ((System.Drawing.Icon)(resources.GetObject("notifyIcon.Icon")));
    1.24 -      this.notifyIcon.Text = "Open Hardware Monitor";
    1.25 -      this.notifyIcon.DoubleClick += new System.EventHandler(this.restoreClick);
    1.26 -      // 
    1.27        // notifyContextMenuStrip
    1.28        // 
    1.29        this.notifyContextMenuStrip.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
    1.30 @@ -526,6 +519,11 @@
    1.31        this.exitToolStripMenuItem1.Text = "Exit";
    1.32        this.exitToolStripMenuItem1.Click += new System.EventHandler(this.exitToolStripMenuItem_Click);
    1.33        // 
    1.34 +      // sensorContextMenuStrip
    1.35 +      // 
    1.36 +      this.sensorContextMenuStrip.Name = "sensorContextMenuStrip";
    1.37 +      this.sensorContextMenuStrip.Size = new System.Drawing.Size(61, 4);
    1.38 +      // 
    1.39        // MainForm
    1.40        // 
    1.41        this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 15F);
    1.42 @@ -592,13 +590,13 @@
    1.43      private System.Windows.Forms.ToolStripMenuItem voltMenuItem;
    1.44      private System.Windows.Forms.ToolStripMenuItem hddMenuItem;
    1.45      private System.Windows.Forms.ToolStripMenuItem loadMenuItem;
    1.46 -    private System.Windows.Forms.NotifyIcon notifyIcon;
    1.47      private System.Windows.Forms.ContextMenuStrip notifyContextMenuStrip;
    1.48      private System.Windows.Forms.ToolStripMenuItem restoreToolStripMenuItem;
    1.49      private System.Windows.Forms.ToolStripSeparator toolStripMenuItem2;
    1.50      private System.Windows.Forms.ToolStripMenuItem exitToolStripMenuItem1;
    1.51      private System.Windows.Forms.ToolStripMenuItem minTrayMenuItem;
    1.52      private System.Windows.Forms.ToolStripSeparator toolStripMenuItem3;
    1.53 +    private System.Windows.Forms.ContextMenuStrip sensorContextMenuStrip;
    1.54    }
    1.55  }
    1.56  
     2.1 --- a/GUI/MainForm.cs	Thu Feb 11 13:22:17 2010 +0000
     2.2 +++ b/GUI/MainForm.cs	Fri Feb 12 00:36:56 2010 +0000
     2.3 @@ -56,6 +56,8 @@
     2.4      private IDictionary<ISensor, Color> sensorPlotColors = 
     2.5        new Dictionary<ISensor, Color>();
     2.6      private Color[] plotColorPalette;
     2.7 +    private SensorSystemTray sensorSystemTray;
     2.8 +    private NotifyIcon notifyIcon;
     2.9  
    2.10      public MainForm() {      
    2.11        InitializeComponent();
    2.12 @@ -98,6 +100,14 @@
    2.13        
    2.14        treeModel.Nodes.Add(root);
    2.15        treeView.Model = treeModel;
    2.16 +      
    2.17 +      notifyIcon = new NotifyIcon();
    2.18 +      notifyIcon.ContextMenuStrip = this.notifyContextMenuStrip;
    2.19 +      notifyIcon.Icon = EmbeddedResources.GetIcon("smallicon.ico");
    2.20 +      notifyIcon.Text = "Open Hardware Monitor";      
    2.21 +      notifyIcon.DoubleClick += new EventHandler(this.restoreClick);
    2.22 +
    2.23 +      sensorSystemTray = new SensorSystemTray(computer);
    2.24  
    2.25        computer.HardwareAdded += new HardwareEventHandler(HardwareAdded);
    2.26        computer.HardwareRemoved += new HardwareEventHandler(HardwareRemoved);
    2.27 @@ -218,6 +228,7 @@
    2.28              
    2.29        treeView.Invalidate();
    2.30        plotPanel.Invalidate();
    2.31 +      sensorSystemTray.Redraw();
    2.32      }
    2.33  
    2.34      private void MainForm_FormClosed(object sender, FormClosedEventArgs e) {
    2.35 @@ -242,6 +253,9 @@
    2.36          Config.Set("mainForm.Width", Width);
    2.37          Config.Set("mainForm.Height", Height);
    2.38        }
    2.39 +      
    2.40 +      sensorSystemTray.Dispose();
    2.41 +      notifyIcon.Dispose();
    2.42  
    2.43        computer.Close();
    2.44      }
    2.45 @@ -287,7 +301,27 @@
    2.46        NodeControlInfo info = treeView.GetNodeControlInfoAt(new Point(m.X, m.Y));
    2.47        if (info.Control == null) {
    2.48          columnsContextMenuStrip.Show(treeView, m.X, m.Y);
    2.49 -      } 
    2.50 +      } else {
    2.51 +        SensorNode node = info.Node.Tag as SensorNode;
    2.52 +        if (node != null && node.Sensor != null) {
    2.53 +
    2.54 +          sensorContextMenuStrip.Items.Clear();
    2.55 +          if (sensorSystemTray.Contains(node.Sensor)) {
    2.56 +            ToolStripMenuItem item = new ToolStripMenuItem("Remove From Tray");
    2.57 +            item.Click += delegate(object obj, EventArgs args) {
    2.58 +              sensorSystemTray.Remove(node.Sensor);
    2.59 +            };
    2.60 +            sensorContextMenuStrip.Items.Add(item);
    2.61 +          } else {
    2.62 +            ToolStripMenuItem item = new ToolStripMenuItem("Add To Tray");
    2.63 +            item.Click += delegate(object obj, EventArgs args) {
    2.64 +              sensorSystemTray.Add(node.Sensor);
    2.65 +            };
    2.66 +            sensorContextMenuStrip.Items.Add(item);
    2.67 +          }
    2.68 +          sensorContextMenuStrip.Show(treeView, m.X, m.Y);
    2.69 +        }
    2.70 +      }
    2.71      }
    2.72  
    2.73      private void saveReportToolStripMenuItem_Click(object sender, EventArgs e) {
    2.74 @@ -338,5 +372,17 @@
    2.75        ToggleSysTray();
    2.76      }
    2.77  
    2.78 +    private void removeToolStripMenuItem_Click(object sender, EventArgs e) {
    2.79 +      ToolStripMenuItem item = sender as ToolStripMenuItem;
    2.80 +      if (item == null)
    2.81 +        return;
    2.82 +
    2.83 +      ISensor sensor = item.Owner.Tag as ISensor;
    2.84 +      if (sensor == null)
    2.85 +        return;
    2.86 +
    2.87 +      sensorSystemTray.Remove(sensor);
    2.88 +    }
    2.89 +
    2.90    }
    2.91  }
     3.1 --- a/GUI/MainForm.resx	Thu Feb 11 13:22:17 2010 +0000
     3.2 +++ b/GUI/MainForm.resx	Fri Feb 12 00:36:56 2010 +0000
     3.3 @@ -126,40 +126,16 @@
     3.4    <metadata name="timer.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
     3.5      <value>124, 15</value>
     3.6    </metadata>
     3.7 -  <metadata name="notifyIcon.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
     3.8 -    <value>401, 15</value>
     3.9 +  <metadata name="notifyContextMenuStrip.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
    3.10 +    <value>399, 15</value>
    3.11    </metadata>
    3.12 -  <metadata name="notifyContextMenuStrip.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
    3.13 -    <value>507, 15</value>
    3.14 +  <metadata name="sensorContextMenuStrip.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
    3.15 +    <value>571, 15</value>
    3.16    </metadata>
    3.17 -  <assembly alias="System.Drawing" name="System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
    3.18 -  <data name="notifyIcon.Icon" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
    3.19 -    <value>
    3.20 -        AAABAAEAEBAAAAEAIABoBAAAFgAAACgAAAAQAAAAIAAAAAEAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
    3.21 -        AABFPDspLg4HSCMUElEcHR1PGRoaTxYWFk8UFBRPEhISTw8QD08NCgpPCgUETwgEA08HAwFPBwEATwYE
    3.22 -        BFEFBQU8S1VW/y9tef83V1z/PTs7/zg3N/8zNDP/Ly8v/yoqKv8mJSX/IiYn/xsnKf8YICP/FB4g/xIe
    3.23 -        IP8OEhP/BgQEUUFka/8Rl7T/MlJZ/zQyMf8uLi3/Kioq/ykoKP8nJyf/JSQj/yIpKv8bOD3/Gjg+/xs6
    3.24 -        Qf8aOD3/Ehob/wcDA09NWlz+OlJY/j83NP5HR0f+TE1N/kNDQ/48PDz+Nzc3/i8vL/4oKCj+JSgp/iIn
    3.25 -        KP4cIiP+HB8g/xQTFP8GBwZPV1VV/kY/Pv5JSUn+oqKi/q6vrv6fn5/+mJiY/o+Pj/6EhIT+enp6/nVy
    3.26 -        cv5jYGD+Ih8e/hsZGv8VFRX/BwcHT1taWv5FRUT+WFhY/q6urv6+vr7+sLCv/qmpqf6goKD+lJSU/omJ
    3.27 -        if6BgYH+cXFx/iQkJP4bGxv/FhYW/wcHB09eXl7+SEhI/lpaWv61tbX+xsbG/ra2tv6srKv+oaGi/paW
    3.28 -        lv6MjIz+hISE/nJycv4kJCT+HBwc/xgYGP8HBwdPY2Nj/k1MTP5eXl7+wMDA/tHR0f6+vr7+r6+v/qOj
    3.29 -        pP6ZmJn+kZOT/oqLiv53eHf+JSUl/h0dHf8ZGRn/BwcHT2dnZ/5QUFD+YmJi/srKyv7c3Nz+x8bH/rW0
    3.30 -        tf6pqan+n5+f/piYmP6Oj4/+e3t8/iUlJv4eHh7/Ghoa/wgICE9ra2v+U1NT/mRkZP7S0tL+4+Xj/szM
    3.31 -        zP68vLz+sLCw/qampv6bm5v+k5GR/n9/f/4oKCj+Hx8e/xwcHP8JCQpPbm5u/lZVVv5mZWb+19bX/ujo
    3.32 -        6P7T0tP+x8fH/rq6uv6rq6v+nZ6e/pSUlP6BgYD+LCws/h8eHv8eHRz/CwsLT29vb/5WVlb+Z2do/uHh
    3.33 -        4f7y8fL+2dnZ/s3Nzf7AwMD+sLKy/qSjpP6ZmZn+hoaG/jAwMP4fIB//Hh8f/w0LDU9vb2/+WFhY/lla
    3.34 -        Wv7BwcH+1dXV/sDAv/61tbT+qamp/pubm/6Oj47+hYWF/nFxcf4uKir+ICwu/x4qLf8OCQdPb29w/lpZ
    3.35 -        Wv5SUlH+VVVV/mBgYP5bW1r+VVVT/k5OTv5HR0f+QUFB/js7Ov4wLy/+KCgo/iM5Pf8fLS//EAkIUW5u
    3.36 -        bv5VVVX+UlJS/ktLS/5ERET+QUFB/j09Pf45OTn+NTU1/jMyMv4vLy7+LCko/icuL/4fQ0z/Ii4x/xMN
    3.37 -        Ckh6e3r+ampq/mVlZf5hYWL+XFxc/lhYWP5TUlP+TU1N/kdGR/5CQkL+PTw8/jc1Nf4wMTH+KjEy/yYo
    3.38 -        Kf8eHBwp//8AAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAAB
    3.39 -        AAAAAQAAAAEAAA==
    3.40 -</value>
    3.41 -  </data>
    3.42    <metadata name="$this.TrayHeight" type="System.Int32, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
    3.43      <value>55</value>
    3.44    </metadata>
    3.45 +  <assembly alias="System.Drawing" name="System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
    3.46    <data name="$this.Icon" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
    3.47      <value>
    3.48          AAABAAMAEBAAAAEAIABoBAAANgAAACAgAAABACAAqBAAAJ4EAAAwMAAAAQAgAKglAABGFQAAKAAAABAA
     4.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     4.2 +++ b/GUI/SensorNotifyIcon.cs	Fri Feb 12 00:36:56 2010 +0000
     4.3 @@ -0,0 +1,192 @@
     4.4 +/*
     4.5 +  
     4.6 +  Version: MPL 1.1/GPL 2.0/LGPL 2.1
     4.7 +
     4.8 +  The contents of this file are subject to the Mozilla Public License Version
     4.9 +  1.1 (the "License"); you may not use this file except in compliance with
    4.10 +  the License. You may obtain a copy of the License at
    4.11 + 
    4.12 +  http://www.mozilla.org/MPL/
    4.13 +
    4.14 +  Software distributed under the License is distributed on an "AS IS" basis,
    4.15 +  WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
    4.16 +  for the specific language governing rights and limitations under the License.
    4.17 +
    4.18 +  The Original Code is the Open Hardware Monitor code.
    4.19 +
    4.20 +  The Initial Developer of the Original Code is 
    4.21 +  Michael Möller <m.moeller@gmx.ch>.
    4.22 +  Portions created by the Initial Developer are Copyright (C) 2009-2010
    4.23 +  the Initial Developer. All Rights Reserved.
    4.24 +
    4.25 +  Contributor(s):
    4.26 +
    4.27 +  Alternatively, the contents of this file may be used under the terms of
    4.28 +  either the GNU General Public License Version 2 or later (the "GPL"), or
    4.29 +  the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
    4.30 +  in which case the provisions of the GPL or the LGPL are applicable instead
    4.31 +  of those above. If you wish to allow use of your version of this file only
    4.32 +  under the terms of either the GPL or the LGPL, and not to allow others to
    4.33 +  use your version of this file under the terms of the MPL, indicate your
    4.34 +  decision by deleting the provisions above and replace them with the notice
    4.35 +  and other provisions required by the GPL or the LGPL. If you do not delete
    4.36 +  the provisions above, a recipient may use your version of this file under
    4.37 +  the terms of any one of the MPL, the GPL or the LGPL.
    4.38 + 
    4.39 +*/
    4.40 +
    4.41 +using System;
    4.42 +using System.Collections.Generic;
    4.43 +using System.Drawing;
    4.44 +using System.Drawing.Drawing2D;
    4.45 +using System.Drawing.Imaging;
    4.46 +using System.Drawing.Text;
    4.47 +using System.Text;
    4.48 +using System.Windows.Forms;
    4.49 +using System.Runtime.InteropServices;
    4.50 +using OpenHardwareMonitor.Hardware;
    4.51 +using OpenHardwareMonitor.Utilities;
    4.52 +
    4.53 +namespace OpenHardwareMonitor.GUI {
    4.54 +  public class SensorNotifyIcon : IDisposable {
    4.55 +
    4.56 +    private ISensor sensor;
    4.57 +    private NotifyIcon notifyIcon;
    4.58 +    private Bitmap bitmap;
    4.59 +    private Graphics graphics;
    4.60 +    private int majorVersion;
    4.61 +
    4.62 +    public SensorNotifyIcon(SensorSystemTray sensorSystemTray, ISensor sensor) {
    4.63 +      this.sensor = sensor;
    4.64 +      this.notifyIcon = new NotifyIcon();
    4.65 +      this.majorVersion = Environment.OSVersion.Version.Major;      
    4.66 +      
    4.67 +      ContextMenuStrip contextMenuStrip = new ContextMenuStrip();
    4.68 +      ToolStripMenuItem item = new ToolStripMenuItem("Remove");
    4.69 +      item.Click += delegate(object obj, EventArgs args) {
    4.70 +        sensorSystemTray.Remove(sensor);
    4.71 +      };
    4.72 +      contextMenuStrip.Items.Add(item);
    4.73 +      this.notifyIcon.ContextMenuStrip = contextMenuStrip;
    4.74 +
    4.75 +      this.bitmap = new Bitmap(16, 16, PixelFormat.Format32bppArgb);
    4.76 +      this.graphics = Graphics.FromImage(this.bitmap);
    4.77 +      this.graphics.TextRenderingHint = TextRenderingHint.ClearTypeGridFit;
    4.78 +      this.graphics.SmoothingMode = SmoothingMode.HighQuality;
    4.79 +    }
    4.80 +
    4.81 +    public ISensor Sensor {
    4.82 +      get { return sensor; }
    4.83 +    }
    4.84 +
    4.85 +    public void Dispose() {      
    4.86 +      Icon icon = notifyIcon.Icon;
    4.87 +      notifyIcon.Icon = null;
    4.88 +      if (icon != null)
    4.89 +        icon.Dispose();      
    4.90 +      notifyIcon.Dispose();
    4.91 +      notifyIcon = null;
    4.92 +
    4.93 +      graphics.Dispose();
    4.94 +      graphics = null;
    4.95 +      bitmap.Dispose();
    4.96 +      bitmap = null;
    4.97 +    }
    4.98 +
    4.99 +    private string GetString() {
   4.100 +      switch (sensor.SensorType) {
   4.101 +        case SensorType.Voltage:
   4.102 +          return string.Format("{0:F11}", sensor.Value);
   4.103 +        case SensorType.Clock:
   4.104 +          return string.Format("{0:F11}", 1e-3f * sensor.Value);
   4.105 +        case SensorType.Load: 
   4.106 +          return string.Format("{0:F0}", sensor.Value < 99 ? sensor.Value : 99);
   4.107 +        case SensorType.Temperature: 
   4.108 +          return string.Format("{0:F0}", sensor.Value);
   4.109 +        case SensorType.Fan: 
   4.110 +          return string.Format("{0:F11}", 1e-3f * sensor.Value);
   4.111 +      }
   4.112 +      return "-";
   4.113 +    }
   4.114 +
   4.115 +    private Icon CreateSimpleIcon() {
   4.116 +
   4.117 +      graphics.Clear(SystemColors.ButtonFace);
   4.118 +      TextRenderer.DrawText(graphics, GetString(), SystemFonts.StatusFont,
   4.119 +        new Point(-2, 0), Color.Blue, SystemColors.ButtonFace);
   4.120 +
   4.121 +      BitmapData data = bitmap.LockBits(
   4.122 +        new Rectangle(0, 0, bitmap.Width, bitmap.Height),
   4.123 +        ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);
   4.124 +
   4.125 +      int stride = data.Stride;
   4.126 +      IntPtr Scan0 = data.Scan0;
   4.127 +
   4.128 +      int numBytes = bitmap.Width * bitmap.Height * 4;
   4.129 +      byte[] bytes = new byte[numBytes];
   4.130 +      Marshal.Copy(Scan0, bytes, 0, numBytes);
   4.131 +      bitmap.UnlockBits(data);
   4.132 +
   4.133 +      return IconFactory.Create(bytes, 16, 16, PixelFormat.Format32bppArgb);
   4.134 +    }
   4.135 +
   4.136 +    private Icon CreateTransparentIcon() {
   4.137 +
   4.138 +      graphics.Clear(Color.Black);
   4.139 +      TextRenderer.DrawText(graphics, GetString(), SystemFonts.StatusFont,
   4.140 +        new Point(-2, 0), Color.White, Color.Black);
   4.141 +
   4.142 +      BitmapData data = bitmap.LockBits(
   4.143 +        new Rectangle(0, 0, bitmap.Width, bitmap.Height),
   4.144 +        ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);
   4.145 +
   4.146 +      int stride = data.Stride;
   4.147 +      IntPtr Scan0 = data.Scan0;
   4.148 +
   4.149 +      int numBytes = bitmap.Width * bitmap.Height * 4;
   4.150 +      byte[] bytes = new byte[numBytes];
   4.151 +      Marshal.Copy(Scan0, bytes, 0, numBytes);
   4.152 +      bitmap.UnlockBits(data);
   4.153 +
   4.154 +      byte red, green, blue;
   4.155 +      for (int i = 0; i < bytes.Length; i += 4) {
   4.156 +        blue = bytes[i];
   4.157 +        green = bytes[i + 1];
   4.158 +        red = bytes[i + 2];
   4.159 +
   4.160 +        bytes[i] = 255;
   4.161 +        bytes[i + 1] = 255;
   4.162 +        bytes[i + 2] = 255;
   4.163 +        bytes[i + 3] = (byte)(0.3 * red + 0.59 * green + 0.11 * blue);
   4.164 +      }
   4.165 +
   4.166 +      return IconFactory.Create(bytes, 16, 16, PixelFormat.Format32bppArgb);
   4.167 +    }
   4.168 +
   4.169 +    public void Update() {
   4.170 +      Icon icon = notifyIcon.Icon;
   4.171 +
   4.172 +      if (majorVersion < 6) {
   4.173 +        notifyIcon.Icon = CreateSimpleIcon();
   4.174 +      } else {
   4.175 +        notifyIcon.Icon = CreateTransparentIcon();
   4.176 +      }
   4.177 +      
   4.178 +      if (icon != null) 
   4.179 +        icon.Dispose();
   4.180 +
   4.181 +      string format = "";
   4.182 +      switch (sensor.SensorType) {
   4.183 +        case SensorType.Voltage: format = "{0}\n{1}: {2:F2} V"; break;
   4.184 +        case SensorType.Clock: format = "{0}\n{1}: {2:F0} MHz"; break;
   4.185 +        case SensorType.Load: format = "{0}\n{1}: {2:F1} %"; break;
   4.186 +        case SensorType.Temperature: format = "{0}\n{1}: {2:F1} °C"; break;
   4.187 +        case SensorType.Fan: format = "{0}\n{1}: {2:F0} RPM"; break;
   4.188 +      }
   4.189 +
   4.190 +      notifyIcon.Text = string.Format(format, 
   4.191 +        sensor.Hardware.Name, sensor.Name, sensor.Value);
   4.192 +      notifyIcon.Visible = true;
   4.193 +    }
   4.194 +  }
   4.195 +}
     5.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     5.2 +++ b/GUI/SensorSystemTray.cs	Fri Feb 12 00:36:56 2010 +0000
     5.3 @@ -0,0 +1,121 @@
     5.4 +/*
     5.5 +  
     5.6 +  Version: MPL 1.1/GPL 2.0/LGPL 2.1
     5.7 +
     5.8 +  The contents of this file are subject to the Mozilla Public License Version
     5.9 +  1.1 (the "License"); you may not use this file except in compliance with
    5.10 +  the License. You may obtain a copy of the License at
    5.11 + 
    5.12 +  http://www.mozilla.org/MPL/
    5.13 +
    5.14 +  Software distributed under the License is distributed on an "AS IS" basis,
    5.15 +  WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
    5.16 +  for the specific language governing rights and limitations under the License.
    5.17 +
    5.18 +  The Original Code is the Open Hardware Monitor code.
    5.19 +
    5.20 +  The Initial Developer of the Original Code is 
    5.21 +  Michael Möller <m.moeller@gmx.ch>.
    5.22 +  Portions created by the Initial Developer are Copyright (C) 2009-2010
    5.23 +  the Initial Developer. All Rights Reserved.
    5.24 +
    5.25 +  Contributor(s):
    5.26 +
    5.27 +  Alternatively, the contents of this file may be used under the terms of
    5.28 +  either the GNU General Public License Version 2 or later (the "GPL"), or
    5.29 +  the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
    5.30 +  in which case the provisions of the GPL or the LGPL are applicable instead
    5.31 +  of those above. If you wish to allow use of your version of this file only
    5.32 +  under the terms of either the GPL or the LGPL, and not to allow others to
    5.33 +  use your version of this file under the terms of the MPL, indicate your
    5.34 +  decision by deleting the provisions above and replace them with the notice
    5.35 +  and other provisions required by the GPL or the LGPL. If you do not delete
    5.36 +  the provisions above, a recipient may use your version of this file under
    5.37 +  the terms of any one of the MPL, the GPL or the LGPL.
    5.38 + 
    5.39 +*/
    5.40 +
    5.41 +using System;
    5.42 +using System.Collections.Generic;
    5.43 +using System.Text;
    5.44 +using System.Windows.Forms;
    5.45 +using OpenHardwareMonitor.Hardware;
    5.46 +using OpenHardwareMonitor.Utilities;
    5.47 +
    5.48 +namespace OpenHardwareMonitor.GUI {
    5.49 +  public class SensorSystemTray : IDisposable {
    5.50 +    private Computer computer;
    5.51 +    private List<SensorNotifyIcon> list = new List<SensorNotifyIcon>();
    5.52 +
    5.53 +    public SensorSystemTray(Computer computer) {
    5.54 +      this.computer = computer;
    5.55 +      computer.HardwareAdded += new HardwareEventHandler(HardwareAdded);
    5.56 +      computer.HardwareRemoved += new HardwareEventHandler(HardwareRemoved);
    5.57 +    }
    5.58 +
    5.59 +    private void HardwareRemoved(IHardware hardware) {
    5.60 +      hardware.SensorAdded -= new SensorEventHandler(SensorAdded);
    5.61 +      hardware.SensorRemoved -= new SensorEventHandler(SensorRemoved);
    5.62 +      foreach (ISensor sensor in hardware.Sensors) 
    5.63 +        SensorRemoved(sensor);
    5.64 +    }
    5.65 +   
    5.66 +    private void HardwareAdded(IHardware hardware) {
    5.67 +      foreach (ISensor sensor in hardware.Sensors)
    5.68 +        SensorAdded(sensor);
    5.69 +      hardware.SensorAdded += new SensorEventHandler(SensorAdded);
    5.70 +      hardware.SensorRemoved += new SensorEventHandler(SensorRemoved);
    5.71 +    }
    5.72 +
    5.73 +    private void SensorAdded(ISensor sensor) {
    5.74 +      if (Config.Get(sensor.Identifier + "/tray", false)) 
    5.75 +        Add(sensor);   
    5.76 +    }
    5.77 +
    5.78 +    private void SensorRemoved(ISensor sensor) {
    5.79 +      if (Contains(sensor)) {        
    5.80 +        Remove(sensor);
    5.81 +        Config.Set(sensor.Identifier + "/tray", true);
    5.82 +      }
    5.83 +    }
    5.84 +
    5.85 +    public void Dispose() {
    5.86 +      foreach (SensorNotifyIcon icon in list)
    5.87 +        icon.Dispose();
    5.88 +    }
    5.89 +
    5.90 +    public void Redraw() {
    5.91 +      foreach (SensorNotifyIcon icon in list)
    5.92 +        icon.Update();
    5.93 +    }
    5.94 +
    5.95 +    public bool Contains(ISensor sensor) {
    5.96 +      foreach (SensorNotifyIcon icon in list)
    5.97 +        if (icon.Sensor == sensor)
    5.98 +          return true;
    5.99 +      return false;
   5.100 +    }
   5.101 +
   5.102 +    public void Add(ISensor sensor) {
   5.103 +      if (Contains(sensor)) {
   5.104 +        return;
   5.105 +      } else {
   5.106 +        list.Add(new SensorNotifyIcon(this, sensor));
   5.107 +        Config.Set(sensor.Identifier + "/tray", true);
   5.108 +      }
   5.109 +    }
   5.110 +
   5.111 +    public void Remove(ISensor sensor) {
   5.112 +      Config.Remove(sensor.Identifier + "/tray");
   5.113 +      SensorNotifyIcon instance = null;
   5.114 +      foreach (SensorNotifyIcon icon in list)
   5.115 +        if (icon.Sensor == sensor)
   5.116 +          instance = icon;
   5.117 +      if (instance != null) {
   5.118 +        list.Remove(instance);
   5.119 +        instance.Dispose();
   5.120 +      }
   5.121 +    }
   5.122 +
   5.123 +  }
   5.124 +}
     6.1 --- a/OpenHardwareMonitor.csproj	Thu Feb 11 13:22:17 2010 +0000
     6.2 +++ b/OpenHardwareMonitor.csproj	Fri Feb 12 00:36:56 2010 +0000
     6.3 @@ -58,6 +58,8 @@
     6.4      <Reference Include="System.Xml" />
     6.5    </ItemGroup>
     6.6    <ItemGroup>
     6.7 +    <Compile Include="GUI\SensorNotifyIcon.cs" />
     6.8 +    <Compile Include="GUI\SensorSystemTray.cs" />
     6.9      <Compile Include="GUI\TypeNode.cs" />
    6.10      <Compile Include="Hardware\CPU\AMD10CPU.cs" />
    6.11      <Compile Include="Hardware\CPU\AMD0FCPU.cs" />
    6.12 @@ -101,6 +103,7 @@
    6.13      <Compile Include="Hardware\Nvidia\NvidiaGPU.cs" />
    6.14      <Compile Include="Hardware\Nvidia\NvidiaGroup.cs" />
    6.15      <Compile Include="Utilities\HexStringArray.cs" />
    6.16 +    <Compile Include="Utilities\IconFactory.cs" />
    6.17      <Compile Include="Utilities\PInvokeDelegateFactory.cs" />
    6.18      <Compile Include="GUI\PlotPanel.cs">
    6.19        <SubType>UserControl</SubType>
    6.20 @@ -139,13 +142,16 @@
    6.21    <ItemGroup>
    6.22      <EmbeddedResource Include="Resources\chip.png" />
    6.23      <EmbeddedResource Include="Resources\hdd.png" />
    6.24 -    <None Include="Resources\icon.ico" />
    6.25      <EmbeddedResource Include="Resources\load.png" />
    6.26      <EmbeddedResource Include="Resources\voltage.png" />
    6.27      <EmbeddedResource Include="Resources\nvidia.png" />
    6.28    </ItemGroup>
    6.29    <ItemGroup>
    6.30      <None Include="Resources\app.manifest" />
    6.31 +    <None Include="Resources\icon.ico" />
    6.32 +  </ItemGroup>
    6.33 +  <ItemGroup>
    6.34 +    <EmbeddedResource Include="Resources\smallicon.ico" />
    6.35    </ItemGroup>
    6.36    <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
    6.37    <ProjectExtensions>
     7.1 --- a/Properties/AssemblyInfo.cs	Thu Feb 11 13:22:17 2010 +0000
     7.2 +++ b/Properties/AssemblyInfo.cs	Fri Feb 12 00:36:56 2010 +0000
     7.3 @@ -69,5 +69,5 @@
     7.4  // You can specify all the values or you can default the Build and Revision Numbers 
     7.5  // by using the '*' as shown below:
     7.6  // [assembly: AssemblyVersion("1.0.*")]
     7.7 -[assembly: AssemblyVersion("0.1.17.1")]
     7.8 -[assembly: AssemblyFileVersion("0.1.17.1")]
     7.9 +[assembly: AssemblyVersion("0.1.18.0")]
    7.10 +[assembly: AssemblyFileVersion("0.1.18.0")]
     8.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     8.2 +++ b/Utilities/IconFactory.cs	Fri Feb 12 00:36:56 2010 +0000
     8.3 @@ -0,0 +1,203 @@
     8.4 +/*
     8.5 +  
     8.6 +  Version: MPL 1.1/GPL 2.0/LGPL 2.1
     8.7 +
     8.8 +  The contents of this file are subject to the Mozilla Public License Version
     8.9 +  1.1 (the "License"); you may not use this file except in compliance with
    8.10 +  the License. You may obtain a copy of the License at
    8.11 + 
    8.12 +  http://www.mozilla.org/MPL/
    8.13 +
    8.14 +  Software distributed under the License is distributed on an "AS IS" basis,
    8.15 +  WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
    8.16 +  for the specific language governing rights and limitations under the License.
    8.17 +
    8.18 +  The Original Code is the Open Hardware Monitor code.
    8.19 +
    8.20 +  The Initial Developer of the Original Code is 
    8.21 +  Michael Möller <m.moeller@gmx.ch>.
    8.22 +  Portions created by the Initial Developer are Copyright (C) 2009-2010
    8.23 +  the Initial Developer. All Rights Reserved.
    8.24 +
    8.25 +  Contributor(s):
    8.26 +
    8.27 +  Alternatively, the contents of this file may be used under the terms of
    8.28 +  either the GNU General Public License Version 2 or later (the "GPL"), or
    8.29 +  the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
    8.30 +  in which case the provisions of the GPL or the LGPL are applicable instead
    8.31 +  of those above. If you wish to allow use of your version of this file only
    8.32 +  under the terms of either the GPL or the LGPL, and not to allow others to
    8.33 +  use your version of this file under the terms of the MPL, indicate your
    8.34 +  decision by deleting the provisions above and replace them with the notice
    8.35 +  and other provisions required by the GPL or the LGPL. If you do not delete
    8.36 +  the provisions above, a recipient may use your version of this file under
    8.37 +  the terms of any one of the MPL, the GPL or the LGPL.
    8.38 + 
    8.39 +*/
    8.40 +
    8.41 +using System;
    8.42 +using System.Collections.Generic;
    8.43 +using System.Drawing;
    8.44 +using System.Drawing.Imaging;
    8.45 +using System.IO;
    8.46 +using System.Text;
    8.47 +
    8.48 +namespace OpenHardwareMonitor.Utilities {
    8.49 +  public class IconFactory {
    8.50 +
    8.51 +    private struct BITMAPINFOHEADER {
    8.52 +      public uint Size;
    8.53 +      public int Width;
    8.54 +      public int Height;
    8.55 +      public ushort Planes;
    8.56 +      public ushort BitCount;
    8.57 +      public uint Compression;
    8.58 +      public uint SizeImage;
    8.59 +      public int XPelsPerMeter;
    8.60 +      public int YPelsPerMeter;
    8.61 +      public uint ClrUsed;
    8.62 +      public uint ClrImportant;
    8.63 +
    8.64 +      public BITMAPINFOHEADER(int width, int height, int bitCount) {
    8.65 +        this.Size = 40;
    8.66 +        this.Width = width;
    8.67 +        this.Height = height;
    8.68 +        this.Planes = 1;
    8.69 +        this.BitCount = (ushort)bitCount;
    8.70 +        this.Compression = 0;
    8.71 +        this.SizeImage = 0;
    8.72 +        this.XPelsPerMeter = 0;
    8.73 +        this.YPelsPerMeter = 0;
    8.74 +        this.ClrUsed = 0;
    8.75 +        this.ClrImportant = 0;
    8.76 +      }
    8.77 +
    8.78 +      public void Write(BinaryWriter bw) {
    8.79 +        bw.Write(Size);
    8.80 +			  bw.Write(Width);
    8.81 +			  bw.Write(Height);
    8.82 +			  bw.Write(Planes);
    8.83 +			  bw.Write(BitCount);
    8.84 +			  bw.Write(Compression);
    8.85 +			  bw.Write(SizeImage);
    8.86 +			  bw.Write(XPelsPerMeter);
    8.87 +			  bw.Write(YPelsPerMeter);
    8.88 +			  bw.Write(ClrUsed);
    8.89 +			  bw.Write(ClrImportant);
    8.90 +      }
    8.91 +    }
    8.92 +
    8.93 +    private struct ICONIMAGE {
    8.94 +      public BITMAPINFOHEADER Header;
    8.95 +      public byte[] Colors;
    8.96 +      public byte[] XOR;
    8.97 +      public byte[] AND;
    8.98 +
    8.99 +      public ICONIMAGE(int width, int height, byte[] colors) {
   8.100 +        this.Header = new BITMAPINFOHEADER(width, height << 1, 
   8.101 +          (8 * colors.Length) / (width * height));
   8.102 +        this.Colors = colors;
   8.103 +        int maskSize = (width * height) >> 3;
   8.104 +        this.XOR = new byte[maskSize];
   8.105 +        this.AND = new byte[maskSize];
   8.106 +      }
   8.107 +
   8.108 +      public void Write(BinaryWriter bw) {
   8.109 +        Header.Write(bw);
   8.110 +        int stride = Header.Width << 2;
   8.111 +        for (int i = (Header.Height >> 1) - 1; i >= 0; i--)
   8.112 +          bw.Write(Colors, i * stride, stride);
   8.113 +        bw.Write(XOR);        
   8.114 +        bw.Write(AND);
   8.115 +      }
   8.116 +    }
   8.117 +
   8.118 +    private struct ICONDIRENTRY {
   8.119 +      public byte Width;
   8.120 +      public byte Height;
   8.121 +      public byte ColorCount;
   8.122 +      public byte Reserved;
   8.123 +      public ushort Planes;
   8.124 +      public ushort BitCount;
   8.125 +      public uint BytesInRes;
   8.126 +      public uint ImageOffset;
   8.127 +
   8.128 +      public ICONDIRENTRY(ICONIMAGE image, int imageOffset) {
   8.129 +        this.Width = (byte)image.Header.Width;
   8.130 +        this.Height = (byte)(image.Header.Height >> 1);
   8.131 +        this.ColorCount = 0;
   8.132 +        this.Reserved = 0;
   8.133 +        this.Planes = image.Header.Planes;
   8.134 +        this.BitCount = image.Header.BitCount;
   8.135 +        this.BytesInRes = (uint)(image.Header.Size +
   8.136 +          image.Colors.Length + image.XOR.Length + image.AND.Length);
   8.137 +        this.ImageOffset = (uint)imageOffset;
   8.138 +      }
   8.139 +
   8.140 +      public void Write(BinaryWriter bw) {
   8.141 +        bw.Write(Width);
   8.142 +        bw.Write(Height);
   8.143 +        bw.Write(ColorCount);
   8.144 +        bw.Write(Reserved);
   8.145 +        bw.Write(Planes);
   8.146 +        bw.Write(BitCount);
   8.147 +        bw.Write(BytesInRes);
   8.148 +        bw.Write(ImageOffset);
   8.149 +      }
   8.150 +
   8.151 +      public uint Size {
   8.152 +        get { return 16; }
   8.153 +      }
   8.154 +    }
   8.155 +
   8.156 +    private struct ICONDIR {
   8.157 +      public ushort Reserved;
   8.158 +      public ushort Type;
   8.159 +      public ushort Count;
   8.160 +      public ICONDIRENTRY[] Entries;
   8.161 +
   8.162 +      public ICONDIR(ICONDIRENTRY[] entries) {
   8.163 +        this.Reserved = 0;
   8.164 +        this.Type = 1;
   8.165 +        this.Count = (ushort)entries.Length;
   8.166 +        this.Entries = entries;
   8.167 +      }
   8.168 +
   8.169 +      public void Write(BinaryWriter bw) {
   8.170 +        bw.Write(Reserved);
   8.171 +        bw.Write(Type);
   8.172 +        bw.Write(Count);
   8.173 +        for (int i = 0; i < Entries.Length; i++)
   8.174 +          Entries[i].Write(bw);
   8.175 +      }
   8.176 +
   8.177 +      public uint Size {
   8.178 +        get { return (uint)(6 + Entries.Length * 
   8.179 +          (Entries.Length > 0 ? Entries[0].Size : 0)); } 
   8.180 +      }
   8.181 +    }
   8.182 +	
   8.183 +    public static Icon Create(byte[] colors, int width, int height, 
   8.184 +      PixelFormat format) {
   8.185 +      if (format != PixelFormat.Format32bppArgb)
   8.186 +        throw new NotImplementedException();
   8.187 +
   8.188 +      ICONIMAGE image = new ICONIMAGE(width, height, colors);
   8.189 +      ICONDIR dir = new ICONDIR(
   8.190 +        new ICONDIRENTRY[] { new ICONDIRENTRY(image, 0) } );
   8.191 +      dir.Entries[0].ImageOffset = dir.Size;
   8.192 +
   8.193 +      Icon icon;
   8.194 +      using (BinaryWriter bw = new BinaryWriter(new MemoryStream())) {
   8.195 +				dir.Write(bw);
   8.196 +        image.Write(bw);
   8.197 +
   8.198 +				bw.BaseStream.Position = 0;
   8.199 +        icon = new Icon(bw.BaseStream);
   8.200 +			}
   8.201 +
   8.202 +      return icon;
   8.203 +    }
   8.204 +
   8.205 +  }
   8.206 +}