Fixed a problem where the ADL Main_Memory_Alloc callback delegate could be garbage collected while still in use.
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 int p = (int)Environment.OSVersion.Platform;
92 if ((p == 4) || (p == 128)) {
93 splitContainer.BorderStyle = BorderStyle.None;
94 splitContainer.Border3DStyle = Border3DStyle.Adjust;
95 splitContainer.SplitterWidth = 4;
96 treeView.BorderStyle = BorderStyle.Fixed3D;
97 plotPanel.BorderStyle = BorderStyle.Fixed3D;
100 this.Font = SystemFonts.MessageBoxFont;
101 treeView.Font = SystemFonts.MessageBoxFont;
102 plotPanel.Font = SystemFonts.MessageBoxFont;
104 nodeCheckBox.IsVisibleValueNeeded += nodeCheckBox_IsVisibleValueNeeded;
105 nodeCheckBox.CheckStateChanged += UpdatePlotSelection;
106 nodeTextBoxText.DrawText += nodeTextBoxText_DrawText;
107 nodeTextBoxValue.DrawText += nodeTextBoxText_DrawText;
108 nodeTextBoxMin.DrawText += nodeTextBoxText_DrawText;
109 nodeTextBoxMax.DrawText += nodeTextBoxText_DrawText;
110 nodeTextBoxText.EditorShowing += nodeTextBoxText_EditorShowing;
112 if (settings.Contains("mainForm.Location.X")) {
113 int x = settings.GetValue("mainForm.Location.X", Location.X);
115 int y = settings.GetValue("mainForm.Location.Y", Location.Y);
117 this.Location = new Point(x, y);
119 StartPosition = FormStartPosition.CenterScreen;
122 ClientSize = new Size(
123 settings.GetValue("mainForm.Width", 470),
124 settings.GetValue("mainForm.Height", 640));
126 foreach (TreeColumn column in treeView.Columns)
127 column.Width = Math.Max(20, Math.Min(400,
128 settings.GetValue("treeView.Columns." + column.Header + ".Width",
131 treeModel = new TreeModel();
132 root = new Node(System.Environment.MachineName);
133 root.Image = Utilities.EmbeddedResources.GetImage("computer.png");
135 treeModel.Nodes.Add(root);
136 treeView.Model = treeModel;
138 this.computer = new Computer(settings);
140 systemTray = new SystemTray(computer, settings);
141 systemTray.HideShowCommand += hideShowClick;
142 systemTray.ExitCommand += exitClick;
144 gadget = new SensorGadget(computer, settings, unitManager);
146 computer.HardwareAdded += new HardwareEventHandler(HardwareAdded);
147 computer.HardwareRemoved += new HardwareEventHandler(HardwareRemoved);
150 timer.Enabled = true;
152 plotColorPalette = new Color[13];
153 plotColorPalette[0] = Color.Blue;
154 plotColorPalette[1] = Color.OrangeRed;
155 plotColorPalette[2] = Color.Green;
156 plotColorPalette[3] = Color.LightSeaGreen;
157 plotColorPalette[4] = Color.Goldenrod;
158 plotColorPalette[5] = Color.DarkViolet;
159 plotColorPalette[6] = Color.YellowGreen;
160 plotColorPalette[7] = Color.SaddleBrown;
161 plotColorPalette[8] = Color.RoyalBlue;
162 plotColorPalette[9] = Color.DeepPink;
163 plotColorPalette[10] = Color.MediumSeaGreen;
164 plotColorPalette[11] = Color.Olive;
165 plotColorPalette[12] = Color.Firebrick;
167 showHiddenSensors = new UserOption("hiddenMenuItem", false, hiddenMenuItem, settings);
168 showHiddenSensors.Changed += delegate(object sender, EventArgs e) {
169 treeModel.ForceVisible = showHiddenSensors.Value;
172 showPlot = new UserOption("plotMenuItem", false, plotMenuItem, settings);
173 showPlot.Changed += delegate(object sender, EventArgs e) {
174 splitContainer.Panel2Collapsed = !showPlot.Value;
175 treeView.Invalidate();
178 showValue = new UserOption("valueMenuItem", true, valueMenuItem, settings);
179 showValue.Changed += delegate(object sender, EventArgs e) {
180 treeView.Columns[1].IsVisible = showValue.Value;
183 showMin = new UserOption("minMenuItem", false, minMenuItem, settings);
184 showMin.Changed += delegate(object sender, EventArgs e) {
185 treeView.Columns[2].IsVisible = showMin.Value;
188 showMax = new UserOption("maxMenuItem", true, maxMenuItem, settings);
189 showMax.Changed += delegate(object sender, EventArgs e) {
190 treeView.Columns[3].IsVisible = showMax.Value;
193 startMinimized = new UserOption("startMinMenuItem", false, startMinMenuItem, settings);
195 minimizeToTray = new UserOption("minTrayMenuItem", true, minTrayMenuItem, settings);
196 minimizeToTray.Changed += delegate(object sender, EventArgs e) {
197 systemTray.IsMainIconEnabled = minimizeToTray.Value;
200 minimizeOnClose = new UserOption("minCloseMenuItem", false, minCloseMenuItem, settings);
202 autoStart = new UserOption(null, startupManager.Startup, startupMenuItem, settings);
203 autoStart.Changed += delegate(object sender, EventArgs e) {
205 startupManager.Startup = autoStart.Value;
206 } catch (InvalidOperationException) {
207 MessageBox.Show("Updating the auto-startup option failed.", "Error",
208 MessageBoxButtons.OK, MessageBoxIcon.Error);
209 autoStart.Value = startupManager.Startup;
213 readHddSensors = new UserOption("hddMenuItem", true, hddMenuItem, settings);
214 readHddSensors.Changed += delegate(object sender, EventArgs e) {
215 computer.HDDEnabled = readHddSensors.Value;
216 UpdatePlotSelection(null, null);
219 showGadget = new UserOption("gadgetMenuItem", false, gadgetMenuItem, settings);
220 showGadget.Changed += delegate(object sender, EventArgs e) {
221 gadget.Visible = showGadget.Value;
224 celciusMenuItem.Checked =
225 unitManager.TemperatureUnit == TemperatureUnit.Celcius;
226 fahrenheitMenuItem.Checked = !celciusMenuItem.Checked;
228 startupMenuItem.Visible = startupManager.IsAvailable;
230 if (startMinMenuItem.Checked) {
231 if (!minTrayMenuItem.Checked) {
232 WindowState = FormWindowState.Minimized;
239 // Create a handle, otherwise calling Close() does not fire FormClosed
240 IntPtr handle = Handle;
242 // Make sure the settings are saved when the user logs off
243 Microsoft.Win32.SystemEvents.SessionEnded +=
244 delegate(object sender, Microsoft.Win32.SessionEndedEventArgs e) {
249 private void SubHardwareAdded(IHardware hardware, Node node) {
250 Node hardwareNode = new HardwareNode(hardware, settings, unitManager);
251 node.Nodes.Add(hardwareNode);
252 foreach (IHardware subHardware in hardware.SubHardware)
253 SubHardwareAdded(subHardware, hardwareNode);
256 private void HardwareAdded(IHardware hardware) {
257 Node hardwareNode = new HardwareNode(hardware, settings, unitManager);
258 root.Nodes.Add(hardwareNode);
259 foreach (IHardware subHardware in hardware.SubHardware)
260 SubHardwareAdded(subHardware, hardwareNode);
263 private void HardwareRemoved(IHardware hardware) {
264 List<Node> nodesToRemove = new List<Node>();
265 foreach (Node node in root.Nodes) {
266 HardwareNode hardwareNode = node as HardwareNode;
267 if (hardwareNode != null && hardwareNode.Hardware == hardware)
268 nodesToRemove.Add(node);
270 foreach (Node node in nodesToRemove)
271 root.Nodes.Remove(node);
274 private void nodeTextBoxText_DrawText(object sender, DrawEventArgs e) {
275 Node node = e.Node.Tag as Node;
278 if (node.IsVisible) {
279 SensorNode sensorNode = node as SensorNode;
280 if (plotMenuItem.Checked && sensorNode != null &&
281 sensorPlotColors.TryGetValue(sensorNode.Sensor, out color))
284 e.TextColor = Color.DarkGray;
289 private void UpdatePlotSelection(object sender,
292 List<ISensor> selected = new List<ISensor>();
293 IDictionary<ISensor, Color> colors = new Dictionary<ISensor, Color>();
295 foreach (TreeNodeAdv node in treeView.AllNodes) {
296 SensorNode sensorNode = node.Tag as SensorNode;
297 if (sensorNode != null &&
298 sensorNode.Sensor.SensorType == SensorType.Temperature) {
299 if (sensorNode.Plot) {
300 colors.Add(sensorNode.Sensor,
301 plotColorPalette[colorIndex % plotColorPalette.Length]);
302 selected.Add(sensorNode.Sensor);
307 sensorPlotColors = colors;
308 plotPanel.SetSensors(selected, colors);
311 private void nodeTextBoxText_EditorShowing(object sender, CancelEventArgs e)
313 e.Cancel = !(treeView.CurrentNode != null &&
314 treeView.CurrentNode.Tag is SensorNode);
317 private void nodeCheckBox_IsVisibleValueNeeded(object sender,
318 NodeControlValueEventArgs e) {
319 SensorNode node = e.Node.Tag as SensorNode;
320 e.Value = (node != null) &&
321 (node.Sensor.SensorType == SensorType.Temperature) &&
322 plotMenuItem.Checked;
325 private void exitClick(object sender, EventArgs e) {
329 private void timer_Tick(object sender, EventArgs e) {
330 computer.Accept(updateVisitor);
331 treeView.Invalidate();
332 plotPanel.Invalidate();
337 private void SaveConfiguration() {
338 if (WindowState != FormWindowState.Minimized) {
339 settings.SetValue("mainForm.Location.X", Location.X);
340 settings.SetValue("mainForm.Location.Y", Location.Y);
341 settings.SetValue("mainForm.Width", ClientSize.Width);
342 settings.SetValue("mainForm.Height", ClientSize.Height);
345 foreach (TreeColumn column in treeView.Columns)
346 settings.SetValue("treeView.Columns." + column.Header + ".Width",
349 settings.Save(Path.ChangeExtension(
350 System.Windows.Forms.Application.ExecutablePath, ".config"));
353 private void MainForm_FormClosed(object sender, FormClosedEventArgs e) {
357 timer.Enabled = false;
358 systemTray.Dispose();
362 private void aboutMenuItem_Click(object sender, EventArgs e) {
363 new AboutBox().ShowDialog();
366 private void treeView_Click(object sender, EventArgs e) {
368 MouseEventArgs m = e as MouseEventArgs;
369 if (m == null || m.Button != MouseButtons.Right)
372 NodeControlInfo info = treeView.GetNodeControlInfoAt(new Point(m.X, m.Y));
373 treeView.SelectedNode = info.Node;
374 if (info.Node != null) {
375 SensorNode node = info.Node.Tag as SensorNode;
376 if (node != null && node.Sensor != null) {
377 sensorContextMenu.MenuItems.Clear();
378 if (node.Sensor.Parameters.Length > 0) {
379 MenuItem item = new MenuItem("Parameters...");
380 item.Click += delegate(object obj, EventArgs args) {
381 ShowParameterForm(node.Sensor);
383 sensorContextMenu.MenuItems.Add(item);
385 if (nodeTextBoxText.EditEnabled) {
386 MenuItem item = new MenuItem("Rename");
387 item.Click += delegate(object obj, EventArgs args) {
388 nodeTextBoxText.BeginEdit();
390 sensorContextMenu.MenuItems.Add(item);
392 if (node.IsVisible) {
393 MenuItem item = new MenuItem("Hide");
394 item.Click += delegate(object obj, EventArgs args) {
395 node.IsVisible = false;
397 sensorContextMenu.MenuItems.Add(item);
399 MenuItem item = new MenuItem("Unhide");
400 item.Click += delegate(object obj, EventArgs args) {
401 node.IsVisible = true;
403 sensorContextMenu.MenuItems.Add(item);
405 sensorContextMenu.MenuItems.Add(new MenuItem("-"));
407 MenuItem item = new MenuItem("Show in Tray");
408 item.Checked = systemTray.Contains(node.Sensor);
409 item.Click += delegate(object obj, EventArgs args) {
411 systemTray.Remove(node.Sensor);
413 systemTray.Add(node.Sensor, true);
415 sensorContextMenu.MenuItems.Add(item);
418 MenuItem item = new MenuItem("Show in Gadget");
419 item.Checked = gadget.Contains(node.Sensor);
420 item.Click += delegate(object obj, EventArgs args) {
422 gadget.Remove(node.Sensor);
424 gadget.Add(node.Sensor);
427 sensorContextMenu.MenuItems.Add(item);
430 sensorContextMenu.Show(treeView, new Point(m.X, m.Y));
435 private void saveReportMenuItem_Click(object sender, EventArgs e) {
436 string report = computer.GetReport();
437 if (saveFileDialog.ShowDialog() == DialogResult.OK) {
438 using (TextWriter w = new StreamWriter(saveFileDialog.FileName)) {
444 private void SysTrayHideShow() {
450 protected override void WndProc(ref Message m) {
451 const int WM_SYSCOMMAND = 0x112;
452 const int SC_MINIMIZE = 0xF020;
453 const int SC_CLOSE = 0xF060;
455 if (minimizeToTray.Value &&
456 m.Msg == WM_SYSCOMMAND && m.WParam.ToInt32() == SC_MINIMIZE) {
458 } else if(minimizeOnClose.Value &&
459 m.Msg == WM_SYSCOMMAND && m.WParam.ToInt32() == SC_CLOSE) {
461 * Apparently the user wants to minimize rather than close
462 * Now we still need to check if we're going to the tray or not
464 * Note: the correct way to do this would be to send out SC_MINIMIZE,
465 * but since the code here is so simple,
466 * that would just be a waste of time.
468 if (minimizeToTray.Value)
471 WindowState = FormWindowState.Minimized;
477 private void hideShowClick(object sender, EventArgs e) {
481 private void removeMenuItem_Click(object sender, EventArgs e) {
482 MenuItem item = sender as MenuItem;
486 ISensor sensor = item.Parent.Tag as ISensor;
490 systemTray.Remove(sensor);
493 private void ShowParameterForm(ISensor sensor) {
494 ParameterForm form = new ParameterForm();
495 form.Parameters = sensor.Parameters;
496 form.captionLabel.Text = sensor.Name;
500 private void treeView_NodeMouseDoubleClick(object sender,
501 TreeNodeAdvMouseEventArgs e) {
502 SensorNode node = e.Node.Tag as SensorNode;
503 if (node != null && node.Sensor != null &&
504 node.Sensor.Parameters.Length > 0) {
505 ShowParameterForm(node.Sensor);
509 private void celciusMenuItem_Click(object sender, EventArgs e) {
510 celciusMenuItem.Checked = true;
511 fahrenheitMenuItem.Checked = false;
512 unitManager.TemperatureUnit = TemperatureUnit.Celcius;
515 private void fahrenheitMenuItem_Click(object sender, EventArgs e) {
516 celciusMenuItem.Checked = false;
517 fahrenheitMenuItem.Checked = true;
518 unitManager.TemperatureUnit = TemperatureUnit.Fahrenheit;
521 private void sumbitReportMenuItem_Click(object sender, EventArgs e)
523 ReportForm form = new ReportForm();
524 form.Report = computer.GetReport();
528 private void resetMinMaxMenuItem_Click(object sender, EventArgs e) {
529 computer.Accept(new SensorVisitor(delegate(ISensor sensor) {