Modified and extended version of the patch v4 by Roland Reinl (see Issue 256). Main differences to the original patch: DeviceIoControl refactorings removed, SmartAttribute is now descriptive only and does not hold any state, report is written as one 80 columns table, sensors are created only for meaningful values and without duplicates (remaining life, temperatures, host writes and reads). Also the current implementation should really preserve all the functionality of the old system. Additionally there is now a simple SMART devices emulation class (DebugSmart) that can be used in place of WindowsSmart for testing with reported data.
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-2011
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.Reflection;
44 using System.Windows.Forms;
45 using Aga.Controls.Tree;
46 using Aga.Controls.Tree.NodeControls;
47 using OpenHardwareMonitor.Hardware;
48 using OpenHardwareMonitor.WMI;
50 namespace OpenHardwareMonitor.GUI {
51 public partial class MainForm : Form {
53 private PersistentSettings settings;
54 private UnitManager unitManager;
55 private Computer computer;
57 private TreeModel treeModel;
58 private IDictionary<ISensor, Color> sensorPlotColors =
59 new Dictionary<ISensor, Color>();
60 private Color[] plotColorPalette;
61 private SystemTray systemTray;
62 private StartupManager startupManager = new StartupManager();
63 private UpdateVisitor updateVisitor = new UpdateVisitor();
64 private SensorGadget gadget;
65 private Form plotForm;
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;
78 private UserRadioGroup plotLocation;
80 private WmiProvider wmiProvider;
82 private bool selectionDragging = false;
85 InitializeComponent();
87 // check if the OpenHardwareMonitorLib assembly has the correct version
88 if (Assembly.GetAssembly(typeof(Computer)).GetName().Version !=
89 Assembly.GetExecutingAssembly().GetName().Version) {
91 "The version of the file OpenHardwareMonitorLib.dll is incompatible.",
92 "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
96 this.settings = new PersistentSettings();
97 this.settings.Load(Path.ChangeExtension(
98 Application.ExecutablePath, ".config"));
100 this.unitManager = new UnitManager(settings);
102 // make sure the buffers used for double buffering are not disposed
103 // after each draw call
104 BufferedGraphicsManager.Current.MaximumBuffer =
105 Screen.PrimaryScreen.Bounds.Size;
107 // set the DockStyle here, to avoid conflicts with the MainMenu
108 this.splitContainer.Dock = DockStyle.Fill;
110 this.Font = SystemFonts.MessageBoxFont;
111 treeView.Font = SystemFonts.MessageBoxFont;
112 plotPanel.Font = SystemFonts.MessageBoxFont;
114 nodeCheckBox.IsVisibleValueNeeded += nodeCheckBox_IsVisibleValueNeeded;
115 nodeCheckBox.CheckStateChanged += UpdatePlotSelection;
116 nodeTextBoxText.DrawText += nodeTextBoxText_DrawText;
117 nodeTextBoxValue.DrawText += nodeTextBoxText_DrawText;
118 nodeTextBoxMin.DrawText += nodeTextBoxText_DrawText;
119 nodeTextBoxMax.DrawText += nodeTextBoxText_DrawText;
120 nodeTextBoxText.EditorShowing += nodeTextBoxText_EditorShowing;
122 foreach (TreeColumn column in treeView.Columns)
123 column.Width = Math.Max(20, Math.Min(400,
124 settings.GetValue("treeView.Columns." + column.Header + ".Width",
127 treeModel = new TreeModel();
128 root = new Node(System.Environment.MachineName);
129 root.Image = Utilities.EmbeddedResources.GetImage("computer.png");
131 treeModel.Nodes.Add(root);
132 treeView.Model = treeModel;
134 this.computer = new Computer(settings);
136 systemTray = new SystemTray(computer, settings);
137 systemTray.HideShowCommand += hideShowClick;
138 systemTray.ExitCommand += exitClick;
140 int p = (int)Environment.OSVersion.Platform;
141 if ((p == 4) || (p == 128)) { // Unix
142 treeView.RowHeight = Math.Max(treeView.RowHeight, 18);
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;
150 minTrayMenuItem.Visible = false;
151 startMinMenuItem.Visible = false;
153 treeView.RowHeight = Math.Max(treeView.Font.Height + 1, 18);
155 gadget = new SensorGadget(computer, settings, unitManager);
156 gadget.HideShowCommand += hideShowClick;
158 wmiProvider = new WmiProvider(computer);
161 computer.HardwareAdded += new HardwareEventHandler(HardwareAdded);
162 computer.HardwareRemoved += new HardwareEventHandler(HardwareRemoved);
166 timer.Enabled = true;
168 plotColorPalette = new Color[13];
169 plotColorPalette[0] = Color.Blue;
170 plotColorPalette[1] = Color.OrangeRed;
171 plotColorPalette[2] = Color.Green;
172 plotColorPalette[3] = Color.LightSeaGreen;
173 plotColorPalette[4] = Color.Goldenrod;
174 plotColorPalette[5] = Color.DarkViolet;
175 plotColorPalette[6] = Color.YellowGreen;
176 plotColorPalette[7] = Color.SaddleBrown;
177 plotColorPalette[8] = Color.RoyalBlue;
178 plotColorPalette[9] = Color.DeepPink;
179 plotColorPalette[10] = Color.MediumSeaGreen;
180 plotColorPalette[11] = Color.Olive;
181 plotColorPalette[12] = Color.Firebrick;
183 showHiddenSensors = new UserOption("hiddenMenuItem", false,
184 hiddenMenuItem, settings);
185 showHiddenSensors.Changed += delegate(object sender, EventArgs e) {
186 treeModel.ForceVisible = showHiddenSensors.Value;
189 showValue = new UserOption("valueMenuItem", true, valueMenuItem,
191 showValue.Changed += delegate(object sender, EventArgs e) {
192 treeView.Columns[1].IsVisible = showValue.Value;
195 showMin = new UserOption("minMenuItem", false, minMenuItem, settings);
196 showMin.Changed += delegate(object sender, EventArgs e) {
197 treeView.Columns[2].IsVisible = showMin.Value;
200 showMax = new UserOption("maxMenuItem", true, maxMenuItem, settings);
201 showMax.Changed += delegate(object sender, EventArgs e) {
202 treeView.Columns[3].IsVisible = showMax.Value;
205 startMinimized = new UserOption("startMinMenuItem", false,
206 startMinMenuItem, settings);
208 minimizeToTray = new UserOption("minTrayMenuItem", true,
209 minTrayMenuItem, settings);
210 minimizeToTray.Changed += delegate(object sender, EventArgs e) {
211 systemTray.IsMainIconEnabled = minimizeToTray.Value;
214 minimizeOnClose = new UserOption("minCloseMenuItem", false,
215 minCloseMenuItem, settings);
217 autoStart = new UserOption(null, startupManager.Startup,
218 startupMenuItem, settings);
219 autoStart.Changed += delegate(object sender, EventArgs e) {
221 startupManager.Startup = autoStart.Value;
222 } catch (InvalidOperationException) {
223 MessageBox.Show("Updating the auto-startup option failed.", "Error",
224 MessageBoxButtons.OK, MessageBoxIcon.Error);
225 autoStart.Value = startupManager.Startup;
229 readHddSensors = new UserOption("hddMenuItem", true, hddMenuItem,
231 readHddSensors.Changed += delegate(object sender, EventArgs e) {
232 computer.HDDEnabled = readHddSensors.Value;
233 UpdatePlotSelection(null, null);
236 showGadget = new UserOption("gadgetMenuItem", false, gadgetMenuItem,
238 showGadget.Changed += delegate(object sender, EventArgs e) {
240 gadget.Visible = showGadget.Value;
243 celsiusMenuItem.Checked =
244 unitManager.TemperatureUnit == TemperatureUnit.Celsius;
245 fahrenheitMenuItem.Checked = !celsiusMenuItem.Checked;
247 InitializePlotForm();
249 startupMenuItem.Visible = startupManager.IsAvailable;
251 if (startMinMenuItem.Checked) {
252 if (!minTrayMenuItem.Checked) {
253 WindowState = FormWindowState.Minimized;
260 // Create a handle, otherwise calling Close() does not fire FormClosed
261 IntPtr handle = Handle;
263 // Make sure the settings are saved when the user logs off
264 Microsoft.Win32.SystemEvents.SessionEnded += delegate {
269 private void InitializePlotForm() {
270 plotForm = new Form();
271 plotForm.FormBorderStyle = FormBorderStyle.SizableToolWindow;
272 plotForm.ShowInTaskbar = false;
273 plotForm.StartPosition = FormStartPosition.Manual;
274 this.AddOwnedForm(plotForm);
275 plotForm.Bounds = new Rectangle {
276 X = settings.GetValue("plotForm.Location.X", -100000),
277 Y = settings.GetValue("plotForm.Location.Y", 100),
278 Width = settings.GetValue("plotForm.Width", 600),
279 Height = settings.GetValue("plotForm.Height", 400)
282 showPlot = new UserOption("plotMenuItem", false, plotMenuItem, settings);
283 plotLocation = new UserRadioGroup("plotLocation", 0,
284 new[] { plotWindowMenuItem, plotBottomMenuItem, plotRightMenuItem },
287 showPlot.Changed += delegate(object sender, EventArgs e) {
288 if (plotLocation.Value == 0) {
289 if (showPlot.Value && this.Visible)
294 splitContainer.Panel2Collapsed = !showPlot.Value;
296 treeView.Invalidate();
298 plotLocation.Changed += delegate(object sender, EventArgs e) {
299 switch (plotLocation.Value) {
301 splitContainer.Panel2.Controls.Clear();
302 splitContainer.Panel2Collapsed = true;
303 plotForm.Controls.Add(plotPanel);
304 if (showPlot.Value && this.Visible)
308 plotForm.Controls.Clear();
310 splitContainer.Orientation = Orientation.Horizontal;
311 splitContainer.Panel2.Controls.Add(plotPanel);
312 splitContainer.Panel2Collapsed = !showPlot.Value;
315 plotForm.Controls.Clear();
317 splitContainer.Orientation = Orientation.Vertical;
318 splitContainer.Panel2.Controls.Add(plotPanel);
319 splitContainer.Panel2Collapsed = !showPlot.Value;
324 plotForm.FormClosing += delegate(object sender, FormClosingEventArgs e) {
325 if (e.CloseReason == CloseReason.UserClosing) {
326 // just switch off the plotting when the user closes the form
327 if (plotLocation.Value == 0) {
328 showPlot.Value = false;
334 EventHandler moveOrResizePlotForm = delegate(object sender, EventArgs e) {
335 if (plotForm.WindowState != FormWindowState.Minimized) {
336 settings.SetValue("plotForm.Location.X", plotForm.Bounds.X);
337 settings.SetValue("plotForm.Location.Y", plotForm.Bounds.Y);
338 settings.SetValue("plotForm.Width", plotForm.Bounds.Width);
339 settings.SetValue("plotForm.Height", plotForm.Bounds.Height);
342 plotForm.Move += moveOrResizePlotForm;
343 plotForm.Resize += moveOrResizePlotForm;
345 plotForm.VisibleChanged += delegate(object sender, EventArgs e) {
346 Rectangle bounds = new Rectangle(plotForm.Location, plotForm.Size);
347 Screen screen = Screen.FromRectangle(bounds);
348 Rectangle intersection =
349 Rectangle.Intersect(screen.WorkingArea, bounds);
350 if (intersection.Width < Math.Min(16, bounds.Width) ||
351 intersection.Height < Math.Min(16, bounds.Height)) {
352 plotForm.Location = new Point(
353 screen.WorkingArea.Width / 2 - bounds.Width / 2,
354 screen.WorkingArea.Height / 2 - bounds.Height / 2);
358 this.VisibleChanged += delegate(object sender, EventArgs e) {
359 if (this.Visible && showPlot.Value && plotLocation.Value == 0)
366 private void SubHardwareAdded(IHardware hardware, Node node) {
367 Node hardwareNode = new HardwareNode(hardware, settings, unitManager);
368 node.Nodes.Add(hardwareNode);
369 foreach (IHardware subHardware in hardware.SubHardware)
370 SubHardwareAdded(subHardware, hardwareNode);
373 private void HardwareAdded(IHardware hardware) {
374 Node hardwareNode = new HardwareNode(hardware, settings, unitManager);
375 root.Nodes.Add(hardwareNode);
376 foreach (IHardware subHardware in hardware.SubHardware)
377 SubHardwareAdded(subHardware, hardwareNode);
380 private void HardwareRemoved(IHardware hardware) {
381 List<Node> nodesToRemove = new List<Node>();
382 foreach (Node node in root.Nodes) {
383 HardwareNode hardwareNode = node as HardwareNode;
384 if (hardwareNode != null && hardwareNode.Hardware == hardware)
385 nodesToRemove.Add(node);
387 foreach (Node node in nodesToRemove)
388 root.Nodes.Remove(node);
391 private void nodeTextBoxText_DrawText(object sender, DrawEventArgs e) {
392 Node node = e.Node.Tag as Node;
395 if (node.IsVisible) {
396 SensorNode sensorNode = node as SensorNode;
397 if (plotMenuItem.Checked && sensorNode != null &&
398 sensorPlotColors.TryGetValue(sensorNode.Sensor, out color))
401 e.TextColor = Color.DarkGray;
406 private void UpdatePlotSelection(object sender,
409 List<ISensor> selected = new List<ISensor>();
410 IDictionary<ISensor, Color> colors = new Dictionary<ISensor, Color>();
412 foreach (TreeNodeAdv node in treeView.AllNodes) {
413 SensorNode sensorNode = node.Tag as SensorNode;
414 if (sensorNode != null &&
415 sensorNode.Sensor.SensorType == SensorType.Temperature) {
416 if (sensorNode.Plot) {
417 colors.Add(sensorNode.Sensor,
418 plotColorPalette[colorIndex % plotColorPalette.Length]);
419 selected.Add(sensorNode.Sensor);
424 sensorPlotColors = colors;
425 plotPanel.SetSensors(selected, colors);
428 private void nodeTextBoxText_EditorShowing(object sender,
431 e.Cancel = !(treeView.CurrentNode != null &&
432 (treeView.CurrentNode.Tag is SensorNode ||
433 treeView.CurrentNode.Tag is HardwareNode));
436 private void nodeCheckBox_IsVisibleValueNeeded(object sender,
437 NodeControlValueEventArgs e) {
438 SensorNode node = e.Node.Tag as SensorNode;
439 e.Value = (node != null) &&
440 (node.Sensor.SensorType == SensorType.Temperature) &&
441 plotMenuItem.Checked;
444 private void exitClick(object sender, EventArgs e) {
448 private void timer_Tick(object sender, EventArgs e) {
449 computer.Accept(updateVisitor);
450 treeView.Invalidate();
451 plotPanel.Invalidate();
456 if (wmiProvider != null)
457 wmiProvider.Update();
460 private void SaveConfiguration() {
461 foreach (TreeColumn column in treeView.Columns)
462 settings.SetValue("treeView.Columns." + column.Header + ".Width",
465 string fileName = Path.ChangeExtension(
466 System.Windows.Forms.Application.ExecutablePath, ".config");
468 settings.Save(fileName);
469 } catch (UnauthorizedAccessException) {
470 MessageBox.Show("Access to the path '" + fileName + "' is denied. " +
471 "The current settings could not be saved.",
472 "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
473 } catch (IOException) {
474 MessageBox.Show("The path '" + fileName + "' is not writeable. " +
475 "The current settings could not be saved.",
476 "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
480 private void MainForm_Load(object sender, EventArgs e) {
481 Rectangle newBounds = new Rectangle {
482 X = settings.GetValue("mainForm.Location.X", Location.X),
483 Y = settings.GetValue("mainForm.Location.Y", Location.Y),
484 Width = settings.GetValue("mainForm.Width", 470),
485 Height = settings.GetValue("mainForm.Height", 640)
488 Rectangle fullWorkingArea = new Rectangle(int.MaxValue, int.MaxValue,
489 int.MinValue, int.MinValue);
491 foreach (Screen screen in Screen.AllScreens)
492 fullWorkingArea = Rectangle.Union(fullWorkingArea, screen.Bounds);
494 Rectangle intersection = Rectangle.Intersect(fullWorkingArea, newBounds);
495 if (intersection.Width < 20 || intersection.Height < 20 ||
496 !settings.Contains("mainForm.Location.X")
498 newBounds.X = (Screen.PrimaryScreen.WorkingArea.Width / 2) -
501 newBounds.Y = (Screen.PrimaryScreen.WorkingArea.Height / 2) -
502 (newBounds.Height / 2);
505 this.Bounds = newBounds;
508 private void MainForm_FormClosed(object sender, FormClosedEventArgs e) {
510 systemTray.IsMainIconEnabled = false;
511 timer.Enabled = false;
514 systemTray.Dispose();
517 private void aboutMenuItem_Click(object sender, EventArgs e) {
518 new AboutBox().ShowDialog();
521 private void treeView_Click(object sender, EventArgs e) {
523 MouseEventArgs m = e as MouseEventArgs;
524 if (m == null || m.Button != MouseButtons.Right)
527 NodeControlInfo info = treeView.GetNodeControlInfoAt(
530 treeView.SelectedNode = info.Node;
531 if (info.Node != null) {
532 SensorNode node = info.Node.Tag as SensorNode;
533 if (node != null && node.Sensor != null) {
534 treeContextMenu.MenuItems.Clear();
535 if (node.Sensor.Parameters.Length > 0) {
536 MenuItem item = new MenuItem("Parameters...");
537 item.Click += delegate(object obj, EventArgs args) {
538 ShowParameterForm(node.Sensor);
540 treeContextMenu.MenuItems.Add(item);
542 if (nodeTextBoxText.EditEnabled) {
543 MenuItem item = new MenuItem("Rename");
544 item.Click += delegate(object obj, EventArgs args) {
545 nodeTextBoxText.BeginEdit();
547 treeContextMenu.MenuItems.Add(item);
549 if (node.IsVisible) {
550 MenuItem item = new MenuItem("Hide");
551 item.Click += delegate(object obj, EventArgs args) {
552 node.IsVisible = false;
554 treeContextMenu.MenuItems.Add(item);
556 MenuItem item = new MenuItem("Unhide");
557 item.Click += delegate(object obj, EventArgs args) {
558 node.IsVisible = true;
560 treeContextMenu.MenuItems.Add(item);
562 treeContextMenu.MenuItems.Add(new MenuItem("-"));
564 MenuItem item = new MenuItem("Show in Tray");
565 item.Checked = systemTray.Contains(node.Sensor);
566 item.Click += delegate(object obj, EventArgs args) {
568 systemTray.Remove(node.Sensor);
570 systemTray.Add(node.Sensor, true);
572 treeContextMenu.MenuItems.Add(item);
574 if (gadget != null) {
575 MenuItem item = new MenuItem("Show in Gadget");
576 item.Checked = gadget.Contains(node.Sensor);
577 item.Click += delegate(object obj, EventArgs args) {
579 gadget.Remove(node.Sensor);
581 gadget.Add(node.Sensor);
584 treeContextMenu.MenuItems.Add(item);
586 if (node.Sensor.Control != null) {
587 treeContextMenu.MenuItems.Add(new MenuItem("-"));
588 IControl control = node.Sensor.Control;
589 MenuItem controlItem = new MenuItem("Control");
590 MenuItem defaultItem = new MenuItem("Default");
591 defaultItem.Checked = control.ControlMode == ControlMode.Default;
592 controlItem.MenuItems.Add(defaultItem);
593 defaultItem.Click += delegate(object obj, EventArgs args) {
594 control.SetDefault();
596 MenuItem manualItem = new MenuItem("Manual");
597 controlItem.MenuItems.Add(manualItem);
598 manualItem.Checked = control.ControlMode == ControlMode.Software;
599 for (int i = 0; i <= 100; i += 5) {
600 if (i <= control.MaxSoftwareValue &&
601 i >= control.MinSoftwareValue) {
602 MenuItem item = new MenuItem(i + " %");
603 manualItem.MenuItems.Add(item);
604 item.Checked = control.ControlMode == ControlMode.Software &&
605 Math.Round(control.SoftwareValue) == i;
606 int softwareValue = i;
607 item.Click += delegate(object obj, EventArgs args) {
608 control.SetSoftware(softwareValue);
612 treeContextMenu.MenuItems.Add(controlItem);
615 treeContextMenu.Show(treeView, new Point(m.X, m.Y));
618 HardwareNode hardwareNode = info.Node.Tag as HardwareNode;
619 if (hardwareNode != null && hardwareNode.Hardware != null) {
620 treeContextMenu.MenuItems.Clear();
622 if (nodeTextBoxText.EditEnabled) {
623 MenuItem item = new MenuItem("Rename");
624 item.Click += delegate(object obj, EventArgs args) {
625 nodeTextBoxText.BeginEdit();
627 treeContextMenu.MenuItems.Add(item);
630 treeContextMenu.Show(treeView, new Point(m.X, m.Y));
635 private void saveReportMenuItem_Click(object sender, EventArgs e) {
636 string report = computer.GetReport();
637 if (saveFileDialog.ShowDialog() == DialogResult.OK) {
638 using (TextWriter w = new StreamWriter(saveFileDialog.FileName)) {
644 private void SysTrayHideShow() {
650 protected override void WndProc(ref Message m) {
651 const int WM_SYSCOMMAND = 0x112;
652 const int SC_MINIMIZE = 0xF020;
653 const int SC_CLOSE = 0xF060;
655 if (minimizeToTray.Value &&
656 m.Msg == WM_SYSCOMMAND && m.WParam.ToInt32() == SC_MINIMIZE) {
658 } else if(minimizeOnClose.Value &&
659 m.Msg == WM_SYSCOMMAND && m.WParam.ToInt32() == SC_CLOSE) {
661 * Apparently the user wants to minimize rather than close
662 * Now we still need to check if we're going to the tray or not
664 * Note: the correct way to do this would be to send out SC_MINIMIZE,
665 * but since the code here is so simple,
666 * that would just be a waste of time.
668 if (minimizeToTray.Value)
671 WindowState = FormWindowState.Minimized;
677 private void hideShowClick(object sender, EventArgs e) {
681 private void ShowParameterForm(ISensor sensor) {
682 ParameterForm form = new ParameterForm();
683 form.Parameters = sensor.Parameters;
684 form.captionLabel.Text = sensor.Name;
688 private void treeView_NodeMouseDoubleClick(object sender,
689 TreeNodeAdvMouseEventArgs e) {
690 SensorNode node = e.Node.Tag as SensorNode;
691 if (node != null && node.Sensor != null &&
692 node.Sensor.Parameters.Length > 0) {
693 ShowParameterForm(node.Sensor);
697 private void celsiusMenuItem_Click(object sender, EventArgs e) {
698 celsiusMenuItem.Checked = true;
699 fahrenheitMenuItem.Checked = false;
700 unitManager.TemperatureUnit = TemperatureUnit.Celsius;
703 private void fahrenheitMenuItem_Click(object sender, EventArgs e) {
704 celsiusMenuItem.Checked = false;
705 fahrenheitMenuItem.Checked = true;
706 unitManager.TemperatureUnit = TemperatureUnit.Fahrenheit;
709 private void sumbitReportMenuItem_Click(object sender, EventArgs e)
711 ReportForm form = new ReportForm();
712 form.Report = computer.GetReport();
716 private void resetMinMaxMenuItem_Click(object sender, EventArgs e) {
717 computer.Accept(new SensorVisitor(delegate(ISensor sensor) {
723 private void MainForm_MoveOrResize(object sender, EventArgs e) {
724 if (WindowState != FormWindowState.Minimized) {
725 settings.SetValue("mainForm.Location.X", Bounds.X);
726 settings.SetValue("mainForm.Location.Y", Bounds.Y);
727 settings.SetValue("mainForm.Width", Bounds.Width);
728 settings.SetValue("mainForm.Height", Bounds.Height);
732 private void resetClick(object sender, EventArgs e) {
733 // disable the fallback MainIcon during reset, otherwise icon visibility
735 systemTray.IsMainIconEnabled = false;
738 // restore the MainIcon setting
739 systemTray.IsMainIconEnabled = minimizeToTray.Value;
742 private void treeView_MouseMove(object sender, MouseEventArgs e) {
743 selectionDragging = selectionDragging &
744 (e.Button & (MouseButtons.Left | MouseButtons.Right)) > 0;
746 if (selectionDragging)
747 treeView.SelectedNode = treeView.GetNodeAt(e.Location);
750 private void treeView_MouseDown(object sender, MouseEventArgs e) {
751 selectionDragging = true;
754 private void treeView_MouseUp(object sender, MouseEventArgs e) {
755 selectionDragging = false;