GUI/SensorNotifyIcon.cs
author moel.mich
Sat, 15 May 2010 14:16:00 +0000
changeset 118 407f98562c3b
parent 117 14329d236f05
child 133 9ad699538c89
permissions -rw-r--r--
Added a sensor type Control (with unit percent) for (fan) PWM control sensors. Fixed Issue 2.
     1 /*
     2   
     3   Version: MPL 1.1/GPL 2.0/LGPL 2.1
     4 
     5   The contents of this file are subject to the Mozilla Public License Version
     6   1.1 (the "License"); you may not use this file except in compliance with
     7   the License. You may obtain a copy of the License at
     8  
     9   http://www.mozilla.org/MPL/
    10 
    11   Software distributed under the License is distributed on an "AS IS" basis,
    12   WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
    13   for the specific language governing rights and limitations under the License.
    14 
    15   The Original Code is the Open Hardware Monitor code.
    16 
    17   The Initial Developer of the Original Code is 
    18   Michael Möller <m.moeller@gmx.ch>.
    19   Portions created by the Initial Developer are Copyright (C) 2009-2010
    20   the Initial Developer. All Rights Reserved.
    21 
    22   Contributor(s):
    23 
    24   Alternatively, the contents of this file may be used under the terms of
    25   either the GNU General Public License Version 2 or later (the "GPL"), or
    26   the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
    27   in which case the provisions of the GPL or the LGPL are applicable instead
    28   of those above. If you wish to allow use of your version of this file only
    29   under the terms of either the GPL or the LGPL, and not to allow others to
    30   use your version of this file under the terms of the MPL, indicate your
    31   decision by deleting the provisions above and replace them with the notice
    32   and other provisions required by the GPL or the LGPL. If you do not delete
    33   the provisions above, a recipient may use your version of this file under
    34   the terms of any one of the MPL, the GPL or the LGPL.
    35  
    36 */
    37 
    38 using System;
    39 using System.Collections.Generic;
    40 using System.Drawing;
    41 using System.Drawing.Drawing2D;
    42 using System.Drawing.Imaging;
    43 using System.Drawing.Text;
    44 using System.Text;
    45 using System.Windows.Forms;
    46 using System.Runtime.InteropServices;
    47 using OpenHardwareMonitor.Hardware;
    48 using OpenHardwareMonitor.Utilities;
    49 
    50 namespace OpenHardwareMonitor.GUI {
    51   public class SensorNotifyIcon : IDisposable {
    52 
    53     private ISensor sensor;
    54     private NotifyIcon notifyIcon;
    55     private Bitmap bitmap;
    56     private Graphics graphics;
    57     private Color color;
    58     private Color darkColor;
    59     private Brush brush;
    60     private Brush darkBrush;
    61     private Pen pen;
    62     private Font font;
    63 
    64     public SensorNotifyIcon(SensorSystemTray sensorSystemTray, ISensor sensor,
    65       bool balloonTip) 
    66     {
    67       this.sensor = sensor;
    68       this.notifyIcon = new NotifyIcon();
    69 
    70       Color defaultColor = Color.Black;
    71       if (sensor.SensorType == SensorType.Load) {
    72         defaultColor = Color.FromArgb(0xff, 0x70, 0x8c, 0xf1);
    73       }
    74       Color = Config.Get(new Identifier(sensor.Identifier, 
    75         "traycolor").ToString(), defaultColor);      
    76       
    77       this.pen = new Pen(Color.FromArgb(96, Color.Black));
    78       this.font = SystemFonts.MessageBoxFont;
    79 
    80       ContextMenuStrip contextMenuStrip = new ContextMenuStrip();
    81       ToolStripMenuItem removeItem = new ToolStripMenuItem("Remove");
    82       removeItem.Click += delegate(object obj, EventArgs args) {
    83         sensorSystemTray.Remove(this.sensor);
    84       };
    85       contextMenuStrip.Items.Add(removeItem);
    86       ToolStripMenuItem colorItem = new ToolStripMenuItem("Change Color...");
    87       colorItem.Click += delegate(object obj, EventArgs args) {
    88         ColorDialog dialog = new ColorDialog();
    89         dialog.Color = Color;
    90         if (dialog.ShowDialog() == DialogResult.OK) {
    91           Color = dialog.Color;
    92           Config.Set(new Identifier(sensor.Identifier,
    93             "traycolor").ToString(), Color);
    94         }
    95       };
    96       contextMenuStrip.Items.Add(colorItem);
    97       this.notifyIcon.ContextMenuStrip = contextMenuStrip;
    98 
    99       this.bitmap = new Bitmap(16, 16, PixelFormat.Format32bppArgb);
   100       this.graphics = Graphics.FromImage(this.bitmap);
   101 
   102       if (Environment.OSVersion.Version.Major > 5) {
   103         this.graphics.TextRenderingHint = TextRenderingHint.ClearTypeGridFit;
   104         this.graphics.SmoothingMode = SmoothingMode.HighQuality;
   105       }
   106     }
   107 
   108     public ISensor Sensor {
   109       get { return sensor; }
   110     }
   111 
   112     public Color Color {
   113       get { return color; }
   114       set { 
   115         this.color = value;
   116         this.darkColor = Color.FromArgb(255,
   117           this.color.R / 3,
   118           this.color.G / 3,
   119           this.color.B / 3);
   120         Brush brush = this.brush;
   121         this.brush = new SolidBrush(this.color);
   122         if (brush != null)
   123           brush.Dispose();
   124         Brush darkBrush = this.darkBrush;
   125         this.darkBrush = new SolidBrush(this.darkColor);
   126         if (darkBrush != null)
   127           darkBrush.Dispose();
   128       }
   129     }
   130 
   131     public void Dispose() {      
   132       Icon icon = notifyIcon.Icon;
   133       notifyIcon.Icon = null;
   134       if (icon != null)
   135         icon.Dispose();      
   136       notifyIcon.Dispose();
   137 
   138       if (brush != null)
   139         brush.Dispose();
   140       if (darkBrush != null)
   141         darkBrush.Dispose();
   142       pen.Dispose();
   143       graphics.Dispose();      
   144       bitmap.Dispose();      
   145     }
   146 
   147     private string GetString() {
   148       switch (sensor.SensorType) {
   149         case SensorType.Voltage:
   150           return string.Format("{0:F11}", sensor.Value);
   151         case SensorType.Clock:
   152           return string.Format("{0:F11}", 1e-3f * sensor.Value);
   153         case SensorType.Load: 
   154           return string.Format("{0:F0}", sensor.Value);
   155         case SensorType.Temperature: 
   156           return string.Format("{0:F0}", sensor.Value);
   157         case SensorType.Fan: 
   158           return string.Format("{0:F11}", 1e-3f * sensor.Value);
   159         case SensorType.Flow:
   160           return string.Format("{0:F11}", 1e-3f * sensor.Value);
   161         case SensorType.Control:
   162           return string.Format("{0:F0}", sensor.Value);
   163       }
   164       return "-";
   165     }
   166 
   167     private Icon CreateTransparentIcon() {
   168 
   169       graphics.Clear(Color.Black);
   170       TextRenderer.DrawText(graphics, GetString(), font,
   171         new Point(-2, 0), Color.White, Color.Black);        
   172 
   173       BitmapData data = bitmap.LockBits(
   174         new Rectangle(0, 0, bitmap.Width, bitmap.Height),
   175         ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);
   176 
   177       int stride = data.Stride;
   178       IntPtr Scan0 = data.Scan0;
   179 
   180       int numBytes = bitmap.Width * bitmap.Height * 4;
   181       byte[] bytes = new byte[numBytes];
   182       Marshal.Copy(Scan0, bytes, 0, numBytes);
   183       bitmap.UnlockBits(data);
   184 
   185       byte red, green, blue;
   186       for (int i = 0; i < bytes.Length; i += 4) {
   187         blue = bytes[i];
   188         green = bytes[i + 1];
   189         red = bytes[i + 2];
   190 
   191         bytes[i] = color.B;
   192         bytes[i + 1] = color.G;
   193         bytes[i + 2] = color.R;
   194         bytes[i + 3] = (byte)(0.3 * red + 0.59 * green + 0.11 * blue);
   195       }
   196 
   197       return IconFactory.Create(bytes, 16, 16, PixelFormat.Format32bppArgb);
   198     }
   199 
   200     private Icon CreateLoadIcon() {      
   201       try {
   202         graphics.Clear(Color.Transparent);
   203       } catch (ArgumentException) {
   204         graphics.Clear(Color.Black);
   205       }
   206       graphics.FillRectangle(darkBrush, 0.5f, -0.5f, 14, 16);
   207       float y = 0.16f * (100 - sensor.Value.Value);
   208       graphics.FillRectangle(brush, 0.5f, -0.5f + y, 14, 16 - y);
   209       graphics.DrawRectangle(pen, 1, 0, 13, 15);
   210 
   211       BitmapData data = bitmap.LockBits(
   212         new Rectangle(0, 0, bitmap.Width, bitmap.Height),
   213         ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);
   214       byte[] bytes = new byte[bitmap.Width * bitmap.Height * 4];
   215       Marshal.Copy(data.Scan0, bytes, 0, bytes.Length);
   216       bitmap.UnlockBits(data);
   217 
   218       return IconFactory.Create(bytes, 16, 16, PixelFormat.Format32bppArgb);
   219     }
   220 
   221     public void Update() {
   222       Icon icon = notifyIcon.Icon;
   223 
   224       if (sensor.SensorType == SensorType.Load) {
   225         notifyIcon.Icon = CreateLoadIcon();
   226       } else {
   227         notifyIcon.Icon = CreateTransparentIcon();
   228       }
   229       if (icon != null) 
   230         icon.Dispose();
   231 
   232       string format = "";
   233       switch (sensor.SensorType) {
   234         case SensorType.Voltage: format = "\n{0}: {1:F2} V"; break;
   235         case SensorType.Clock: format = "\n{0}: {1:F0} MHz"; break;
   236         case SensorType.Load: format = "\n{0}: {1:F1} %"; break;
   237         case SensorType.Temperature: format = "\n{0}: {1:F1} °C"; break;
   238         case SensorType.Fan: format = "\n{0}: {1:F0} RPM"; break;
   239         case SensorType.Flow: format = "\n{0}: {1:F0} L/h"; break;
   240         case SensorType.Control: format = "\n{0}: {1:F1} %"; break;
   241       }
   242       string formattedValue = string.Format(format, sensor.Name, sensor.Value);
   243       string hardwareName = sensor.Hardware.Name;
   244       hardwareName = hardwareName.Substring(0, 
   245         Math.Min(63 - formattedValue.Length, hardwareName.Length));
   246       string text = hardwareName + formattedValue;
   247       if (text.Length > 63)
   248         text = null;
   249 
   250       notifyIcon.Text = text;
   251       notifyIcon.Visible = true;         
   252     }
   253   }
   254 }