Fixed Issue 123.
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.
39 using System.Collections.Generic;
40 using System.ComponentModel;
41 using System.Configuration;
45 using System.Windows.Forms;
46 using Aga.Controls.Tree;
47 using Aga.Controls.Tree.NodeControls;
48 using OpenHardwareMonitor.Hardware;
49 using OpenHardwareMonitor.Utilities;
51 namespace OpenHardwareMonitor.GUI {
52 public partial class MainForm : Form {
54 private PersistentSettings settings;
55 private UnitManager unitManager;
56 private Computer computer;
58 private TreeModel treeModel;
59 private IDictionary<ISensor, Color> sensorPlotColors =
60 new Dictionary<ISensor, Color>();
61 private Color[] plotColorPalette;
62 private SystemTray systemTray;
63 private StartupManager startupManager = new StartupManager();
64 private UpdateVisitor updateVisitor = new UpdateVisitor();
65 private SensorGadget gadget;
67 private UserOption showHiddenSensors;
68 private UserOption showPlot;
69 private UserOption showValue;
70 private UserOption showMin;
71 private UserOption showMax;
72 private UserOption startMinimized;
73 private UserOption minimizeToTray;
74 private UserOption minimizeOnClose;
75 private UserOption autoStart;
76 private UserOption readHddSensors;
77 private UserOption showGadget;
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 Rectangle newBounds = new Rectangle {
104 X = settings.GetValue("mainForm.Location.X", Location.X),
105 Y = settings.GetValue("mainForm.Location.Y", Location.Y),
106 Width = settings.GetValue("mainForm.Width", 470),
107 Height = settings.GetValue("mainForm.Height", 640)
110 Screen[] screens = Screen.AllScreens;
111 Rectangle totalWorkingArea = new Rectangle(int.MaxValue, int.MaxValue,
112 int.MinValue, int.MinValue);
114 foreach(Screen screen in screens)
115 totalWorkingArea = Rectangle.Union(totalWorkingArea, screen.Bounds);
117 this.Bounds = newBounds;
119 if (!totalWorkingArea.Contains(newBounds) ||
120 !settings.Contains("mainForm.Location.X"))
121 this.StartPosition = FormStartPosition.CenterScreen;
123 foreach (TreeColumn column in treeView.Columns)
124 column.Width = Math.Max(20, Math.Min(400,
125 settings.GetValue("treeView.Columns." + column.Header + ".Width",
128 treeModel = new TreeModel();
129 root = new Node(System.Environment.MachineName);
130 root.Image = Utilities.EmbeddedResources.GetImage("computer.png");
132 treeModel.Nodes.Add(root);
133 treeView.Model = treeModel;
135 this.computer = new Computer(settings);
137 systemTray = new SystemTray(computer, settings);
138 systemTray.HideShowCommand += hideShowClick;
139 systemTray.ExitCommand += exitClick;
141 int p = (int)Environment.OSVersion.Platform;
142 if ((p == 4) || (p == 128)) { // Unix
143 splitContainer.BorderStyle = BorderStyle.None;
144 splitContainer.Border3DStyle = Border3DStyle.Adjust;
145 splitContainer.SplitterWidth = 4;
146 treeView.BorderStyle = BorderStyle.Fixed3D;
147 plotPanel.BorderStyle = BorderStyle.Fixed3D;
148 gadgetMenuItem.Visible = false;
149 minCloseMenuItem.Visible = false;
151 gadget = new SensorGadget(computer, settings, unitManager);
154 computer.HardwareAdded += new HardwareEventHandler(HardwareAdded);
155 computer.HardwareRemoved += new HardwareEventHandler(HardwareRemoved);
158 timer.Enabled = true;
160 plotColorPalette = new Color[13];
161 plotColorPalette[0] = Color.Blue;
162 plotColorPalette[1] = Color.OrangeRed;
163 plotColorPalette[2] = Color.Green;
164 plotColorPalette[3] = Color.LightSeaGreen;
165 plotColorPalette[4] = Color.Goldenrod;
166 plotColorPalette[5] = Color.DarkViolet;
167 plotColorPalette[6] = Color.YellowGreen;
168 plotColorPalette[7] = Color.SaddleBrown;
169 plotColorPalette[8] = Color.RoyalBlue;
170 plotColorPalette[9] = Color.DeepPink;
171 plotColorPalette[10] = Color.MediumSeaGreen;
172 plotColorPalette[11] = Color.Olive;
173 plotColorPalette[12] = Color.Firebrick;
175 showHiddenSensors = new UserOption("hiddenMenuItem", false, hiddenMenuItem, settings);
176 showHiddenSensors.Changed += delegate(object sender, EventArgs e) {
177 treeModel.ForceVisible = showHiddenSensors.Value;
180 showPlot = new UserOption("plotMenuItem", false, plotMenuItem, settings);
181 showPlot.Changed += delegate(object sender, EventArgs e) {
182 splitContainer.Panel2Collapsed = !showPlot.Value;
183 treeView.Invalidate();
186 showValue = new UserOption("valueMenuItem", true, valueMenuItem, settings);
187 showValue.Changed += delegate(object sender, EventArgs e) {
188 treeView.Columns[1].IsVisible = showValue.Value;
191 showMin = new UserOption("minMenuItem", false, minMenuItem, settings);
192 showMin.Changed += delegate(object sender, EventArgs e) {
193 treeView.Columns[2].IsVisible = showMin.Value;
196 showMax = new UserOption("maxMenuItem", true, maxMenuItem, settings);
197 showMax.Changed += delegate(object sender, EventArgs e) {
198 treeView.Columns[3].IsVisible = showMax.Value;
201 startMinimized = new UserOption("startMinMenuItem", false, startMinMenuItem, settings);
203 minimizeToTray = new UserOption("minTrayMenuItem", true, minTrayMenuItem, settings);
204 minimizeToTray.Changed += delegate(object sender, EventArgs e) {
205 systemTray.IsMainIconEnabled = minimizeToTray.Value;
208 minimizeOnClose = new UserOption("minCloseMenuItem", false, minCloseMenuItem, settings);
210 autoStart = new UserOption(null, startupManager.Startup, startupMenuItem, settings);
211 autoStart.Changed += delegate(object sender, EventArgs e) {
213 startupManager.Startup = autoStart.Value;
214 } catch (InvalidOperationException) {
215 MessageBox.Show("Updating the auto-startup option failed.", "Error",
216 MessageBoxButtons.OK, MessageBoxIcon.Error);
217 autoStart.Value = startupManager.Startup;
221 readHddSensors = new UserOption("hddMenuItem", true, hddMenuItem, settings);
222 readHddSensors.Changed += delegate(object sender, EventArgs e) {
223 computer.HDDEnabled = readHddSensors.Value;
224 UpdatePlotSelection(null, null);
227 showGadget = new UserOption("gadgetMenuItem", false, gadgetMenuItem, settings);
228 showGadget.Changed += delegate(object sender, EventArgs e) {
230 gadget.Visible = showGadget.Value;
233 celciusMenuItem.Checked =
234 unitManager.TemperatureUnit == TemperatureUnit.Celcius;
235 fahrenheitMenuItem.Checked = !celciusMenuItem.Checked;
237 startupMenuItem.Visible = startupManager.IsAvailable;
239 if (startMinMenuItem.Checked) {
240 if (!minTrayMenuItem.Checked) {
241 WindowState = FormWindowState.Minimized;
248 // Create a handle, otherwise calling Close() does not fire FormClosed
249 IntPtr handle = Handle;
251 // Make sure the settings are saved when the user logs off
252 Microsoft.Win32.SystemEvents.SessionEnded +=
253 delegate(object sender, Microsoft.Win32.SessionEndedEventArgs e) {
258 private void SubHardwareAdded(IHardware hardware, Node node) {
259 Node hardwareNode = new HardwareNode(hardware, settings, unitManager);
260 node.Nodes.Add(hardwareNode);
261 foreach (IHardware subHardware in hardware.SubHardware)
262 SubHardwareAdded(subHardware, hardwareNode);
265 private void HardwareAdded(IHardware hardware) {
266 Node hardwareNode = new HardwareNode(hardware, settings, unitManager);
267 root.Nodes.Add(hardwareNode);
268 foreach (IHardware subHardware in hardware.SubHardware)
269 SubHardwareAdded(subHardware, hardwareNode);
272 private void HardwareRemoved(IHardware hardware) {
273 List<Node> nodesToRemove = new List<Node>();
274 foreach (Node node in root.Nodes) {
275 HardwareNode hardwareNode = node as HardwareNode;
276 if (hardwareNode != null && hardwareNode.Hardware == hardware)
277 nodesToRemove.Add(node);
279 foreach (Node node in nodesToRemove)
280 root.Nodes.Remove(node);
283 private void nodeTextBoxText_DrawText(object sender, DrawEventArgs e) {
284 Node node = e.Node.Tag as Node;
287 if (node.IsVisible) {
288 SensorNode sensorNode = node as SensorNode;
289 if (plotMenuItem.Checked && sensorNode != null &&
290 sensorPlotColors.TryGetValue(sensorNode.Sensor, out color))
293 e.TextColor = Color.DarkGray;
298 private void UpdatePlotSelection(object sender,
301 List<ISensor> selected = new List<ISensor>();
302 IDictionary<ISensor, Color> colors = new Dictionary<ISensor, Color>();
304 foreach (TreeNodeAdv node in treeView.AllNodes) {
305 SensorNode sensorNode = node.Tag as SensorNode;
306 if (sensorNode != null &&
307 sensorNode.Sensor.SensorType == SensorType.Temperature) {
308 if (sensorNode.Plot) {
309 colors.Add(sensorNode.Sensor,
310 plotColorPalette[colorIndex % plotColorPalette.Length]);
311 selected.Add(sensorNode.Sensor);
316 sensorPlotColors = colors;
317 plotPanel.SetSensors(selected, colors);
320 private void nodeTextBoxText_EditorShowing(object sender, CancelEventArgs e)
322 e.Cancel = !(treeView.CurrentNode != null &&
323 treeView.CurrentNode.Tag is SensorNode);
326 private void nodeCheckBox_IsVisibleValueNeeded(object sender,
327 NodeControlValueEventArgs e) {
328 SensorNode node = e.Node.Tag as SensorNode;
329 e.Value = (node != null) &&
330 (node.Sensor.SensorType == SensorType.Temperature) &&
331 plotMenuItem.Checked;
334 private void exitClick(object sender, EventArgs e) {
338 private void timer_Tick(object sender, EventArgs e) {
339 computer.Accept(updateVisitor);
340 treeView.Invalidate();
341 plotPanel.Invalidate();
347 private void SaveConfiguration() {
348 if (WindowState != FormWindowState.Minimized) {
349 settings.SetValue("mainForm.Location.X", Location.X);
350 settings.SetValue("mainForm.Location.Y", Location.Y);
351 settings.SetValue("mainForm.Width", ClientSize.Width);
352 settings.SetValue("mainForm.Height", ClientSize.Height);
355 foreach (TreeColumn column in treeView.Columns)
356 settings.SetValue("treeView.Columns." + column.Header + ".Width",
359 string fileName = Path.ChangeExtension(
360 System.Windows.Forms.Application.ExecutablePath, ".config");
362 settings.Save(fileName);
363 } catch (UnauthorizedAccessException) {
364 MessageBox.Show("Access to the path '" + fileName + "' is denied. " +
365 "The current seetings could not be saved.",
366 "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
370 private void MainForm_FormClosed(object sender, FormClosedEventArgs e) {
374 timer.Enabled = false;
375 systemTray.Dispose();
379 private void aboutMenuItem_Click(object sender, EventArgs e) {
380 new AboutBox().ShowDialog();
383 private void treeView_Click(object sender, EventArgs e) {
385 MouseEventArgs m = e as MouseEventArgs;
386 if (m == null || m.Button != MouseButtons.Right)
389 NodeControlInfo info = treeView.GetNodeControlInfoAt(new Point(m.X, m.Y));
390 treeView.SelectedNode = info.Node;
391 if (info.Node != null) {
392 SensorNode node = info.Node.Tag as SensorNode;
393 if (node != null && node.Sensor != null) {
394 sensorContextMenu.MenuItems.Clear();
395 if (node.Sensor.Parameters.Length > 0) {
396 MenuItem item = new MenuItem("Parameters...");
397 item.Click += delegate(object obj, EventArgs args) {
398 ShowParameterForm(node.Sensor);
400 sensorContextMenu.MenuItems.Add(item);
402 if (nodeTextBoxText.EditEnabled) {
403 MenuItem item = new MenuItem("Rename");
404 item.Click += delegate(object obj, EventArgs args) {
405 nodeTextBoxText.BeginEdit();
407 sensorContextMenu.MenuItems.Add(item);
409 if (node.IsVisible) {
410 MenuItem item = new MenuItem("Hide");
411 item.Click += delegate(object obj, EventArgs args) {
412 node.IsVisible = false;
414 sensorContextMenu.MenuItems.Add(item);
416 MenuItem item = new MenuItem("Unhide");
417 item.Click += delegate(object obj, EventArgs args) {
418 node.IsVisible = true;
420 sensorContextMenu.MenuItems.Add(item);
422 sensorContextMenu.MenuItems.Add(new MenuItem("-"));
424 MenuItem item = new MenuItem("Show in Tray");
425 item.Checked = systemTray.Contains(node.Sensor);
426 item.Click += delegate(object obj, EventArgs args) {
428 systemTray.Remove(node.Sensor);
430 systemTray.Add(node.Sensor, true);
432 sensorContextMenu.MenuItems.Add(item);
434 if (gadget != null) {
435 MenuItem item = new MenuItem("Show in Gadget");
436 item.Checked = gadget.Contains(node.Sensor);
437 item.Click += delegate(object obj, EventArgs args) {
439 gadget.Remove(node.Sensor);
441 gadget.Add(node.Sensor);
444 sensorContextMenu.MenuItems.Add(item);
447 sensorContextMenu.Show(treeView, new Point(m.X, m.Y));
452 private void saveReportMenuItem_Click(object sender, EventArgs e) {
453 string report = computer.GetReport();
454 if (saveFileDialog.ShowDialog() == DialogResult.OK) {
455 using (TextWriter w = new StreamWriter(saveFileDialog.FileName)) {
461 private void SysTrayHideShow() {
467 protected override void WndProc(ref Message m) {
468 const int WM_SYSCOMMAND = 0x112;
469 const int SC_MINIMIZE = 0xF020;
470 const int SC_CLOSE = 0xF060;
472 if (minimizeToTray.Value &&
473 m.Msg == WM_SYSCOMMAND && m.WParam.ToInt32() == SC_MINIMIZE) {
475 } else if(minimizeOnClose.Value &&
476 m.Msg == WM_SYSCOMMAND && m.WParam.ToInt32() == SC_CLOSE) {
478 * Apparently the user wants to minimize rather than close
479 * Now we still need to check if we're going to the tray or not
481 * Note: the correct way to do this would be to send out SC_MINIMIZE,
482 * but since the code here is so simple,
483 * that would just be a waste of time.
485 if (minimizeToTray.Value)
488 WindowState = FormWindowState.Minimized;
494 private void hideShowClick(object sender, EventArgs e) {
498 private void ShowParameterForm(ISensor sensor) {
499 ParameterForm form = new ParameterForm();
500 form.Parameters = sensor.Parameters;
501 form.captionLabel.Text = sensor.Name;
505 private void treeView_NodeMouseDoubleClick(object sender,
506 TreeNodeAdvMouseEventArgs e) {
507 SensorNode node = e.Node.Tag as SensorNode;
508 if (node != null && node.Sensor != null &&
509 node.Sensor.Parameters.Length > 0) {
510 ShowParameterForm(node.Sensor);
514 private void celciusMenuItem_Click(object sender, EventArgs e) {
515 celciusMenuItem.Checked = true;
516 fahrenheitMenuItem.Checked = false;
517 unitManager.TemperatureUnit = TemperatureUnit.Celcius;
520 private void fahrenheitMenuItem_Click(object sender, EventArgs e) {
521 celciusMenuItem.Checked = false;
522 fahrenheitMenuItem.Checked = true;
523 unitManager.TemperatureUnit = TemperatureUnit.Fahrenheit;
526 private void sumbitReportMenuItem_Click(object sender, EventArgs e)
528 ReportForm form = new ReportForm();
529 form.Report = computer.GetReport();
533 private void resetMinMaxMenuItem_Click(object sender, EventArgs e) {
534 computer.Accept(new SensorVisitor(delegate(ISensor sensor) {