Fixed an UnauthorizedAccessException when modifying the auto-startup registry entry.
3 Version: MPL 1.1/GPL 2.0/LGPL 2.1
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
9 http://www.mozilla.org/MPL/
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.
15 The Original Code is the Open Hardware Monitor code.
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.
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.
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;
48 namespace OpenHardwareMonitor.GUI {
49 public class SensorNotifyIcon : IDisposable {
51 private ISensor sensor;
52 private NotifyIcon notifyIcon;
53 private Bitmap bitmap;
54 private Graphics graphics;
56 private Color darkColor;
58 private Brush darkBrush;
62 public SensorNotifyIcon(SystemTray sensorSystemTray, ISensor sensor,
63 bool balloonTip, PersistentSettings settings)
66 this.notifyIcon = new NotifyIcon();
68 Color defaultColor = Color.Black;
69 if (sensor.SensorType == SensorType.Load) {
70 defaultColor = Color.FromArgb(0xff, 0x70, 0x8c, 0xf1);
72 Color = settings.GetValue(new Identifier(sensor.Identifier,
73 "traycolor").ToString(), defaultColor);
75 this.pen = new Pen(Color.FromArgb(96, Color.Black));
76 this.font = SystemFonts.MessageBoxFont;
78 ContextMenu contextMenu = new ContextMenu();
79 MenuItem hideShowItem = new MenuItem("Hide/Show");
80 hideShowItem.Click += delegate(object obj, EventArgs args) {
81 sensorSystemTray.SendHideShowCommand();
83 contextMenu.MenuItems.Add(hideShowItem);
84 contextMenu.MenuItems.Add(new MenuItem("-"));
85 MenuItem removeItem = new MenuItem("Remove Sensor");
86 removeItem.Click += delegate(object obj, EventArgs args) {
87 sensorSystemTray.Remove(this.sensor);
89 contextMenu.MenuItems.Add(removeItem);
90 MenuItem colorItem = new MenuItem("Change Color...");
91 colorItem.Click += delegate(object obj, EventArgs args) {
92 ColorDialog dialog = new ColorDialog();
94 if (dialog.ShowDialog() == DialogResult.OK) {
96 settings.SetValue(new Identifier(sensor.Identifier,
97 "traycolor").ToString(), Color);
100 contextMenu.MenuItems.Add(colorItem);
101 contextMenu.MenuItems.Add(new MenuItem("-"));
102 MenuItem exitItem = new MenuItem("Exit");
103 exitItem.Click += delegate(object obj, EventArgs args) {
104 sensorSystemTray.SendExitCommand();
106 contextMenu.MenuItems.Add(exitItem);
107 this.notifyIcon.ContextMenu = contextMenu;
108 this.notifyIcon.DoubleClick += delegate(object obj, EventArgs args) {
109 sensorSystemTray.SendHideShowCommand();
112 this.bitmap = new Bitmap(16, 16, PixelFormat.Format32bppArgb);
113 this.graphics = Graphics.FromImage(this.bitmap);
115 if (Environment.OSVersion.Version.Major > 5) {
116 this.graphics.TextRenderingHint = TextRenderingHint.ClearTypeGridFit;
117 this.graphics.SmoothingMode = SmoothingMode.HighQuality;
121 public ISensor Sensor {
122 get { return sensor; }
126 get { return color; }
129 this.darkColor = Color.FromArgb(255,
133 Brush brush = this.brush;
134 this.brush = new SolidBrush(this.color);
137 Brush darkBrush = this.darkBrush;
138 this.darkBrush = new SolidBrush(this.darkColor);
139 if (darkBrush != null)
144 public void Dispose() {
145 Icon icon = notifyIcon.Icon;
146 notifyIcon.Icon = null;
149 notifyIcon.Dispose();
153 if (darkBrush != null)
160 private string GetString() {
161 switch (sensor.SensorType) {
162 case SensorType.Voltage:
163 return string.Format("{0:F11}", sensor.Value);
164 case SensorType.Clock:
165 return string.Format("{0:F11}", 1e-3f * sensor.Value);
166 case SensorType.Load:
167 return string.Format("{0:F0}", sensor.Value);
168 case SensorType.Temperature:
169 return string.Format("{0:F0}", sensor.Value);
171 return string.Format("{0:F11}", 1e-3f * sensor.Value);
172 case SensorType.Flow:
173 return string.Format("{0:F11}", 1e-3f * sensor.Value);
174 case SensorType.Control:
175 return string.Format("{0:F0}", sensor.Value);
180 private Icon CreateTransparentIcon() {
182 graphics.Clear(Color.Black);
183 TextRenderer.DrawText(graphics, GetString(), font,
184 new Point(-2, 0), Color.White, Color.Black);
186 BitmapData data = bitmap.LockBits(
187 new Rectangle(0, 0, bitmap.Width, bitmap.Height),
188 ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);
190 int stride = data.Stride;
191 IntPtr Scan0 = data.Scan0;
193 int numBytes = bitmap.Width * bitmap.Height * 4;
194 byte[] bytes = new byte[numBytes];
195 Marshal.Copy(Scan0, bytes, 0, numBytes);
196 bitmap.UnlockBits(data);
198 byte red, green, blue;
199 for (int i = 0; i < bytes.Length; i += 4) {
201 green = bytes[i + 1];
205 bytes[i + 1] = color.G;
206 bytes[i + 2] = color.R;
207 bytes[i + 3] = (byte)(0.3 * red + 0.59 * green + 0.11 * blue);
210 return IconFactory.Create(bytes, 16, 16, PixelFormat.Format32bppArgb);
213 private Icon CreateLoadIcon() {
215 graphics.Clear(Color.Transparent);
216 } catch (ArgumentException) {
217 graphics.Clear(Color.Black);
219 graphics.FillRectangle(darkBrush, 0.5f, -0.5f, 14, 16);
220 float y = 0.16f * (100 - sensor.Value.Value);
221 graphics.FillRectangle(brush, 0.5f, -0.5f + y, 14, 16 - y);
222 graphics.DrawRectangle(pen, 1, 0, 13, 15);
224 BitmapData data = bitmap.LockBits(
225 new Rectangle(0, 0, bitmap.Width, bitmap.Height),
226 ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);
227 byte[] bytes = new byte[bitmap.Width * bitmap.Height * 4];
228 Marshal.Copy(data.Scan0, bytes, 0, bytes.Length);
229 bitmap.UnlockBits(data);
231 return IconFactory.Create(bytes, 16, 16, PixelFormat.Format32bppArgb);
234 public void Update() {
235 Icon icon = notifyIcon.Icon;
237 if (sensor.SensorType == SensorType.Load) {
238 notifyIcon.Icon = CreateLoadIcon();
240 notifyIcon.Icon = CreateTransparentIcon();
246 switch (sensor.SensorType) {
247 case SensorType.Voltage: format = "\n{0}: {1:F2} V"; break;
248 case SensorType.Clock: format = "\n{0}: {1:F0} MHz"; break;
249 case SensorType.Load: format = "\n{0}: {1:F1} %"; break;
250 case SensorType.Temperature: format = "\n{0}: {1:F1} °C"; break;
251 case SensorType.Fan: format = "\n{0}: {1:F0} RPM"; break;
252 case SensorType.Flow: format = "\n{0}: {1:F0} L/h"; break;
253 case SensorType.Control: format = "\n{0}: {1:F1} %"; break;
255 string formattedValue = string.Format(format, sensor.Name, sensor.Value);
256 string hardwareName = sensor.Hardware.Name;
257 hardwareName = hardwareName.Substring(0,
258 Math.Min(63 - formattedValue.Length, hardwareName.Length));
259 string text = hardwareName + formattedValue;
260 if (text.Length > 63)
263 notifyIcon.Text = text;
264 notifyIcon.Visible = true;