GUI/SensorNotifyIcon.cs
author moel.mich
Fri, 21 Jan 2011 21:41:14 +0000
changeset 249 3b5be5dce071
parent 202 551243a66b32
child 252 e62afa69214f
permissions -rw-r--r--
Added initial support for Intel Sandy Bridge CPUs.
     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.Drawing;
    40 using System.Drawing.Drawing2D;
    41 using System.Drawing.Imaging;
    42 using System.Drawing.Text;
    43 using System.Runtime.InteropServices;
    44 using System.Windows.Forms;
    45 using OpenHardwareMonitor.Hardware;
    46 using OpenHardwareMonitor.Utilities;
    47 
    48 namespace OpenHardwareMonitor.GUI {
    49   public class SensorNotifyIcon : IDisposable {
    50 
    51     private ISensor sensor;
    52     private NotifyIcon notifyIcon;
    53     private Bitmap bitmap;
    54     private Graphics graphics;
    55     private Color color;
    56     private Color darkColor;
    57     private Brush brush;
    58     private Brush darkBrush;
    59     private Pen pen;
    60     private Font font;
    61 
    62     public SensorNotifyIcon(SystemTray sensorSystemTray, ISensor sensor,
    63       bool balloonTip, PersistentSettings settings) 
    64     {
    65       this.sensor = sensor;
    66       this.notifyIcon = new NotifyIcon();
    67 
    68       Color defaultColor = Color.Black;
    69       if (sensor.SensorType == SensorType.Load ||
    70           sensor.SensorType == SensorType.Control ||
    71           sensor.SensorType == SensorType.Level) 
    72       {
    73         defaultColor = Color.FromArgb(0xff, 0x70, 0x8c, 0xf1);
    74       }
    75       Color = settings.GetValue(new Identifier(sensor.Identifier, 
    76         "traycolor").ToString(), defaultColor);      
    77       
    78       this.pen = new Pen(Color.FromArgb(96, Color.Black));
    79       this.font = SystemFonts.MessageBoxFont;
    80 
    81       ContextMenu contextMenu = new ContextMenu();
    82       MenuItem hideShowItem = new MenuItem("Hide/Show");
    83       hideShowItem.Click += delegate(object obj, EventArgs args) {
    84         sensorSystemTray.SendHideShowCommand();
    85       };
    86       contextMenu.MenuItems.Add(hideShowItem);
    87       contextMenu.MenuItems.Add(new MenuItem("-"));
    88       MenuItem removeItem = new MenuItem("Remove Sensor");
    89       removeItem.Click += delegate(object obj, EventArgs args) {
    90         sensorSystemTray.Remove(this.sensor);
    91       };
    92       contextMenu.MenuItems.Add(removeItem);
    93       MenuItem colorItem = new MenuItem("Change Color...");
    94       colorItem.Click += delegate(object obj, EventArgs args) {
    95         ColorDialog dialog = new ColorDialog();
    96         dialog.Color = Color;
    97         if (dialog.ShowDialog() == DialogResult.OK) {
    98           Color = dialog.Color;
    99           settings.SetValue(new Identifier(sensor.Identifier,
   100             "traycolor").ToString(), Color);
   101         }
   102       };
   103       contextMenu.MenuItems.Add(colorItem);
   104       contextMenu.MenuItems.Add(new MenuItem("-"));
   105       MenuItem exitItem = new MenuItem("Exit");
   106       exitItem.Click += delegate(object obj, EventArgs args) {
   107         sensorSystemTray.SendExitCommand();
   108       };
   109       contextMenu.MenuItems.Add(exitItem);
   110       this.notifyIcon.ContextMenu = contextMenu;
   111       this.notifyIcon.DoubleClick += delegate(object obj, EventArgs args) {
   112         sensorSystemTray.SendHideShowCommand();
   113       };
   114 
   115       this.bitmap = new Bitmap(16, 16, PixelFormat.Format32bppArgb);
   116       this.graphics = Graphics.FromImage(this.bitmap);
   117 
   118       if (Environment.OSVersion.Version.Major > 5) {
   119         this.graphics.TextRenderingHint = TextRenderingHint.ClearTypeGridFit;
   120         this.graphics.SmoothingMode = SmoothingMode.HighQuality;
   121       }
   122     }
   123 
   124     public ISensor Sensor {
   125       get { return sensor; }
   126     }
   127 
   128     public Color Color {
   129       get { return color; }
   130       set { 
   131         this.color = value;
   132         this.darkColor = Color.FromArgb(255,
   133           this.color.R / 3,
   134           this.color.G / 3,
   135           this.color.B / 3);
   136         Brush brush = this.brush;
   137         this.brush = new SolidBrush(this.color);
   138         if (brush != null)
   139           brush.Dispose();
   140         Brush darkBrush = this.darkBrush;
   141         this.darkBrush = new SolidBrush(this.darkColor);
   142         if (darkBrush != null)
   143           darkBrush.Dispose();
   144       }
   145     }
   146 
   147     public void Dispose() {      
   148       Icon icon = notifyIcon.Icon;
   149       notifyIcon.Icon = null;
   150       if (icon != null)
   151         icon.Dispose();      
   152       notifyIcon.Dispose();
   153 
   154       if (brush != null)
   155         brush.Dispose();
   156       if (darkBrush != null)
   157         darkBrush.Dispose();
   158       pen.Dispose();
   159       graphics.Dispose();      
   160       bitmap.Dispose();      
   161     }
   162 
   163     private string GetString() {
   164       switch (sensor.SensorType) {
   165         case SensorType.Voltage:
   166           return string.Format("{0:F11}", sensor.Value);
   167         case SensorType.Clock:
   168           return string.Format("{0:F11}", 1e-3f * sensor.Value);
   169         case SensorType.Load: 
   170           return string.Format("{0:F0}", sensor.Value);
   171         case SensorType.Temperature: 
   172           return string.Format("{0:F0}", sensor.Value);
   173         case SensorType.Fan: 
   174           return string.Format("{0:F11}", 1e-3f * sensor.Value);
   175         case SensorType.Flow:
   176           return string.Format("{0:F11}", 1e-3f * sensor.Value);
   177         case SensorType.Control:
   178           return string.Format("{0:F0}", sensor.Value);
   179         case SensorType.Level:
   180           return string.Format("{0:F0}", sensor.Value);
   181       }
   182       return "-";
   183     }
   184 
   185     private Icon CreateTransparentIcon() {
   186 
   187       graphics.Clear(Color.Black);
   188       TextRenderer.DrawText(graphics, GetString(), font,
   189         new Point(-2, 0), Color.White, Color.Black);        
   190 
   191       BitmapData data = bitmap.LockBits(
   192         new Rectangle(0, 0, bitmap.Width, bitmap.Height),
   193         ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);
   194 
   195       IntPtr Scan0 = data.Scan0;
   196 
   197       int numBytes = bitmap.Width * bitmap.Height * 4;
   198       byte[] bytes = new byte[numBytes];
   199       Marshal.Copy(Scan0, bytes, 0, numBytes);
   200       bitmap.UnlockBits(data);
   201 
   202       byte red, green, blue;
   203       for (int i = 0; i < bytes.Length; i += 4) {
   204         blue = bytes[i];
   205         green = bytes[i + 1];
   206         red = bytes[i + 2];
   207 
   208         bytes[i] = color.B;
   209         bytes[i + 1] = color.G;
   210         bytes[i + 2] = color.R;
   211         bytes[i + 3] = (byte)(0.3 * red + 0.59 * green + 0.11 * blue);
   212       }
   213 
   214       return IconFactory.Create(bytes, 16, 16, PixelFormat.Format32bppArgb);
   215     }
   216 
   217     private Icon CreatePercentageIcon() {      
   218       try {
   219         graphics.Clear(Color.Transparent);
   220       } catch (ArgumentException) {
   221         graphics.Clear(Color.Black);
   222       }
   223       graphics.FillRectangle(darkBrush, 0.5f, -0.5f, 14, 16);
   224       float y = 0.16f * (100 - sensor.Value.Value);
   225       graphics.FillRectangle(brush, 0.5f, -0.5f + y, 14, 16 - y);
   226       graphics.DrawRectangle(pen, 1, 0, 13, 15);
   227 
   228       BitmapData data = bitmap.LockBits(
   229         new Rectangle(0, 0, bitmap.Width, bitmap.Height),
   230         ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);
   231       byte[] bytes = new byte[bitmap.Width * bitmap.Height * 4];
   232       Marshal.Copy(data.Scan0, bytes, 0, bytes.Length);
   233       bitmap.UnlockBits(data);
   234 
   235       return IconFactory.Create(bytes, 16, 16, PixelFormat.Format32bppArgb);
   236     }
   237 
   238     public void Update() {
   239       Icon icon = notifyIcon.Icon;
   240 
   241       switch (sensor.SensorType) {
   242         case SensorType.Load:
   243         case SensorType.Control:
   244         case SensorType.Level:
   245           notifyIcon.Icon = CreatePercentageIcon();
   246           break;
   247         default:
   248           notifyIcon.Icon = CreateTransparentIcon();
   249           break;
   250       }
   251 
   252       if (icon != null) 
   253         icon.Dispose();
   254 
   255       string format = "";
   256       switch (sensor.SensorType) {
   257         case SensorType.Voltage: format = "\n{0}: {1:F2} V"; break;
   258         case SensorType.Clock: format = "\n{0}: {1:F0} MHz"; break;
   259         case SensorType.Load: format = "\n{0}: {1:F1} %"; break;
   260         case SensorType.Temperature: format = "\n{0}: {1:F1} °C"; break;
   261         case SensorType.Fan: format = "\n{0}: {1:F0} RPM"; break;
   262         case SensorType.Flow: format = "\n{0}: {1:F0} L/h"; break;
   263         case SensorType.Control: format = "\n{0}: {1:F1} %"; break;
   264         case SensorType.Level: format = "\n{0}: {1:F1} %"; break;
   265       }
   266       string formattedValue = string.Format(format, sensor.Name, sensor.Value);
   267       string hardwareName = sensor.Hardware.Name;
   268       hardwareName = hardwareName.Substring(0, 
   269         Math.Min(63 - formattedValue.Length, hardwareName.Length));
   270       string text = hardwareName + formattedValue;
   271       if (text.Length > 63)
   272         text = null;
   273 
   274       notifyIcon.Text = text;
   275       notifyIcon.Visible = true;         
   276     }
   277   }
   278 }