moel@40: /* moel@40: moel@40: Version: MPL 1.1/GPL 2.0/LGPL 2.1 moel@40: moel@40: The contents of this file are subject to the Mozilla Public License Version moel@40: 1.1 (the "License"); you may not use this file except in compliance with moel@40: the License. You may obtain a copy of the License at moel@40: moel@40: http://www.mozilla.org/MPL/ moel@40: moel@40: Software distributed under the License is distributed on an "AS IS" basis, moel@40: WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License moel@40: for the specific language governing rights and limitations under the License. moel@40: moel@40: The Original Code is the Open Hardware Monitor code. moel@40: moel@40: The Initial Developer of the Original Code is moel@40: Michael Möller . moel@40: Portions created by the Initial Developer are Copyright (C) 2009-2010 moel@40: the Initial Developer. All Rights Reserved. moel@40: moel@40: Contributor(s): moel@40: moel@40: Alternatively, the contents of this file may be used under the terms of moel@40: either the GNU General Public License Version 2 or later (the "GPL"), or moel@40: the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), moel@40: in which case the provisions of the GPL or the LGPL are applicable instead moel@40: of those above. If you wish to allow use of your version of this file only moel@40: under the terms of either the GPL or the LGPL, and not to allow others to moel@40: use your version of this file under the terms of the MPL, indicate your moel@40: decision by deleting the provisions above and replace them with the notice moel@40: and other provisions required by the GPL or the LGPL. If you do not delete moel@40: the provisions above, a recipient may use your version of this file under moel@40: the terms of any one of the MPL, the GPL or the LGPL. moel@40: moel@40: */ moel@40: moel@40: using System; moel@40: using System.Collections.Generic; moel@40: using System.Drawing; moel@40: using System.Drawing.Drawing2D; moel@40: using System.Drawing.Imaging; moel@40: using System.Drawing.Text; moel@40: using System.Text; moel@40: using System.Windows.Forms; moel@40: using System.Runtime.InteropServices; moel@40: using OpenHardwareMonitor.Hardware; moel@40: using OpenHardwareMonitor.Utilities; moel@40: moel@40: namespace OpenHardwareMonitor.GUI { moel@40: public class SensorNotifyIcon : IDisposable { moel@40: moel@40: private ISensor sensor; moel@40: private NotifyIcon notifyIcon; moel@40: private Bitmap bitmap; moel@40: private Graphics graphics; moel@40: private int majorVersion; moel@40: moel@40: public SensorNotifyIcon(SensorSystemTray sensorSystemTray, ISensor sensor) { moel@40: this.sensor = sensor; moel@40: this.notifyIcon = new NotifyIcon(); moel@40: this.majorVersion = Environment.OSVersion.Version.Major; moel@40: moel@40: ContextMenuStrip contextMenuStrip = new ContextMenuStrip(); moel@40: ToolStripMenuItem item = new ToolStripMenuItem("Remove"); moel@40: item.Click += delegate(object obj, EventArgs args) { moel@40: sensorSystemTray.Remove(sensor); moel@40: }; moel@40: contextMenuStrip.Items.Add(item); moel@40: this.notifyIcon.ContextMenuStrip = contextMenuStrip; moel@40: moel@40: this.bitmap = new Bitmap(16, 16, PixelFormat.Format32bppArgb); moel@40: this.graphics = Graphics.FromImage(this.bitmap); moel@40: this.graphics.TextRenderingHint = TextRenderingHint.ClearTypeGridFit; moel@40: this.graphics.SmoothingMode = SmoothingMode.HighQuality; moel@40: } moel@40: moel@40: public ISensor Sensor { moel@40: get { return sensor; } moel@40: } moel@40: moel@40: public void Dispose() { moel@40: Icon icon = notifyIcon.Icon; moel@40: notifyIcon.Icon = null; moel@40: if (icon != null) moel@40: icon.Dispose(); moel@40: notifyIcon.Dispose(); moel@40: notifyIcon = null; moel@40: moel@40: graphics.Dispose(); moel@40: graphics = null; moel@40: bitmap.Dispose(); moel@40: bitmap = null; moel@40: } moel@40: moel@40: private string GetString() { moel@40: switch (sensor.SensorType) { moel@40: case SensorType.Voltage: moel@40: return string.Format("{0:F11}", sensor.Value); moel@40: case SensorType.Clock: moel@40: return string.Format("{0:F11}", 1e-3f * sensor.Value); moel@40: case SensorType.Load: moel@40: return string.Format("{0:F0}", sensor.Value < 99 ? sensor.Value : 99); moel@40: case SensorType.Temperature: moel@40: return string.Format("{0:F0}", sensor.Value); moel@40: case SensorType.Fan: moel@40: return string.Format("{0:F11}", 1e-3f * sensor.Value); moel@40: } moel@40: return "-"; moel@40: } moel@40: moel@40: private Icon CreateSimpleIcon() { moel@40: moel@40: graphics.Clear(SystemColors.ButtonFace); moel@40: TextRenderer.DrawText(graphics, GetString(), SystemFonts.StatusFont, moel@40: new Point(-2, 0), Color.Blue, SystemColors.ButtonFace); moel@40: moel@40: BitmapData data = bitmap.LockBits( moel@40: new Rectangle(0, 0, bitmap.Width, bitmap.Height), moel@40: ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb); moel@40: moel@40: int stride = data.Stride; moel@40: IntPtr Scan0 = data.Scan0; moel@40: moel@40: int numBytes = bitmap.Width * bitmap.Height * 4; moel@40: byte[] bytes = new byte[numBytes]; moel@40: Marshal.Copy(Scan0, bytes, 0, numBytes); moel@40: bitmap.UnlockBits(data); moel@40: moel@40: return IconFactory.Create(bytes, 16, 16, PixelFormat.Format32bppArgb); moel@40: } moel@40: moel@40: private Icon CreateTransparentIcon() { moel@40: moel@40: graphics.Clear(Color.Black); moel@40: TextRenderer.DrawText(graphics, GetString(), SystemFonts.StatusFont, moel@40: new Point(-2, 0), Color.White, Color.Black); moel@40: moel@40: BitmapData data = bitmap.LockBits( moel@40: new Rectangle(0, 0, bitmap.Width, bitmap.Height), moel@40: ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb); moel@40: moel@40: int stride = data.Stride; moel@40: IntPtr Scan0 = data.Scan0; moel@40: moel@40: int numBytes = bitmap.Width * bitmap.Height * 4; moel@40: byte[] bytes = new byte[numBytes]; moel@40: Marshal.Copy(Scan0, bytes, 0, numBytes); moel@40: bitmap.UnlockBits(data); moel@40: moel@40: byte red, green, blue; moel@40: for (int i = 0; i < bytes.Length; i += 4) { moel@40: blue = bytes[i]; moel@40: green = bytes[i + 1]; moel@40: red = bytes[i + 2]; moel@40: moel@40: bytes[i] = 255; moel@40: bytes[i + 1] = 255; moel@40: bytes[i + 2] = 255; moel@40: bytes[i + 3] = (byte)(0.3 * red + 0.59 * green + 0.11 * blue); moel@40: } moel@40: moel@40: return IconFactory.Create(bytes, 16, 16, PixelFormat.Format32bppArgb); moel@40: } moel@40: moel@40: public void Update() { moel@40: Icon icon = notifyIcon.Icon; moel@40: moel@40: if (majorVersion < 6) { moel@40: notifyIcon.Icon = CreateSimpleIcon(); moel@40: } else { moel@40: notifyIcon.Icon = CreateTransparentIcon(); moel@40: } moel@40: moel@40: if (icon != null) moel@40: icon.Dispose(); moel@40: moel@40: string format = ""; moel@40: switch (sensor.SensorType) { moel@40: case SensorType.Voltage: format = "{0}\n{1}: {2:F2} V"; break; moel@40: case SensorType.Clock: format = "{0}\n{1}: {2:F0} MHz"; break; moel@40: case SensorType.Load: format = "{0}\n{1}: {2:F1} %"; break; moel@40: case SensorType.Temperature: format = "{0}\n{1}: {2:F1} °C"; break; moel@40: case SensorType.Fan: format = "{0}\n{1}: {2:F0} RPM"; break; moel@40: } moel@40: moel@40: notifyIcon.Text = string.Format(format, moel@40: sensor.Hardware.Name, sensor.Name, sensor.Value); moel@40: notifyIcon.Visible = true; moel@40: } moel@40: } moel@40: }