GUI/SensorNotifyIcon.cs
author moel.mich
Sun, 09 May 2010 16:22:13 +0000
changeset 110 411b72b73d8f
parent 86 b4f0f206173d
child 116 c92e98bc2073
permissions -rw-r--r--
Refactored the hardware code and added the visitor pattern for operations on the computer/hardware/sensor/parameter tree.
     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 = new Font(SystemFonts.MessageBoxFont.FontFamily, 9);
    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       this.graphics.TextRenderingHint = TextRenderingHint.ClearTypeGridFit;
   102       this.graphics.SmoothingMode = SmoothingMode.HighQuality;
   103     }
   104 
   105     public ISensor Sensor {
   106       get { return sensor; }
   107     }
   108 
   109     public Color Color {
   110       get { return color; }
   111       set { 
   112         this.color = value;
   113         this.darkColor = Color.FromArgb(255,
   114           this.color.R / 3,
   115           this.color.G / 3,
   116           this.color.B / 3);
   117         Brush brush = this.brush;
   118         this.brush = new SolidBrush(this.color);
   119         if (brush != null)
   120           brush.Dispose();
   121         Brush darkBrush = this.darkBrush;
   122         this.darkBrush = new SolidBrush(this.darkColor);
   123         if (darkBrush != null)
   124           darkBrush.Dispose();
   125       }
   126     }
   127 
   128     public void Dispose() {      
   129       Icon icon = notifyIcon.Icon;
   130       notifyIcon.Icon = null;
   131       if (icon != null)
   132         icon.Dispose();      
   133       notifyIcon.Dispose();
   134 
   135       if (brush != null)
   136         brush.Dispose();
   137       if (darkBrush != null)
   138         darkBrush.Dispose();
   139       pen.Dispose();
   140       font.Dispose();
   141       graphics.Dispose();      
   142       bitmap.Dispose();      
   143     }
   144 
   145     private string GetString() {
   146       switch (sensor.SensorType) {
   147         case SensorType.Voltage:
   148           return string.Format("{0:F11}", sensor.Value);
   149         case SensorType.Clock:
   150           return string.Format("{0:F11}", 1e-3f * sensor.Value);
   151         case SensorType.Load: 
   152           return string.Format("{0:F0}", sensor.Value < 99 ? sensor.Value : 99);
   153         case SensorType.Temperature: 
   154           return string.Format("{0:F0}", sensor.Value);
   155         case SensorType.Fan: 
   156           return string.Format("{0:F11}", 1e-3f * sensor.Value);
   157         case SensorType.Flow:
   158           return string.Format("{0:F11}", 1e-3f * sensor.Value);
   159       }
   160       return "-";
   161     }
   162 
   163     private Icon CreateTransparentIcon() {
   164 
   165       graphics.Clear(Color.Black);
   166       TextRenderer.DrawText(graphics, GetString(), font,
   167         new Point(-2, 0), Color.White, Color.Black);
   168 
   169       BitmapData data = bitmap.LockBits(
   170         new Rectangle(0, 0, bitmap.Width, bitmap.Height),
   171         ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);
   172 
   173       int stride = data.Stride;
   174       IntPtr Scan0 = data.Scan0;
   175 
   176       int numBytes = bitmap.Width * bitmap.Height * 4;
   177       byte[] bytes = new byte[numBytes];
   178       Marshal.Copy(Scan0, bytes, 0, numBytes);
   179       bitmap.UnlockBits(data);
   180 
   181       byte red, green, blue;
   182       for (int i = 0; i < bytes.Length; i += 4) {
   183         blue = bytes[i];
   184         green = bytes[i + 1];
   185         red = bytes[i + 2];
   186 
   187         bytes[i] = color.B;
   188         bytes[i + 1] = color.G;
   189         bytes[i + 2] = color.R;
   190         bytes[i + 3] = (byte)(0.3 * red + 0.59 * green + 0.11 * blue);
   191       }
   192 
   193       return IconFactory.Create(bytes, 16, 16, PixelFormat.Format32bppArgb);
   194     }
   195 
   196     private Icon CreateLoadIcon() {      
   197       try {
   198         graphics.Clear(Color.Transparent);
   199       } catch (ArgumentException) {
   200         graphics.Clear(Color.Black);
   201       }
   202       graphics.FillRectangle(darkBrush, 0.5f, -0.5f, 14, 16);
   203       float y = 0.16f * (100 - sensor.Value.Value);
   204       graphics.FillRectangle(brush, 0.5f, -0.5f + y, 14, 16 - y);
   205       graphics.DrawRectangle(pen, 1, 0, 13, 15);
   206 
   207       BitmapData data = bitmap.LockBits(
   208         new Rectangle(0, 0, bitmap.Width, bitmap.Height),
   209         ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);
   210       byte[] bytes = new byte[bitmap.Width * bitmap.Height * 4];
   211       Marshal.Copy(data.Scan0, bytes, 0, bytes.Length);
   212       bitmap.UnlockBits(data);
   213 
   214       return IconFactory.Create(bytes, 16, 16, PixelFormat.Format32bppArgb);
   215     }
   216 
   217     public void Update() {
   218       Icon icon = notifyIcon.Icon;
   219 
   220       if (sensor.SensorType == SensorType.Load) {
   221         notifyIcon.Icon = CreateLoadIcon();
   222       } else {
   223         notifyIcon.Icon = CreateTransparentIcon();
   224       }
   225       if (icon != null) 
   226         icon.Dispose();
   227 
   228       string format = "";
   229       switch (sensor.SensorType) {
   230         case SensorType.Voltage: format = "{0}\n{1}: {2:F2} V"; break;
   231         case SensorType.Clock: format = "{0}\n{1}: {2:F0} MHz"; break;
   232         case SensorType.Load: format = "{0}\n{1}: {2:F1} %"; break;
   233         case SensorType.Temperature: format = "{0}\n{1}: {2:F1} °C"; break;
   234         case SensorType.Fan: format = "{0}\n{1}: {2:F0} RPM"; break;
   235         case SensorType.Flow: format = "{0}\n{1}: {2:F0} L/h"; break;
   236       }
   237 
   238       notifyIcon.Text = string.Format(format, sensor.Hardware.Name, sensor.Name,
   239         sensor.Value);    
   240       notifyIcon.Visible = true;         
   241     }
   242   }
   243 }