GUI/MainForm.cs
author moel.mich
Tue, 09 Mar 2010 22:27:10 +0000
changeset 79 9cdbe1d8d12a
parent 70 dc69dc4d7512
child 82 91edecb084a1
permissions -rw-r--r--
Changed the CPU clock calculation. If no invariant TSC is available, then the max CPU clock is estimated at startup under load, otherwise an average over one second is used.
moel@1
     1
/*
moel@1
     2
  
moel@1
     3
  Version: MPL 1.1/GPL 2.0/LGPL 2.1
moel@1
     4
moel@1
     5
  The contents of this file are subject to the Mozilla Public License Version
moel@1
     6
  1.1 (the "License"); you may not use this file except in compliance with
moel@1
     7
  the License. You may obtain a copy of the License at
moel@1
     8
 
moel@1
     9
  http://www.mozilla.org/MPL/
moel@1
    10
moel@1
    11
  Software distributed under the License is distributed on an "AS IS" basis,
moel@1
    12
  WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
moel@1
    13
  for the specific language governing rights and limitations under the License.
moel@1
    14
moel@1
    15
  The Original Code is the Open Hardware Monitor code.
moel@1
    16
moel@1
    17
  The Initial Developer of the Original Code is 
moel@1
    18
  Michael Möller <m.moeller@gmx.ch>.
moel@1
    19
  Portions created by the Initial Developer are Copyright (C) 2009-2010
moel@1
    20
  the Initial Developer. All Rights Reserved.
moel@1
    21
moel@1
    22
  Contributor(s):
moel@1
    23
moel@1
    24
  Alternatively, the contents of this file may be used under the terms of
moel@1
    25
  either the GNU General Public License Version 2 or later (the "GPL"), or
moel@1
    26
  the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
moel@1
    27
  in which case the provisions of the GPL or the LGPL are applicable instead
moel@1
    28
  of those above. If you wish to allow use of your version of this file only
moel@1
    29
  under the terms of either the GPL or the LGPL, and not to allow others to
moel@1
    30
  use your version of this file under the terms of the MPL, indicate your
moel@1
    31
  decision by deleting the provisions above and replace them with the notice
moel@1
    32
  and other provisions required by the GPL or the LGPL. If you do not delete
moel@1
    33
  the provisions above, a recipient may use your version of this file under
moel@1
    34
  the terms of any one of the MPL, the GPL or the LGPL.
moel@1
    35
 
moel@1
    36
*/
moel@1
    37
moel@1
    38
using System;
moel@1
    39
using System.Collections.Generic;
moel@1
    40
using System.ComponentModel;
moel@1
    41
using System.Configuration;
moel@1
    42
using System.Drawing;
moel@1
    43
using System.Text;
moel@1
    44
using System.Windows.Forms;
moel@1
    45
using Aga.Controls.Tree;
moel@1
    46
using Aga.Controls.Tree.NodeControls;
moel@1
    47
using OpenHardwareMonitor.Hardware;
moel@28
    48
using OpenHardwareMonitor.Utilities;
moel@1
    49
moel@1
    50
