Replaced the StreamReader based lm-sensors access with an implementation using the FileStream class in order to avoid buffering problems when seeking.
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.
22 Contributor(s): Paul Werelds
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.
39 using System.Collections.Generic;
40 using System.ComponentModel;
43 using System.Windows.Forms;
44 using Aga.Controls.Tree;
45 using Aga.Controls.Tree.NodeControls;
46 using OpenHardwareMonitor.Hardware;
47 using OpenHardwareMonitor.WMI;
49 namespace OpenHardwareMonitor.GUI {
50 public partial class MainForm : Form {
52 private PersistentSettings settings;
53 private UnitManager unitManager;
54 private Computer computer;
56 private TreeModel treeModel;
57 private IDictionary<ISensor, Color> sensorPlotColors =
58 new Dictionary<ISensor, Color>();
59 private Color[] plotColorPalette;
60 private SystemTray systemTray;
61 private StartupManager startupManager = new StartupManager();
62 private UpdateVisitor updateVisitor = new UpdateVisitor();
63 private SensorGadget gadget;
65 private UserOption showHiddenSensors;
66 private UserOption showPlot;
67 private UserOption showValue;
68 private UserOption showMin;
69 private UserOption showMax;
70 private UserOption startMinimized;
71 private UserOption minimizeToTray;
72 private UserOption minimizeOnClose;
73 private UserOption autoStart;
74 private UserOption readHddSensors;
75 private UserOption showGadget;
77 private WmiProvider wmiProvider;
80 InitializeComponent();
82 this.settings = new PersistentSettings();
83 this.settings.Load(Path.ChangeExtension(
84 Application.ExecutablePath, ".config"));
86 this.unitManager = new UnitManager(settings);
88 // set the DockStyle here, to avoid conflicts with the MainMenu
89 this.splitContainer.Dock = DockStyle.Fill;
91 this.Font = SystemFonts.MessageBoxFont;
92 treeView.Font = SystemFonts.MessageBoxFont;
93 plotPanel.Font = SystemFonts.MessageBoxFont;
95 nodeCheckBox.IsVisibleValueNeeded += nodeCheckBox_IsVisibleValueNeeded;
96 nodeCheckBox.CheckStateChanged += UpdatePlotSelection;
97 nodeTextBoxText.DrawText += nodeTextBoxText_DrawText;
98 nodeTextBoxValue.DrawText += nodeTextBoxText_DrawText;
99 nodeTextBoxMin.DrawText += nodeTextBoxText_DrawText;
100 nodeTextBoxMax.DrawText += nodeTextBoxText_DrawText;
101 nodeTextBoxText.EditorShowing += nodeTextBoxText_EditorShowing;
103 foreach (TreeColumn column in treeView.Columns)
104 column.Width = Math.Max(20, Math.Min(400,
105 settings.GetValue("treeView.Columns." + column.Header + ".Width",
108 treeModel = new TreeModel();
109 root = new Node(System.Environment.MachineName);
110 root.Image = Utilities.EmbeddedResources.GetImage("computer.png");
112 treeModel.Nodes.Add(root);
113 treeView.Model = treeModel;
115 this.computer = new Computer(settings);
117 systemTray = new SystemTray(computer, settings);
118 systemTray.HideShowCommand += hideShowClick;
119 systemTray.ExitCommand += exitClick;
121 int p = (int)Environment.OSVersion.Platform;
122 if ((p == 4) || (p == 128)) { // Unix
123 treeView.RowHeight = Math.Max(treeView.RowHeight, 17);
124 splitContainer.BorderStyle = BorderStyle.None;
125 splitContainer.Border3DStyle = Border3DStyle.Adjust;
126 splitContainer.SplitterWidth = 4;
127 treeView.BorderStyle = BorderStyle.Fixed3D;
128 plotPanel.BorderStyle = BorderStyle.Fixed3D;
129 gadgetMenuItem.Visible = false;
130 minCloseMenuItem.Visible = false;
132 treeView.RowHeight = Math.Max(treeView.Font.Height + 1, 17);
134 gadget = new SensorGadget(computer, settings, unitManager);
135 gadget.HideShowCommand += hideShowClick;
137 wmiProvider = new WmiProvider(computer);
140 computer.HardwareAdded += new HardwareEventHandler(HardwareAdded);
141 computer.HardwareRemoved += new HardwareEventHandler(HardwareRemoved);
145 timer.Enabled = true;
147 plotColorPalette = new Color[13];
148 plotColorPalette[0] = Color.Blue;
149 plotColorPalette[1] = Color.OrangeRed;
150 plotColorPalette[2] = Color.Green;
151 plotColorPalette[3] = Color.LightSeaGreen;
152 plotColorPalette[4] = Color.Goldenrod;
153 plotColorPalette[5] = Color.DarkViolet;
154 plotColorPalette[6] = Color.YellowGreen;
155 plotColorPalette[7] = Color.SaddleBrown;
156 plotColorPalette[8] = Color.RoyalBlue;
157 plotColorPalette[9] = Color.DeepPink;
158 plotColorPalette[10] = Color.MediumSeaGreen;
159 plotColorPalette[11] = Color.Olive;
160 plotColorPalette[12] = Color.Firebrick;
162 showHiddenSensors = new UserOption("hiddenMenuItem", false,
163 hiddenMenuItem, settings);
164 showHiddenSensors.Changed += delegate(object sender, EventArgs e) {
165 treeModel.ForceVisible = showHiddenSensors.Value;
168 showPlot = new UserOption("plotMenuItem", false, plotMenuItem, settings);
169 showPlot.Changed += delegate(object sender, EventArgs e) {
170 splitContainer.Panel2Collapsed = !showPlot.Value;
171 treeView.Invalidate();
174 showValue = new UserOption("valueMenuItem", true, valueMenuItem,
176 showValue.Changed += delegate(object sender, EventArgs e) {
177 treeView.Columns[1].IsVisible = showValue.Value;
180 showMin = new UserOption("minMenuItem", false, minMenuItem, settings);
181 showMin.Changed += delegate(object sender, EventArgs e) {
182 treeView.Columns[2].IsVisible = showMin.Value;
185 showMax = new UserOption("maxMenuItem", true, maxMenuItem, settings);
186 showMax.Changed += delegate(object sender, EventArgs e) {
187 treeView.Columns[3].IsVisible = showMax.Value;
190 startMinimized = new UserOption("startMinMenuItem", false,
191 startMinMenuItem, settings);
193 minimizeToTray = new UserOption("minTrayMenuItem", true,
194 minTrayMenuItem, settings);
195 minimizeToTray.Changed += delegate(object sender, EventArgs e) {
196 systemTray.IsMainIconEnabled = minimizeToTray.Value;
199 minimizeOnClose = new UserOption("minCloseMenuItem", false,
200 minCloseMenuItem, settings);
202 autoStart = new UserOption(null, startupManager.Startup,
203 startupMenuItem, settings);
204 autoStart.Changed += delegate(object sender, EventArgs e) {
206 startupManager.Startup = autoStart.Value;
207 } catch (InvalidOperationException) {
208 MessageBox.Show("Updating the auto-startup option failed.", "Error",
209 MessageBoxButtons.OK, MessageBoxIcon.Error);
210 autoStart.Value = startupManager.Startup;
214 readHddSensors = new UserOption("hddMenuItem", true, hddMenuItem,
216 readHddSensors.Changed += delegate(object sender, EventArgs e) {
217 computer.HDDEnabled = readHddSensors.Value;
218 UpdatePlotSelection(null, null);
221 showGadget = new UserOption("gadgetMenuItem", false, gadgetMenuItem,
223 showGadget.Changed += delegate(object sender, EventArgs e) {
225 gadget.Visible = showGadget.Value;
228 celciusMenuItem.Checked =
229 unitManager.TemperatureUnit == TemperatureUnit.Celcius;
230 fahrenheitMenuItem.Checked = !celciusMenuItem.Checked;
232 startupMenuItem.Visible = startupManager.IsAvailable;
234 if (startMinMenuItem.Checked) {
235 if (!minTrayMenuItem.Checked) {
236 WindowState = FormWindowState.Minimized;
243 // Create a handle, otherwise calling Close() does not fire FormClosed
244 IntPtr handle = Handle;
246 // Make sure the settings are saved when the user logs off
247 Microsoft.Win32.SystemEvents.SessionEnded += delegate {
252 private void SubHardwareAdded(IHardware hardware, Node node) {
253 Node hardwareNode = new HardwareNode(hardware, settings, unitManager);
254 node.Nodes.Add(hardwareNode);
255 foreach (IHardware subHardware in hardware.SubHardware)
256 SubHardwareAdded(subHardware, hardwareNode);
259 private void HardwareAdded(IHardware hardware) {
260 Node hardwareNode = new HardwareNode(hardware, settings, unitManager);
261 root.Nodes.Add(hardwareNode);
262 foreach (IHardware subHardware in hardware.SubHardware)
263 SubHardwareAdded(subHardware, hardwareNode);
266 private void HardwareRemoved(IHardware hardware) {
267 List<Node> nodesToRemove = new List<Node>();
268 foreach (Node node in root.Nodes) {
269 HardwareNode hardwareNode = node as HardwareNode;
270 if (hardwareNode != null && hardwareNode.Hardware == hardware)
271 nodesToRemove.Add(node);
273 foreach (Node node in nodesToRemove)
274 root.Nodes.Remove(node);
277 private void nodeTextBoxText_DrawText(object sender, DrawEventArgs e) {
278 Node node = e.Node.Tag as Node;
281 if (node.IsVisible) {
282 SensorNode sensorNode = node as SensorNode;
283 if (plotMenuItem.Checked && sensorNode != null &&
284 sensorPlotColors.TryGetValue(sensorNode.Sensor, out color))
287 e.TextColor = Color.DarkGray;
292 private void UpdatePlotSelection(object sender,
295 List<ISensor> selected = new List<ISensor>();
296 IDictionary<ISensor, Color> colors = new Dictionary<ISensor, Color>();
298 foreach (TreeNodeAdv node in treeView.AllNodes) {
299 SensorNode sensorNode = node.Tag as SensorNode;
300 if (sensorNode != null &&
301 sensorNode.Sensor.SensorType == SensorType.Temperature) {
302 if (sensorNode.Plot) {
303 colors.Add(sensorNode.Sensor,
304 plotColorPalette[colorIndex % plotColorPalette.Length]);
305 selected.Add(sensorNode.Sensor);
310 sensorPlotColors = colors;
311 plotPanel.SetSensors(selected, colors);
314 private void nodeTextBoxText_EditorShowing(object sender,
317 e.Cancel = !(treeView.CurrentNode != null &&
318 treeView.CurrentNode.Tag is SensorNode);
321 private void nodeCheckBox_IsVisibleValueNeeded(object sender,
322 NodeControlValueEventArgs e) {
323 SensorNode node = e.Node.Tag as SensorNode;
324 e.Value = (node != null) &&
325 (node.Sensor.SensorType == SensorType.Temperature) &&
326 plotMenuItem.Checked;
329 private void exitClick(object sender, EventArgs e) {
333 private void timer_Tick(object sender, EventArgs e) {
334 computer.Accept(updateVisitor);
335 treeView.Invalidate();
336 plotPanel.Invalidate();
341 if (wmiProvider != null)
342 wmiProvider.Update();
345 private void SaveConfiguration() {
346 foreach (TreeColumn column in treeView.Columns)
347 settings.SetValue("treeView.Columns." + column.Header + ".Width",
350 string fileName = Path.ChangeExtension(
351 System.Windows.Forms.Application.ExecutablePath, ".config");
353 settings.Save(fileName);
354 } catch (UnauthorizedAccessException) {
355 MessageBox.Show("Access to the path '" + fileName + "' is denied. " +
356 "The current seetings could not be saved.",
357 "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
361 private void MainForm_Load(object sender, EventArgs e) {
362 Rectangle newBounds = new Rectangle {
363 X = settings.GetValue("mainForm.Location.X", Location.X),
364 Y = settings.GetValue("mainForm.Location.Y", Location.Y),
365 Width = settings.GetValue("mainForm.Width", 470),
366 Height = settings.GetValue("mainForm.Height", 640)
369 Rectangle fullWorkingArea = new Rectangle(int.MaxValue, int.MaxValue,
370 int.MinValue, int.MinValue);
372 foreach (Screen screen in Screen.AllScreens)
373 fullWorkingArea = Rectangle.Union(fullWorkingArea, screen.Bounds);
375 Rectangle intersection = Rectangle.Intersect(fullWorkingArea, newBounds);
376 if (intersection.Width < 20 || intersection.Height < 20 ||
377 !settings.Contains("mainForm.Location.X")
379 newBounds.X = (Screen.PrimaryScreen.WorkingArea.Width / 2) -
382 newBounds.Y = (Screen.PrimaryScreen.WorkingArea.Height / 2) -
383 (newBounds.Height / 2);
386 this.Bounds = newBounds;
389 private void MainForm_FormClosed(object sender, FormClosedEventArgs e) {
393 systemTray.IsMainIconEnabled = false;
394 timer.Enabled = false;
396 systemTray.Dispose();
399 private void aboutMenuItem_Click(object sender, EventArgs e) {
400 new AboutBox().ShowDialog();
403 private void treeView_Click(object sender, EventArgs e) {
405 MouseEventArgs m = e as MouseEventArgs;
406 if (m == null || m.Button != MouseButtons.Right)
409 NodeControlInfo info = treeView.GetNodeControlInfoAt(
412 treeView.SelectedNode = info.Node;
413 if (info.Node != null) {
414 SensorNode node = info.Node.Tag as SensorNode;
415 if (node != null && node.Sensor != null) {
416 sensorContextMenu.MenuItems.Clear();
417 if (node.Sensor.Parameters.Length > 0) {
418 MenuItem item = new MenuItem("Parameters...");
419 item.Click += delegate(object obj, EventArgs args) {
420 ShowParameterForm(node.Sensor);
422 sensorContextMenu.MenuItems.Add(item);
424 if (nodeTextBoxText.EditEnabled) {
425 MenuItem item = new MenuItem("Rename");
426 item.Click += delegate(object obj, EventArgs args) {
427 nodeTextBoxText.BeginEdit();
429 sensorContextMenu.MenuItems.Add(item);
431 if (node.IsVisible) {
432 MenuItem item = new MenuItem("Hide");
433 item.Click += delegate(object obj, EventArgs args) {
434 node.IsVisible = false;
436 sensorContextMenu.MenuItems.Add(item);
438 MenuItem item = new MenuItem("Unhide");
439 item.Click += delegate(object obj, EventArgs args) {
440 node.IsVisible = true;
442 sensorContextMenu.MenuItems.Add(item);
444 sensorContextMenu.MenuItems.Add(new MenuItem("-"));
446 MenuItem item = new MenuItem("Show in Tray");
447 item.Checked = systemTray.Contains(node.Sensor);
448 item.Click += delegate(object obj, EventArgs args) {
450 systemTray.Remove(node.Sensor);
452 systemTray.Add(node.Sensor, true);
454 sensorContextMenu.MenuItems.Add(item);
456 if (gadget != null) {
457 MenuItem item = new MenuItem("Show in Gadget");
458 item.Checked = gadget.Contains(node.Sensor);
459 item.Click += delegate(object obj, EventArgs args) {
461 gadget.Remove(node.Sensor);
463 gadget.Add(node.Sensor);
466 sensorContextMenu.MenuItems.Add(item);
468 if (node.Sensor.Control != null) {
469 sensorContextMenu.MenuItems.Add(new MenuItem("-"));
470 IControl control = node.Sensor.Control;
471 MenuItem controlItem = new MenuItem("Control");
472 MenuItem defaultItem = new MenuItem("Default");
473 defaultItem.Checked = control.ControlMode == ControlMode.Default;
474 controlItem.MenuItems.Add(defaultItem);
475 defaultItem.Click += delegate(object obj, EventArgs args) {
476 control.SetDefault();
478 MenuItem manualItem = new MenuItem("Manual");
479 controlItem.MenuItems.Add(manualItem);
480 manualItem.Checked = control.ControlMode == ControlMode.Software;
481 for (int i = 0; i <= 100; i += 5) {
482 if (i <= control.MaxSoftwareValue &&
483 i >= control.MinSoftwareValue)
485 MenuItem item = new MenuItem(i + " %");
486 manualItem.MenuItems.Add(item);
487 item.Checked = control.ControlMode == ControlMode.Software &&
488 Math.Round(control.SoftwareValue) == i;
489 int softwareValue = i;
490 item.Click += delegate(object obj, EventArgs args) {
491 control.SetSoftware(softwareValue);
495 sensorContextMenu.MenuItems.Add(controlItem);
498 sensorContextMenu.Show(treeView, new Point(m.X, m.Y));
503 private void saveReportMenuItem_Click(object sender, EventArgs e) {
504 string report = computer.GetReport();
505 if (saveFileDialog.ShowDialog() == DialogResult.OK) {
506 using (TextWriter w = new StreamWriter(saveFileDialog.FileName)) {
512 private void SysTrayHideShow() {
518 protected override void WndProc(ref Message m) {
519 const int WM_SYSCOMMAND = 0x112;
520 const int SC_MINIMIZE = 0xF020;
521 const int SC_CLOSE = 0xF060;
523 if (minimizeToTray.Value &&
524 m.Msg == WM_SYSCOMMAND && m.WParam.ToInt32() == SC_MINIMIZE) {
526 } else if(minimizeOnClose.Value &&
527 m.Msg == WM_SYSCOMMAND && m.WParam.ToInt32() == SC_CLOSE) {
529 * Apparently the user wants to minimize rather than close
530 * Now we still need to check if we're going to the tray or not
532 * Note: the correct way to do this would be to send out SC_MINIMIZE,
533 * but since the code here is so simple,
534 * that would just be a waste of time.
536 if (minimizeToTray.Value)
539 WindowState = FormWindowState.Minimized;
545 private void hideShowClick(object sender, EventArgs e) {
549 private void ShowParameterForm(ISensor sensor) {
550 ParameterForm form = new ParameterForm();
551 form.Parameters = sensor.Parameters;
552 form.captionLabel.Text = sensor.Name;
556 private void treeView_NodeMouseDoubleClick(object sender,
557 TreeNodeAdvMouseEventArgs e) {
558 SensorNode node = e.Node.Tag as SensorNode;
559 if (node != null && node.Sensor != null &&
560 node.Sensor.Parameters.Length > 0) {
561 ShowParameterForm(node.Sensor);
565 private void celciusMenuItem_Click(object sender, EventArgs e) {
566 celciusMenuItem.Checked = true;
567 fahrenheitMenuItem.Checked = false;
568 unitManager.TemperatureUnit = TemperatureUnit.Celcius;
571 private void fahrenheitMenuItem_Click(object sender, EventArgs e) {
572 celciusMenuItem.Checked = false;
573 fahrenheitMenuItem.Checked = true;
574 unitManager.TemperatureUnit = TemperatureUnit.Fahrenheit;
577 private void sumbitReportMenuItem_Click(object sender, EventArgs e)
579 ReportForm form = new ReportForm();
580 form.Report = computer.GetReport();
584 private void resetMinMaxMenuItem_Click(object sender, EventArgs e) {
585 computer.Accept(new SensorVisitor(delegate(ISensor sensor) {
591 private void MainForm_MoveOrResize(object sender, EventArgs e) {
592 if (WindowState != FormWindowState.Minimized) {
593 settings.SetValue("mainForm.Location.X", Bounds.X);
594 settings.SetValue("mainForm.Location.Y", Bounds.Y);
595 settings.SetValue("mainForm.Width", Bounds.Width);
596 settings.SetValue("mainForm.Height", Bounds.Height);
600 private void resetClick(object sender, EventArgs e) {
601 // disable the fallback MainIcon during reset, otherwise icon visibility
603 systemTray.IsMainIconEnabled = false;
606 // restore the MainIcon setting
607 systemTray.IsMainIconEnabled = minimizeToTray.Value;