Fixed Issue 179.
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;
94 treeView.RowHeight = treeView.Font.Height + 1;
96 nodeCheckBox.IsVisibleValueNeeded += nodeCheckBox_IsVisibleValueNeeded;
97 nodeCheckBox.CheckStateChanged += UpdatePlotSelection;
98 nodeTextBoxText.DrawText += nodeTextBoxText_DrawText;
99 nodeTextBoxValue.DrawText += nodeTextBoxText_DrawText;
100 nodeTextBoxMin.DrawText += nodeTextBoxText_DrawText;
101 nodeTextBoxMax.DrawText += nodeTextBoxText_DrawText;
102 nodeTextBoxText.EditorShowing += nodeTextBoxText_EditorShowing;
104 foreach (TreeColumn column in treeView.Columns)
105 column.Width = Math.Max(20, Math.Min(400,
106 settings.GetValue("treeView.Columns." + column.Header + ".Width",
109 treeModel = new TreeModel();
110 root = new Node(System.Environment.MachineName);
111 root.Image = Utilities.EmbeddedResources.GetImage("computer.png");
113 treeModel.Nodes.Add(root);
114 treeView.Model = treeModel;
116 this.computer = new Computer(settings);
118 systemTray = new SystemTray(computer, settings);
119 systemTray.HideShowCommand += hideShowClick;
120 systemTray.ExitCommand += exitClick;
122 int p = (int)Environment.OSVersion.Platform;
123 if ((p == 4) || (p == 128)) { // Unix
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 gadget = new SensorGadget(computer, settings, unitManager);
133 gadget.HideShowCommand += hideShowClick;
135 wmiProvider = new WmiProvider(computer);
138 computer.HardwareAdded += new HardwareEventHandler(HardwareAdded);
139 computer.HardwareRemoved += new HardwareEventHandler(HardwareRemoved);
143 timer.Enabled = true;
145 plotColorPalette = new Color[13];
146 plotColorPalette[0] = Color.Blue;
147 plotColorPalette[1] = Color.OrangeRed;
148 plotColorPalette[2] = Color.Green;
149 plotColorPalette[3] = Color.LightSeaGreen;
150 plotColorPalette[4] = Color.Goldenrod;
151 plotColorPalette[5] = Color.DarkViolet;
152 plotColorPalette[6] = Color.YellowGreen;
153 plotColorPalette[7] = Color.SaddleBrown;
154 plotColorPalette[8] = Color.RoyalBlue;
155 plotColorPalette[9] = Color.DeepPink;
156 plotColorPalette[10] = Color.MediumSeaGreen;
157 plotColorPalette[11] = Color.Olive;
158 plotColorPalette[12] = Color.Firebrick;
160 showHiddenSensors = new UserOption("hiddenMenuItem", false,
161 hiddenMenuItem, settings);
162 showHiddenSensors.Changed += delegate(object sender, EventArgs e) {
163 treeModel.ForceVisible = showHiddenSensors.Value;
166 showPlot = new UserOption("plotMenuItem", false, plotMenuItem, settings);
167 showPlot.Changed += delegate(object sender, EventArgs e) {
168 splitContainer.Panel2Collapsed = !showPlot.Value;
169 treeView.Invalidate();
172 showValue = new UserOption("valueMenuItem", true, valueMenuItem,
174 showValue.Changed += delegate(object sender, EventArgs e) {
175 treeView.Columns[1].IsVisible = showValue.Value;
178 showMin = new UserOption("minMenuItem", false, minMenuItem, settings);
179 showMin.Changed += delegate(object sender, EventArgs e) {
180 treeView.Columns[2].IsVisible = showMin.Value;
183 showMax = new UserOption("maxMenuItem", true, maxMenuItem, settings);
184 showMax.Changed += delegate(object sender, EventArgs e) {
185 treeView.Columns[3].IsVisible = showMax.Value;
188 startMinimized = new UserOption("startMinMenuItem", false,
189 startMinMenuItem, settings);
191 minimizeToTray = new UserOption("minTrayMenuItem", true,
192 minTrayMenuItem, settings);
193 minimizeToTray.Changed += delegate(object sender, EventArgs e) {
194 systemTray.IsMainIconEnabled = minimizeToTray.Value;
197 minimizeOnClose = new UserOption("minCloseMenuItem", false,
198 minCloseMenuItem, settings);
200 autoStart = new UserOption(null, startupManager.Startup,
201 startupMenuItem, settings);
202 autoStart.Changed += delegate(object sender, EventArgs e) {
204 startupManager.Startup = autoStart.Value;
205 } catch (InvalidOperationException) {
206 MessageBox.Show("Updating the auto-startup option failed.", "Error",
207 MessageBoxButtons.OK, MessageBoxIcon.Error);
208 autoStart.Value = startupManager.Startup;
212 readHddSensors = new UserOption("hddMenuItem", true, hddMenuItem,
214 readHddSensors.Changed += delegate(object sender, EventArgs e) {
215 computer.HDDEnabled = readHddSensors.Value;
216 UpdatePlotSelection(null, null);
219 showGadget = new UserOption("gadgetMenuItem", false, gadgetMenuItem,
221 showGadget.Changed += delegate(object sender, EventArgs e) {
223 gadget.Visible = showGadget.Value;
226 celciusMenuItem.Checked =
227 unitManager.TemperatureUnit == TemperatureUnit.Celcius;
228 fahrenheitMenuItem.Checked = !celciusMenuItem.Checked;
230 startupMenuItem.Visible = startupManager.IsAvailable;
232 if (startMinMenuItem.Checked) {
233 if (!minTrayMenuItem.Checked) {
234 WindowState = FormWindowState.Minimized;
241 // Create a handle, otherwise calling Close() does not fire FormClosed
242 IntPtr handle = Handle;
244 // Make sure the settings are saved when the user logs off
245 Microsoft.Win32.SystemEvents.SessionEnded += delegate {
250 private void SubHardwareAdded(IHardware hardware, Node node) {
251 Node hardwareNode = new HardwareNode(hardware, settings, unitManager);
252 node.Nodes.Add(hardwareNode);
253 foreach (IHardware subHardware in hardware.SubHardware)
254 SubHardwareAdded(subHardware, hardwareNode);
257 private void HardwareAdded(IHardware hardware) {
258 Node hardwareNode = new HardwareNode(hardware, settings, unitManager);
259 root.Nodes.Add(hardwareNode);
260 foreach (IHardware subHardware in hardware.SubHardware)
261 SubHardwareAdded(subHardware, hardwareNode);
264 private void HardwareRemoved(IHardware hardware) {
265 List<Node> nodesToRemove = new List<Node>();
266 foreach (Node node in root.Nodes) {
267 HardwareNode hardwareNode = node as HardwareNode;
268 if (hardwareNode != null && hardwareNode.Hardware == hardware)
269 nodesToRemove.Add(node);
271 foreach (Node node in nodesToRemove)
272 root.Nodes.Remove(node);
275 private void nodeTextBoxText_DrawText(object sender, DrawEventArgs e) {
276 Node node = e.Node.Tag as Node;
279 if (node.IsVisible) {
280 SensorNode sensorNode = node as SensorNode;
281 if (plotMenuItem.Checked && sensorNode != null &&
282 sensorPlotColors.TryGetValue(sensorNode.Sensor, out color))
285 e.TextColor = Color.DarkGray;
290 private void UpdatePlotSelection(object sender,
293 List<ISensor> selected = new List<ISensor>();
294 IDictionary<ISensor, Color> colors = new Dictionary<ISensor, Color>();
296 foreach (TreeNodeAdv node in treeView.AllNodes) {
297 SensorNode sensorNode = node.Tag as SensorNode;
298 if (sensorNode != null &&
299 sensorNode.Sensor.SensorType == SensorType.Temperature) {
300 if (sensorNode.Plot) {
301 colors.Add(sensorNode.Sensor,
302 plotColorPalette[colorIndex % plotColorPalette.Length]);
303 selected.Add(sensorNode.Sensor);
308 sensorPlotColors = colors;
309 plotPanel.SetSensors(selected, colors);
312 private void nodeTextBoxText_EditorShowing(object sender,
315 e.Cancel = !(treeView.CurrentNode != null &&
316 treeView.CurrentNode.Tag is SensorNode);
319 private void nodeCheckBox_IsVisibleValueNeeded(object sender,
320 NodeControlValueEventArgs e) {
321 SensorNode node = e.Node.Tag as SensorNode;
322 e.Value = (node != null) &&
323 (node.Sensor.SensorType == SensorType.Temperature) &&
324 plotMenuItem.Checked;
327 private void exitClick(object sender, EventArgs e) {
331 private void timer_Tick(object sender, EventArgs e) {
332 computer.Accept(updateVisitor);
333 treeView.Invalidate();
334 plotPanel.Invalidate();
339 if (wmiProvider != null)
340 wmiProvider.Update();
343 private void SaveConfiguration() {
344 foreach (TreeColumn column in treeView.Columns)
345 settings.SetValue("treeView.Columns." + column.Header + ".Width",
348 string fileName = Path.ChangeExtension(
349 System.Windows.Forms.Application.ExecutablePath, ".config");
351 settings.Save(fileName);
352 } catch (UnauthorizedAccessException) {
353 MessageBox.Show("Access to the path '" + fileName + "' is denied. " +
354 "The current seetings could not be saved.",
355 "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
359 private void MainForm_Load(object sender, EventArgs e) {
360 Rectangle newBounds = new Rectangle {
361 X = settings.GetValue("mainForm.Location.X", Location.X),
362 Y = settings.GetValue("mainForm.Location.Y", Location.Y),
363 Width = settings.GetValue("mainForm.Width", 470),
364 Height = settings.GetValue("mainForm.Height", 640)
367 Rectangle fullWorkingArea = new Rectangle(int.MaxValue, int.MaxValue,
368 int.MinValue, int.MinValue);
370 foreach (Screen screen in Screen.AllScreens)
371 fullWorkingArea = Rectangle.Union(fullWorkingArea, screen.Bounds);
373 Rectangle intersection = Rectangle.Intersect(fullWorkingArea, newBounds);
374 if (intersection.Width < 20 || intersection.Height < 20 ||
375 !settings.Contains("mainForm.Location.X")
377 newBounds.X = (Screen.PrimaryScreen.WorkingArea.Width / 2) -
380 newBounds.Y = (Screen.PrimaryScreen.WorkingArea.Height / 2) -
381 (newBounds.Height / 2);
384 this.Bounds = newBounds;
387 private void MainForm_FormClosed(object sender, FormClosedEventArgs e) {
391 systemTray.IsMainIconEnabled = false;
392 timer.Enabled = false;
394 systemTray.Dispose();
397 private void aboutMenuItem_Click(object sender, EventArgs e) {
398 new AboutBox().ShowDialog();
401 private void treeView_Click(object sender, EventArgs e) {
403 MouseEventArgs m = e as MouseEventArgs;
404 if (m == null || m.Button != MouseButtons.Right)
407 NodeControlInfo info = treeView.GetNodeControlInfoAt(
410 treeView.SelectedNode = info.Node;
411 if (info.Node != null) {
412 SensorNode node = info.Node.Tag as SensorNode;
413 if (node != null && node.Sensor != null) {
414 sensorContextMenu.MenuItems.Clear();
415 if (node.Sensor.Parameters.Length > 0) {
416 MenuItem item = new MenuItem("Parameters...");
417 item.Click += delegate(object obj, EventArgs args) {
418 ShowParameterForm(node.Sensor);
420 sensorContextMenu.MenuItems.Add(item);
422 if (nodeTextBoxText.EditEnabled) {
423 MenuItem item = new MenuItem("Rename");
424 item.Click += delegate(object obj, EventArgs args) {
425 nodeTextBoxText.BeginEdit();
427 sensorContextMenu.MenuItems.Add(item);
429 if (node.IsVisible) {
430 MenuItem item = new MenuItem("Hide");
431 item.Click += delegate(object obj, EventArgs args) {
432 node.IsVisible = false;
434 sensorContextMenu.MenuItems.Add(item);
436 MenuItem item = new MenuItem("Unhide");
437 item.Click += delegate(object obj, EventArgs args) {
438 node.IsVisible = true;
440 sensorContextMenu.MenuItems.Add(item);
442 sensorContextMenu.MenuItems.Add(new MenuItem("-"));
444 MenuItem item = new MenuItem("Show in Tray");
445 item.Checked = systemTray.Contains(node.Sensor);
446 item.Click += delegate(object obj, EventArgs args) {
448 systemTray.Remove(node.Sensor);
450 systemTray.Add(node.Sensor, true);
452 sensorContextMenu.MenuItems.Add(item);
454 if (gadget != null) {
455 MenuItem item = new MenuItem("Show in Gadget");
456 item.Checked = gadget.Contains(node.Sensor);
457 item.Click += delegate(object obj, EventArgs args) {
459 gadget.Remove(node.Sensor);
461 gadget.Add(node.Sensor);
464 sensorContextMenu.MenuItems.Add(item);
466 if (node.Sensor.Control != null) {
467 sensorContextMenu.MenuItems.Add(new MenuItem("-"));
468 IControl control = node.Sensor.Control;
469 MenuItem controlItem = new MenuItem("Control");
470 MenuItem defaultItem = new MenuItem("Default");
471 defaultItem.Checked = control.ControlMode == ControlMode.Default;
472 controlItem.MenuItems.Add(defaultItem);
473 defaultItem.Click += delegate(object obj, EventArgs args) {
474 control.SetDefault();
476 MenuItem manualItem = new MenuItem("Manual");
477 controlItem.MenuItems.Add(manualItem);
478 manualItem.Checked = control.ControlMode == ControlMode.Software;
479 for (int i = 0; i <= 100; i += 5) {
480 if (i <= control.MaxSoftwareValue &&
481 i >= control.MinSoftwareValue)
483 MenuItem item = new MenuItem(i + " %");
484 manualItem.MenuItems.Add(item);
485 item.Checked = control.ControlMode == ControlMode.Software &&
486 Math.Round(control.SoftwareValue) == i;
487 int softwareValue = i;
488 item.Click += delegate(object obj, EventArgs args) {
489 control.SetSoftware(softwareValue);
493 sensorContextMenu.MenuItems.Add(controlItem);
496 sensorContextMenu.Show(treeView, new Point(m.X, m.Y));
501 private void saveReportMenuItem_Click(object sender, EventArgs e) {
502 string report = computer.GetReport();
503 if (saveFileDialog.ShowDialog() == DialogResult.OK) {
504 using (TextWriter w = new StreamWriter(saveFileDialog.FileName)) {
510 private void SysTrayHideShow() {
516 protected override void WndProc(ref Message m) {
517 const int WM_SYSCOMMAND = 0x112;
518 const int SC_MINIMIZE = 0xF020;
519 const int SC_CLOSE = 0xF060;
521 if (minimizeToTray.Value &&
522 m.Msg == WM_SYSCOMMAND && m.WParam.ToInt32() == SC_MINIMIZE) {
524 } else if(minimizeOnClose.Value &&
525 m.Msg == WM_SYSCOMMAND && m.WParam.ToInt32() == SC_CLOSE) {
527 * Apparently the user wants to minimize rather than close
528 * Now we still need to check if we're going to the tray or not
530 * Note: the correct way to do this would be to send out SC_MINIMIZE,
531 * but since the code here is so simple,
532 * that would just be a waste of time.
534 if (minimizeToTray.Value)
537 WindowState = FormWindowState.Minimized;
543 private void hideShowClick(object sender, EventArgs e) {
547 private void ShowParameterForm(ISensor sensor) {
548 ParameterForm form = new ParameterForm();
549 form.Parameters = sensor.Parameters;
550 form.captionLabel.Text = sensor.Name;
554 private void treeView_NodeMouseDoubleClick(object sender,
555 TreeNodeAdvMouseEventArgs e) {
556 SensorNode node = e.Node.Tag as SensorNode;
557 if (node != null && node.Sensor != null &&
558 node.Sensor.Parameters.Length > 0) {
559 ShowParameterForm(node.Sensor);
563 private void celciusMenuItem_Click(object sender, EventArgs e) {
564 celciusMenuItem.Checked = true;
565 fahrenheitMenuItem.Checked = false;
566 unitManager.TemperatureUnit = TemperatureUnit.Celcius;
569 private void fahrenheitMenuItem_Click(object sender, EventArgs e) {
570 celciusMenuItem.Checked = false;
571 fahrenheitMenuItem.Checked = true;
572 unitManager.TemperatureUnit = TemperatureUnit.Fahrenheit;
575 private void sumbitReportMenuItem_Click(object sender, EventArgs e)
577 ReportForm form = new ReportForm();
578 form.Report = computer.GetReport();
582 private void resetMinMaxMenuItem_Click(object sender, EventArgs e) {
583 computer.Accept(new SensorVisitor(delegate(ISensor sensor) {
589 private void MainForm_MoveOrResize(object sender, EventArgs e) {
590 if (WindowState != FormWindowState.Minimized) {
591 settings.SetValue("mainForm.Location.X", Bounds.X);
592 settings.SetValue("mainForm.Location.Y", Bounds.Y);
593 settings.SetValue("mainForm.Width", Bounds.Width);
594 settings.SetValue("mainForm.Height", Bounds.Height);
598 private void resetClick(object sender, EventArgs e) {
599 // disable the fallback MainIcon during reset, otherwise icon visibility
601 systemTray.IsMainIconEnabled = false;
604 // restore the MainIcon setting
605 systemTray.IsMainIconEnabled = minimizeToTray.Value;