namespace OpenHardwareMonitor.GUI {
moel@1
    51
  public partial class MainForm : Form {
moel@1
    52
moel@28
    53
    private Computer computer = new Computer();
moel@1
    54
    private Node root;
moel@1
    55
    private TreeModel treeModel;
moel@1
    56
    private IDictionary<ISensor, Color> sensorPlotColors = 
moel@1
    57
      new Dictionary<ISensor, Color>();
moel@1
    58
    private Color[] plotColorPalette;
moel@40
    59
    private SensorSystemTray sensorSystemTray;
moel@40
    60
    private NotifyIcon notifyIcon;
moel@1
    61
moel@28
    62
    public MainForm() {      
moel@1
    63
      InitializeComponent();
moel@1
    64
      this.Font = SystemFonts.MessageBoxFont;
moel@1
    65
      treeView.Font = SystemFonts.MessageBoxFont;
moel@63
    66
      plotPanel.Font = SystemFonts.MessageBoxFont;
moel@1
    67
      
moel@1
    68
      nodeCheckBox.IsVisibleValueNeeded += 
moel@1
    69
        new EventHandler<NodeControlValueEventArgs>(
moel@1
    70
          nodeCheckBox_IsVisibleValueNeeded);
moel@1
    71
      nodeCheckBox.CheckStateChanged += 
moel@1
    72
        new EventHandler<TreePathEventArgs>(UpdatePlotSelection);
moel@1
    73
      nodeTextBoxText.DrawText += 
moel@1
    74
        new EventHandler<DrawEventArgs>(nodeTextBoxText_DrawText);
moel@1
    75
      nodeTextBoxValue.DrawText +=
moel@1
    76
        new EventHandler<DrawEventArgs>(nodeTextBoxText_DrawText);
moel@1
    77
      nodeTextBoxMin.DrawText +=
moel@1
    78
        new EventHandler<DrawEventArgs>(nodeTextBoxText_DrawText);
moel@1
    79
      nodeTextBoxMax.DrawText +=
moel@1
    80
        new EventHandler<DrawEventArgs>(nodeTextBoxText_DrawText);
moel@1
    81
      nodeTextBoxLimit.DrawText += 
moel@1
    82
        new EventHandler<DrawEventArgs>(nodeTextBoxLimit_DrawText);
moel@1
    83
moel@1
    84
      if (Utilities.Config.Contains("mainForm.Location.X")) {
moel@1
    85
        int x = Utilities.Config.Get("mainForm.Location.X", Location.X);
moel@1
    86
        x = x < 0 ? 0 : x;
moel@1
    87
        int y = Utilities.Config.Get("mainForm.Location.Y", Location.Y);
moel@1
    88
        y = y < 0 ? 0 : y;
moel@1
    89
        this.Location = new Point(x, y);
moel@1
    90
      } else {
moel@1
    91
        StartPosition = FormStartPosition.CenterScreen;
moel@1
    92
      }
moel@1
    93
moel@1
    94
      Width = Utilities.Config.Get("mainForm.Width", Width);
moel@1
    95
      Height = Utilities.Config.Get("mainForm.Height", Height);
moel@1
    96
         
moel@1
    97
      treeModel = new TreeModel();
moel@1
    98
      root = new Node(System.Environment.MachineName);
moel@1
    99
      root.Image = Utilities.EmbeddedResources.GetImage("computer.png");
moel@1
   100
      
moel@1
   101
      treeModel.Nodes.Add(root);
moel@1
   102
      treeView.Model = treeModel;
moel@40
   103
      
moel@40
   104
      notifyIcon = new NotifyIcon();
moel@40
   105
      notifyIcon.ContextMenuStrip = this.notifyContextMenuStrip;
moel@40
   106
      notifyIcon.Icon = EmbeddedResources.GetIcon("smallicon.ico");
moel@40
   107
      notifyIcon.Text = "Open Hardware Monitor";      
moel@40
   108
      notifyIcon.DoubleClick += new EventHandler(this.restoreClick);
moel@40
   109
moel@40
   110
      sensorSystemTray = new SensorSystemTray(computer);
moel@1
   111
moel@28
   112
      computer.HardwareAdded += new HardwareEventHandler(HardwareAdded);
moel@28
   113
      computer.HardwareRemoved += new HardwareEventHandler(HardwareRemoved);
moel@28
   114
      computer.Open();
moel@28
   115
moel@1
   116
      plotColorPalette = new Color[14];
moel@1
   117
      plotColorPalette[0] = Color.Blue;
moel@1
   118
      plotColorPalette[1] = Color.OrangeRed;
moel@1
   119
      plotColorPalette[2] = Color.Green;
moel@1
   120
      plotColorPalette[3] = Color.LightSeaGreen;
moel@1
   121
      plotColorPalette[4] = Color.Goldenrod;
moel@1
   122
      plotColorPalette[5] = Color.DarkViolet;
moel@1
   123
      plotColorPalette[6] = Color.YellowGreen;
moel@1
   124
      plotColorPalette[7] = Color.SaddleBrown;
moel@1
   125
      plotColorPalette[8] = Color.Gray;
moel@1
   126
      plotColorPalette[9] = Color.RoyalBlue;
moel@1
   127
      plotColorPalette[10] = Color.DeepPink;
moel@1
   128
      plotColorPalette[11] = Color.MediumSeaGreen;
moel@1
   129
      plotColorPalette[12] = Color.Olive;
moel@1
   130
      plotColorPalette[13] = Color.Firebrick;
moel@1
   131
moel@28
   132
      plotMenuItem.Checked = Config.Get(plotMenuItem.Name, false);
moel@28
   133
      minMenuItem.Checked = Config.Get(minMenuItem.Name, false);
moel@28
   134
      maxMenuItem.Checked = Config.Get(maxMenuItem.Name, true);
moel@28
   135
      limitMenuItem.Checked = Config.Get(limitMenuItem.Name, false);
moel@1
   136
moel@55
   137
      startMinMenuItem.Checked = Config.Get(startMinMenuItem.Name, false); 
moel@28
   138
      minTrayMenuItem.Checked = Config.Get(minTrayMenuItem.Name, true);
moel@28
   139
      hddMenuItem.Checked = Config.Get(hddMenuItem.Name, true);
moel@1
   140
moel@28
   141
      voltMenuItem.Checked = Config.Get(voltMenuItem.Name, true);
moel@28
   142
      clocksMenuItem.Checked = Config.Get(clocksMenuItem.Name, true);
moel@28
   143
      loadMenuItem.Checked = Config.Get(loadMenuItem.Name, true);
moel@28
   144
      tempMenuItem.Checked = Config.Get(tempMenuItem.Name, true);
moel@28
   145
      fansMenuItem.Checked = Config.Get(fansMenuItem.Name, true);
moel@57
   146
      flowsMenuItem.Checked = Config.Get(flowsMenuItem.Name, true);
moel@28
   147
     
moel@55
   148
      timer.Enabled = true;
moel@55
   149
moel@55
   150
      if (startMinMenuItem.Checked) {
moel@55
   151
        if (minTrayMenuItem.Checked) {
moel@55
   152
          notifyIcon.Visible = true;
moel@55
   153
        } else {
moel@55
   154
          WindowState = FormWindowState.Minimized;
moel@55
   155
          Show();
moel@55
   156
        }
moel@55
   157
      } else {
moel@55
   158
        Show();
moel@55
   159
      }
moel@70
   160
moel@71
   161
      // Create a handle, otherwise calling Close() does not fire FormClosed     
moel@71
   162
      IntPtr handle = Handle;
moel@1
   163
    }
moel@1
   164
moel@64
   165
    private void SubHardwareAdded(IHardware hardware, Node node) {
moel@64
   166
      Node hardwareNode = new HardwareNode(hardware);
moel@64
   167
      node.Nodes.Add(hardwareNode);
moel@64
   168
      foreach (IHardware subHardware in hardware.SubHardware)
moel@64
   169
        SubHardwareAdded(subHardware, hardwareNode);  
moel@64
   170
    }
moel@64
   171
moel@28
   172
    private void HardwareAdded(IHardware hardware) {
moel@64
   173
      Node hardwareNode = new HardwareNode(hardware);
moel@64
   174
      root.Nodes.Add(hardwareNode);
moel@64
   175
      foreach (IHardware subHardware in hardware.SubHardware)
moel@64
   176
        SubHardwareAdded(subHardware, hardwareNode);     
moel@1
   177
    }
moel@1
   178
moel@28
   179
    private void HardwareRemoved(IHardware hardware) {      
moel@1
   180
      List<Node> nodesToRemove = new List<Node>();
moel@28
   181
      foreach (Node node in root.Nodes) {
moel@28
   182
        HardwareNode hardwareNode = node as HardwareNode;
moel@28
   183
        if (hardwareNode != null && hardwareNode.Hardware == hardware)
moel@28
   184
          nodesToRemove.Add(node);
moel@28
   185
      }
moel@1
   186
      foreach (Node node in nodesToRemove)
moel@1
   187
        root.Nodes.Remove(node);
moel@1
   188
    }
moel@1
   189
moel@1
   190
    private void nodeTextBoxLimit_DrawText(object sender, DrawEventArgs e) {
moel@1
   191
      SensorNode sensorNode = e.Node.Tag as SensorNode;
moel@1
   192
      if (sensorNode != null) 
moel@1
   193
        e.Text = sensorNode.ValueToString(sensorNode.Sensor.Limit);
moel@1
   194
    }
moel@1
   195
moel@1
   196
    private void nodeTextBoxText_DrawText(object sender, DrawEventArgs e) {
moel@1
   197
      if (!plotMenuItem.Checked)
moel@1
   198
        return;      
moel@1
   199
moel@1
   200
      SensorNode sensorNode = e.Node.Tag as SensorNode;
moel@1
   201
      if (sensorNode != null) {
moel@1
   202
        Color color;
moel@1
   203
        if (sensorPlotColors.TryGetValue(sensorNode.Sensor, out color)) 
moel@1
   204
          e.TextColor = color;        
moel@1
   205
      }
moel@1
   206
    }
moel@1
   207
moel@1
   208
    private void UpdatePlotSelection(object sender, 
moel@1
   209
      TreePathEventArgs e) 
moel@1
   210
    {
moel@1
   211
      List<ISensor> selected = new List<ISensor>();
moel@1
   212
      IDictionary<ISensor, Color> colors = new Dictionary<ISensor, Color>();
moel@1
   213
      int colorIndex = 0;
moel@1
   214
      foreach (TreeNodeAdv node in treeView.AllNodes) {
moel@1
   215
        SensorNode sensorNode = node.Tag as SensorNode;
moel@1
   216
        if (sensorNode != null && 
moel@1
   217
          sensorNode.Sensor.SensorType == SensorType.Temperature) {
moel@1
   218
          if (sensorNode.Plot) {
moel@1
   219
            colors.Add(sensorNode.Sensor,
moel@1
   220
              plotColorPalette[colorIndex % plotColorPalette.Length]);
moel@1
   221
            selected.Add(sensorNode.Sensor);
moel@1
   222
          }
moel@1
   223
          colorIndex++;
moel@1
   224
        }
moel@1
   225
      }
moel@1
   226
      sensorPlotColors = colors;
moel@1
   227
      plotPanel.SetSensors(selected, colors);
moel@1
   228
    }
moel@1
   229
moel@1
   230
    private void nodeCheckBox_IsVisibleValueNeeded(object sender, 
moel@1
   231
      NodeControlValueEventArgs e) {
moel@1
   232
      SensorNode node = e.Node.Tag as SensorNode;
moel@1
   233
      e.Value = (node != null) && 
moel@1
   234
        (node.Sensor.SensorType == SensorType.Temperature) && 
moel@1
   235
        plotMenuItem.Checked;
moel@1
   236
    }
moel@1
   237
moel@1
   238
    private void exitToolStripMenuItem_Click(object sender, EventArgs e) {
moel@70
   239
      Close();      
moel@1
   240
    }
moel@1
   241
moel@1
   242
    private void timer_Tick(object sender, EventArgs e) {
moel@1
   243
      
moel@1
   244
      #if !DEBUG
moel@1
   245
      try {
moel@1
   246
      #endif
moel@28
   247
        computer.Update();        
moel@1
   248
      #if !DEBUG
moel@1
   249
      } catch (Exception exception) {
moel@28
   250
        CrashReport.Save(exception);
moel@1
   251
        Close();
moel@1
   252
      }
moel@1
   253
      #endif
moel@1
   254
            
moel@1
   255
      treeView.Invalidate();
moel@1
   256
      plotPanel.Invalidate();
moel@40
   257
      sensorSystemTray.Redraw();
moel@1
   258
    }
moel@1
   259
moel@1
   260
    private void MainForm_FormClosed(object sender, FormClosedEventArgs e) {
moel@28
   261
            
moel@28
   262
      Config.Set(plotMenuItem.Name, plotMenuItem.Checked);
moel@28
   263
      Config.Set(minMenuItem.Name, minMenuItem.Checked);
moel@28
   264
      Config.Set(maxMenuItem.Name, maxMenuItem.Checked);
moel@28
   265
      Config.Set(limitMenuItem.Name, limitMenuItem.Checked);
moel@1
   266
moel@55
   267
      Config.Set(startMinMenuItem.Name, startMinMenuItem.Checked);
moel@28
   268
      Config.Set(minTrayMenuItem.Name, minTrayMenuItem.Checked);
moel@28
   269
      Config.Set(hddMenuItem.Name, hddMenuItem.Checked);
moel@28
   270
moel@28
   271
      Config.Set(voltMenuItem.Name, voltMenuItem.Checked);
moel@28
   272
      Config.Set(clocksMenuItem.Name, clocksMenuItem.Checked);
moel@28
   273
      Config.Set(loadMenuItem.Name, loadMenuItem.Checked);
moel@28
   274
      Config.Set(tempMenuItem.Name, tempMenuItem.Checked);
moel@28
   275
      Config.Set(fansMenuItem.Name, fansMenuItem.Checked);
moel@57
   276
      Config.Set(flowsMenuItem.Name, flowsMenuItem.Checked);
moel@1
   277
moel@14
   278
      if (WindowState != FormWindowState.Minimized) {
moel@28
   279
        Config.Set("mainForm.Location.X", Location.X);
moel@28
   280
        Config.Set("mainForm.Location.Y", Location.Y);
moel@28
   281
        Config.Set("mainForm.Width", Width);
moel@28
   282
        Config.Set("mainForm.Height", Height);
moel@14
   283
      }
moel@42
   284
           
moel@40
   285
      sensorSystemTray.Dispose();
moel@40
   286
      notifyIcon.Dispose();
moel@28
   287
      computer.Close();
moel@1
   288
    }
moel@1
   289
moel@1
   290
    private void aboutToolStripMenuItem_Click(object sender, EventArgs e) {
moel@1
   291
      new AboutBox().ShowDialog();
moel@1
   292
    }
moel@1
   293
moel@1
   294
    private void plotToolStripMenuItem_CheckedChanged(object sender, 
moel@1
   295
      EventArgs e) 
moel@1
   296
    {
moel@1
   297
      splitContainer.Panel2Collapsed = !plotMenuItem.Checked;
moel@1
   298
      treeView.Invalidate();
moel@1
   299
    }
moel@1
   300
moel@1
   301
    private void valueToolStripMenuItem_CheckedChanged(object sender, 
moel@1
   302
      EventArgs e) 
moel@1
   303
    {
moel@1
   304
      treeView.Columns[1].IsVisible = valueToolStripMenuItem.Checked;
moel@1
   305
    }
moel@1
   306
moel@1
   307
    private void minToolStripMenuItem_CheckedChanged(object sender, EventArgs e) 
moel@1
   308
    {
moel@1
   309
      treeView.Columns[2].IsVisible = minMenuItem.Checked;
moel@1
   310
    }
moel@1
   311
moel@1
   312
    private void maxToolStripMenuItem_CheckedChanged(object sender, EventArgs e) 
moel@1
   313
    {
moel@1
   314
      treeView.Columns[3].IsVisible = maxMenuItem.Checked;
moel@1
   315
    }
moel@1
   316
moel@1
   317
    private void limitToolStripMenuItem_CheckedChanged(object sender, 
moel@1
   318
      EventArgs e) {
moel@1
   319
      treeView.Columns[4].IsVisible = limitMenuItem.Checked;
moel@1
   320
    }
moel@1
   321
moel@1
   322
    private void treeView_Click(object sender, EventArgs e) {
moel@1
   323
      
moel@1
   324
      MouseEventArgs m = e as MouseEventArgs;
moel@1
   325
      if (m == null || m.Button != MouseButtons.Right)
moel@1
   326
        return;
moel@1
   327
moel@1
   328
      NodeControlInfo info = treeView.GetNodeControlInfoAt(new Point(m.X, m.Y));
moel@28
   329
      if (info.Control == null) {
moel@1
   330
        columnsContextMenuStrip.Show(treeView, m.X, m.Y);
moel@40
   331
      } else {
moel@40
   332
        SensorNode node = info.Node.Tag as SensorNode;
moel@40
   333
        if (node != null && node.Sensor != null) {
moel@40
   334
moel@40
   335
          sensorContextMenuStrip.Items.Clear();
moel@63
   336
          if (node.Sensor.Parameters.Length > 0) {
moel@63
   337
            ToolStripMenuItem item = new ToolStripMenuItem("Parameters...");
moel@63
   338
            item.Click += delegate(object obj, EventArgs args) {
moel@63
   339
              ShowParameterForm(node.Sensor);
moel@63
   340
            };
moel@63
   341
            sensorContextMenuStrip.Items.Add(item);
moel@63
   342
          }
moel@40
   343
          if (sensorSystemTray.Contains(node.Sensor)) {
moel@40
   344
            ToolStripMenuItem item = new ToolStripMenuItem("Remove From Tray");
moel@40
   345
            item.Click += delegate(object obj, EventArgs args) {
moel@40
   346
              sensorSystemTray.Remove(node.Sensor);
moel@40
   347
            };
moel@40
   348
            sensorContextMenuStrip.Items.Add(item);
moel@40
   349
          } else {
moel@40
   350
            ToolStripMenuItem item = new ToolStripMenuItem("Add To Tray");
moel@40
   351
            item.Click += delegate(object obj, EventArgs args) {
moel@42
   352
              sensorSystemTray.Add(node.Sensor, true);
moel@40
   353
            };
moel@40
   354
            sensorContextMenuStrip.Items.Add(item);
moel@40
   355
          }
moel@40
   356
          sensorContextMenuStrip.Show(treeView, m.X, m.Y);
moel@40
   357
        }
moel@40
   358
      }
moel@1
   359
    }
moel@1
   360
moel@1
   361
    private void saveReportToolStripMenuItem_Click(object sender, EventArgs e) {
moel@28
   362
      computer.SaveReport(new Version(Application.ProductVersion));      
moel@1
   363
    }
moel@1
   364
moel@1
   365
    private void hddsensorsToolStripMenuItem_CheckedChanged(object sender, 
moel@1
   366
      EventArgs e) 
moel@1
   367
    {
moel@28
   368
      computer.HDDEnabled = hddMenuItem.Checked;
moel@28
   369
      UpdateSensorTypeChecked(null, null);
moel@28
   370
      UpdatePlotSelection(null, null);      
moel@1
   371
    }
moel@1
   372
moel@64
   373
    private void UpdateSensorTypeVisible(Node node) {
moel@64
   374
      HardwareNode hardwareNode = node as HardwareNode;
moel@64
   375
      if (hardwareNode == null)
moel@64
   376
        return;
moel@64
   377
moel@64
   378
      hardwareNode.SetVisible(SensorType.Voltage, voltMenuItem.Checked);
moel@64
   379
      hardwareNode.SetVisible(SensorType.Clock, clocksMenuItem.Checked);
moel@64
   380
      hardwareNode.SetVisible(SensorType.Load, loadMenuItem.Checked);
moel@64
   381
      hardwareNode.SetVisible(SensorType.Temperature, tempMenuItem.Checked);
moel@64
   382
      hardwareNode.SetVisible(SensorType.Fan, fansMenuItem.Checked);
moel@64
   383
      hardwareNode.SetVisible(SensorType.Flow, flowsMenuItem.Checked);
moel@64
   384
moel@64
   385
      foreach (Node n in node.Nodes)
moel@64
   386
        UpdateSensorTypeVisible(n);
moel@64
   387
    }
moel@64
   388
moel@64
   389
    private void UpdateSensorTypeChecked(object sender, EventArgs e) {          
moel@64
   390
      foreach (HardwareNode node in root.Nodes) 
moel@64
   391
        UpdateSensorTypeVisible(node);
moel@27
   392
    }
moel@27
   393
moel@27
   394
    private void ToggleSysTray() {
moel@55
   395
      if (notifyIcon.Visible) {
moel@27
   396
        Visible = true;
moel@27
   397
        notifyIcon.Visible = false;
moel@55
   398
        Activate(); 
moel@55
   399
      } else {
moel@55
   400
        notifyIcon.Visible = true;
moel@55
   401
        Visible = false;           
moel@27
   402
      }
moel@27
   403
    }
moel@27
   404
moel@27
   405
    protected override void WndProc(ref Message m) {
moel@27
   406
      const int WM_SYSCOMMAND = 0x112;
moel@27
   407
      const int SC_MINIMIZE = 0xF020;
moel@28
   408
      if (minTrayMenuItem.Checked && 
moel@28
   409
        m.Msg == WM_SYSCOMMAND && m.WParam.ToInt32() == SC_MINIMIZE) {
moel@27
   410
        ToggleSysTray();
moel@27
   411
      } else {      
moel@27
   412
        base.WndProc(ref m);
moel@27
   413
      }
moel@27
   414
    }
moel@27
   415
moel@28
   416
    private void restoreClick(object sender, EventArgs e) {
moel@28
   417
      ToggleSysTray();
moel@27
   418
    }
moel@27
   419
moel@40
   420
    private void removeToolStripMenuItem_Click(object sender, EventArgs e) {
moel@40
   421
      ToolStripMenuItem item = sender as ToolStripMenuItem;
moel@40
   422
      if (item == null)
moel@40
   423
        return;
moel@40
   424
moel@40
   425
      ISensor sensor = item.Owner.Tag as ISensor;
moel@40
   426
      if (sensor == null)
moel@40
   427
        return;
moel@40
   428
moel@40
   429
      sensorSystemTray.Remove(sensor);
moel@40
   430
    }
moel@63
   431
moel@63
   432
    private void ShowParameterForm(ISensor sensor) {
moel@63
   433
      ParameterForm form = new ParameterForm();
moel@63
   434
      form.Parameters = sensor.Parameters;
moel@63
   435
      form.captionLabel.Text = sensor.Name;
moel@63
   436
      form.ShowDialog();
moel@63
   437
    }
moel@63
   438
moel@63
   439
    private void treeView_NodeMouseDoubleClick(object sender, 
moel@63
   440
      TreeNodeAdvMouseEventArgs e) {
moel@63
   441
      SensorNode node = e.Node.Tag as SensorNode;
moel@63
   442
      if (node != null && node.Sensor != null && 
moel@63
   443
        node.Sensor.Parameters.Length > 0) {
moel@63
   444
        ShowParameterForm(node.Sensor);
moel@63
   445
      }
moel@63
   446
    }
moel@1
   447
  }
moel@1
   448
}