Fixed the context menu positioning as well, following the previous fix to multimonitor setups.
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 if (settings.Contains("mainForm.Location.X")) {
104 int x = settings.GetValue("mainForm.Location.X", Location.X);
106 int y = settings.GetValue("mainForm.Location.Y", Location.Y);
108 this.Location = new Point(x, y);
110 StartPosition = FormStartPosition.CenterScreen;
113 ClientSize = new Size(
114 settings.GetValue("mainForm.Width", 470),
115 settings.GetValue("mainForm.Height", 640));
117 foreach (TreeColumn column in treeView.Columns)
118 column.Width = Math.Max(20, Math.Min(400,
119 settings.GetValue("treeView.Columns." + column.Header + ".Width",
122 treeModel = new TreeModel();
123 root = new Node(System.Environment.MachineName);
124 root.Image = Utilities.EmbeddedResources.GetImage("computer.png");
126 treeModel.Nodes.Add(root);
127 treeView.Model = treeModel;
129 this.computer = new Computer(settings);
131 systemTray = new SystemTray(computer, settings);
132 systemTray.HideShowCommand += hideShowClick;
133 systemTray.ExitCommand += exitClick;
135 int p = (int)Environment.OSVersion.Platform;
136 if ((p == 4) || (p == 128)) { // Unix
137 splitContainer.BorderStyle = BorderStyle.None;
138 splitContainer.Border3DStyle = Border3DStyle.Adjust;
139 splitContainer.SplitterWidth = 4;
140 treeView.BorderStyle = BorderStyle.Fixed3D;
141 plotPanel.BorderStyle = BorderStyle.Fixed3D;
142 gadgetMenuItem.Visible = false;
143 minCloseMenuItem.Visible = false;
145 gadget = new SensorGadget(computer, settings, unitManager);
148 computer.HardwareAdded += new HardwareEventHandler(HardwareAdded);
149 computer.HardwareRemoved += new HardwareEventHandler(HardwareRemoved);
152 timer.Enabled = true;
154 plotColorPalette = new Color[13];
155 plotColorPalette[0] = Color.Blue;
156 plotColorPalette[1] = Color.OrangeRed;
157 plotColorPalette[2] = Color.Green;
158 plotColorPalette[3] = Color.LightSeaGreen;
159 plotColorPalette[4] = Color.Goldenrod;
160 plotColorPalette[5] = Color.DarkViolet;
161 plotColorPalette[6] = Color.YellowGreen;
162 plotColorPalette[7] = Color.SaddleBrown;
163 plotColorPalette[8] = Color.RoyalBlue;
164 plotColorPalette[9] = Color.DeepPink;
165 plotColorPalette[10] = Color.MediumSeaGreen;
166 plotColorPalette[11] = Color.Olive;
167 plotColorPalette[12] = Color.Firebrick;
169 showHiddenSensors = new UserOption("hiddenMenuItem", false, hiddenMenuItem, settings);
170 showHiddenSensors.Changed += delegate(object sender, EventArgs e) {
171 treeModel.ForceVisible = showHiddenSensors.Value;
174 showPlot = new UserOption("plotMenuItem", false, plotMenuItem, settings);
175 showPlot.Changed += delegate(object sender, EventArgs e) {
176 splitContainer.Panel2Collapsed = !showPlot.Value;
177 treeView.Invalidate();
180 showValue = new UserOption("valueMenuItem", true, valueMenuItem, settings);
181 showValue.Changed += delegate(object sender, EventArgs e) {
182 treeView.Columns[1].IsVisible = showValue.Value;
185 showMin = new UserOption("minMenuItem", false, minMenuItem, settings);
186 showMin.Changed += delegate(object sender, EventArgs e) {
187 treeView.Columns[2].IsVisible = showMin.Value;
190 showMax = new UserOption("maxMenuItem", true, maxMenuItem, settings);
191 showMax.Changed += delegate(object sender, EventArgs e) {
192 treeView.Columns[3].IsVisible = showMax.Value;
195 startMinimized = new UserOption("startMinMenuItem", false, startMinMenuItem, settings);
197 minimizeToTray = new UserOption("minTrayMenuItem", true, minTrayMenuItem, settings);
198 minimizeToTray.Changed += delegate(object sender, EventArgs e) {
199 systemTray.IsMainIconEnabled = minimizeToTray.Value;
202 minimizeOnClose = new UserOption("minCloseMenuItem", false, minCloseMenuItem, settings);
204 autoStart = new UserOption(null, startupManager.Startup, startupMenuItem, settings);
205 autoStart.Changed += delegate(object sender, EventArgs e) {
207 startupManager.Startup = autoStart.Value;
208 } catch (InvalidOperationException) {
209 MessageBox.Show("Updating the auto-startup option failed.", "Error",
210 MessageBoxButtons.OK, MessageBoxIcon.Error);
211 autoStart.Value = startupManager.Startup;
215 readHddSensors = new UserOption("hddMenuItem", true, hddMenuItem, settings);
216 readHddSensors.Changed += delegate(object sender, EventArgs e) {
217 computer.HDDEnabled = readHddSensors.Value;
218 UpdatePlotSelection(null, null);
221 showGadget = new UserOption("gadgetMenuItem", false, gadgetMenuItem, settings);
222 showGadget.Changed += delegate(object sender, EventArgs e) {
224 gadget.Visible = showGadget.Value;
227 celciusMenuItem.Checked =
228 unitManager.TemperatureUnit == TemperatureUnit.Celcius;
229 fahrenheitMenuItem.Checked = !celciusMenuItem.Checked;
231 startupMenuItem.Visible = startupManager.IsAvailable;
233 if (startMinMenuItem.Checked) {
234 if (!minTrayMenuItem.Checked) {
235 WindowState = FormWindowState.Minimized;
242 // Create a handle, otherwise calling Close() does not fire FormClosed
243 IntPtr handle = Handle;
245 // Make sure the settings are saved when the user logs off
246 Microsoft.Win32.SystemEvents.SessionEnded +=
247 delegate(object sender, Microsoft.Win32.SessionEndedEventArgs e) {
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, CancelEventArgs e)
316 e.Cancel = !(treeView.CurrentNode != null &&
317 treeView.CurrentNode.Tag is SensorNode);
320 private void nodeCheckBox_IsVisibleValueNeeded(object sender,
321 NodeControlValueEventArgs e) {
322 SensorNode node = e.Node.Tag as SensorNode;
323 e.Value = (node != null) &&
324 (node.Sensor.SensorType == SensorType.Temperature) &&
325 plotMenuItem.Checked;
328 private void exitClick(object sender, EventArgs e) {
332 private void timer_Tick(object sender, EventArgs e) {
333 computer.Accept(updateVisitor);
334 treeView.Invalidate();
335 plotPanel.Invalidate();
341 private void SaveConfiguration() {
342 if (WindowState != FormWindowState.Minimized) {
343 settings.SetValue("mainForm.Location.X", Location.X);
344 settings.SetValue("mainForm.Location.Y", Location.Y);
345 settings.SetValue("mainForm.Width", ClientSize.Width);
346 settings.SetValue("mainForm.Height", ClientSize.Height);
349 foreach (TreeColumn column in treeView.Columns)
350 settings.SetValue("treeView.Columns." + column.Header + ".Width",
353 settings.Save(Path.ChangeExtension(
354 System.Windows.Forms.Application.ExecutablePath, ".config"));
357 private void MainForm_FormClosed(object sender, FormClosedEventArgs e) {
361 timer.Enabled = false;
362 systemTray.Dispose();
366 private void aboutMenuItem_Click(object sender, EventArgs e) {
367 new AboutBox().ShowDialog();
370 private void treeView_Click(object sender, EventArgs e) {
372 MouseEventArgs m = e as MouseEventArgs;
373 if (m == null || m.Button != MouseButtons.Right)
376 NodeControlInfo info = treeView.GetNodeControlInfoAt(new Point(m.X, m.Y));
377 treeView.SelectedNode = info.Node;
378 if (info.Node != null) {
379 SensorNode node = info.Node.Tag as SensorNode;
380 if (node != null && node.Sensor != null) {
381 sensorContextMenu.MenuItems.Clear();
382 if (node.Sensor.Parameters.Length > 0) {
383 MenuItem item = new MenuItem("Parameters...");
384 item.Click += delegate(object obj, EventArgs args) {
385 ShowParameterForm(node.Sensor);
387 sensorContextMenu.MenuItems.Add(item);
389 if (nodeTextBoxText.EditEnabled) {
390 MenuItem item = new MenuItem("Rename");
391 item.Click += delegate(object obj, EventArgs args) {
392 nodeTextBoxText.BeginEdit();
394 sensorContextMenu.MenuItems.Add(item);
396 if (node.IsVisible) {
397 MenuItem item = new MenuItem("Hide");
398 item.Click += delegate(object obj, EventArgs args) {
399 node.IsVisible = false;
401 sensorContextMenu.MenuItems.Add(item);
403 MenuItem item = new MenuItem("Unhide");
404 item.Click += delegate(object obj, EventArgs args) {
405 node.IsVisible = true;
407 sensorContextMenu.MenuItems.Add(item);
409 sensorContextMenu.MenuItems.Add(new MenuItem("-"));
411 MenuItem item = new MenuItem("Show in Tray");
412 item.Checked = systemTray.Contains(node.Sensor);
413 item.Click += delegate(object obj, EventArgs args) {
415 systemTray.Remove(node.Sensor);
417 systemTray.Add(node.Sensor, true);
419 sensorContextMenu.MenuItems.Add(item);
422 MenuItem item = new MenuItem("Show in Gadget");
423 item.Checked = gadget.Contains(node.Sensor);
424 item.Click += delegate(object obj, EventArgs args) {
426 gadget.Remove(node.Sensor);
428 gadget.Add(node.Sensor);
431 sensorContextMenu.MenuItems.Add(item);
434 sensorContextMenu.Show(treeView, new Point(m.X, m.Y));
439 private void saveReportMenuItem_Click(object sender, EventArgs e) {
440 string report = computer.GetReport();
441 if (saveFileDialog.ShowDialog() == DialogResult.OK) {
442 using (TextWriter w = new StreamWriter(saveFileDialog.FileName)) {
448 private void SysTrayHideShow() {
454 protected override void WndProc(ref Message m) {
455 const int WM_SYSCOMMAND = 0x112;
456 const int SC_MINIMIZE = 0xF020;
457 const int SC_CLOSE = 0xF060;
459 if (minimizeToTray.Value &&
460 m.Msg == WM_SYSCOMMAND && m.WParam.ToInt32() == SC_MINIMIZE) {
462 } else if(minimizeOnClose.Value &&
463 m.Msg == WM_SYSCOMMAND && m.WParam.ToInt32() == SC_CLOSE) {
465 * Apparently the user wants to minimize rather than close
466 * Now we still need to check if we're going to the tray or not
468 * Note: the correct way to do this would be to send out SC_MINIMIZE,
469 * but since the code here is so simple,
470 * that would just be a waste of time.
472 if (minimizeToTray.Value)
475 WindowState = FormWindowState.Minimized;
481 private void hideShowClick(object sender, EventArgs e) {
485 private void ShowParameterForm(ISensor sensor) {
486 ParameterForm form = new ParameterForm();
487 form.Parameters = sensor.Parameters;
488 form.captionLabel.Text = sensor.Name;
492 private void treeView_NodeMouseDoubleClick(object sender,
493 TreeNodeAdvMouseEventArgs e) {
494 SensorNode node = e.Node.Tag as SensorNode;
495 if (node != null && node.Sensor != null &&
496 node.Sensor.Parameters.Length > 0) {
497 ShowParameterForm(node.Sensor);
501 private void celciusMenuItem_Click(object sender, EventArgs e) {
502 celciusMenuItem.Checked = true;
503 fahrenheitMenuItem.Checked = false;
504 unitManager.TemperatureUnit = TemperatureUnit.Celcius;
507 private void fahrenheitMenuItem_Click(object sender, EventArgs e) {
508 celciusMenuItem.Checked = false;
509 fahrenheitMenuItem.Checked = true;
510 unitManager.TemperatureUnit = TemperatureUnit.Fahrenheit;
513 private void sumbitReportMenuItem_Click(object sender, EventArgs e)
515 ReportForm form = new ReportForm();
516 form.Report = computer.GetReport();
520 private void resetMinMaxMenuItem_Click(object sender, EventArgs e) {
521 computer.Accept(new SensorVisitor(delegate(ISensor sensor) {