GUI/SensorFrontView.cs
author sl
Sun, 03 Feb 2013 18:01:50 +0100
changeset 391 ca4c0e7ae75d
child 396 21a9e2325617
permissions -rw-r--r--
Converted project to VisualStudio 2012.
Adding SoundGraphDisplay and SensorFrontView classes.
They were respectively based on SystemTray and SensorNotifyIcon.
SoundGraphDisplay is now able to load iMONDisplay.dll providing it lives on your PATH.
Adding option to sensor context menu for adding it into FrontView.
sl@391
     1
/*
sl@391
     2
 
sl@391
     3
  This Source Code Form is subject to the terms of the Mozilla Public
sl@391
     4
  License, v. 2.0. If a copy of the MPL was not distributed with this
sl@391
     5
  file, You can obtain one at http://mozilla.org/MPL/2.0/.
sl@391
     6
 
sl@391
     7
  Copyright (C) 2009-2012 Michael Möller <mmoeller@openhardwaremonitor.org>
sl@391
     8
	
sl@391
     9
*/
sl@391
    10
sl@391
    11
using System;
sl@391
    12
using System.Drawing;
sl@391
    13
using System.Drawing.Drawing2D;
sl@391
    14
using System.Drawing.Imaging;
sl@391
    15
using System.Drawing.Text;
sl@391
    16
using System.Runtime.InteropServices;
sl@391
    17
using System.Windows.Forms;
sl@391
    18
using OpenHardwareMonitor.Hardware;
sl@391
    19
using OpenHardwareMonitor.Utilities;
sl@391
    20
sl@391
    21
namespace OpenHardwareMonitor.GUI
sl@391
    22
{
sl@391
    23
    public class SensorFrontView : IDisposable
sl@391
    24
    {
sl@391
    25
sl@391
    26
        private UnitManager unitManager;
sl@391
    27
sl@391
    28
        private ISensor sensor;
sl@391
    29
        private Bitmap bitmap;
sl@391
    30
        private Graphics graphics;
sl@391
    31
        private Color color;
sl@391
    32
        private Color darkColor;
sl@391
    33
        private Brush brush;
sl@391
    34
        private Brush darkBrush;
sl@391
    35
        private Pen pen;
sl@391
    36
        private Font font;
sl@391
    37
        private Font smallFont;
sl@391
    38
sl@391
    39
        public SensorFrontView(SoundGraphDisplay soundGraphDisplay, ISensor sensor,
sl@391
    40
          bool balloonTip, PersistentSettings settings, UnitManager unitManager)
sl@391
    41
        {
sl@391
    42
            this.unitManager = unitManager;
sl@391
    43
            this.sensor = sensor;
sl@391
    44
       
sl@391
    45
            // get the default dpi to create an icon with the correct size
sl@391
    46
            float dpiX, dpiY;
sl@391
    47
            using (Bitmap b = new Bitmap(1, 1, PixelFormat.Format32bppArgb))
sl@391
    48
            {
sl@391
    49
                dpiX = b.HorizontalResolution;
sl@391
    50
                dpiY = b.VerticalResolution;
sl@391
    51
            }
sl@391
    52
sl@391
    53
            // adjust the size of the icon to current dpi (default is 16x16 at 96 dpi) 
sl@391
    54
            int width = (int)Math.Round(16 * dpiX / 96);
sl@391
    55
            int height = (int)Math.Round(16 * dpiY / 96);
sl@391
    56
sl@391
    57
            // make sure it does never get smaller than 16x16
sl@391
    58
            width = width < 16 ? 16 : width;
sl@391
    59
            height = height < 16 ? 16 : height;
sl@391
    60
sl@391
    61
            // adjust the font size to the icon size
sl@391
    62
            FontFamily family = SystemFonts.MessageBoxFont.FontFamily;
sl@391
    63
            float baseSize;
sl@391
    64
            switch (family.Name)
sl@391
    65
            {
sl@391
    66
                case "Segoe UI": baseSize = 12; break;
sl@391
    67
                case "Tahoma": baseSize = 11; break;
sl@391
    68
                default: baseSize = 12; break;
sl@391
    69
            }
sl@391
    70
sl@391
    71
            this.font = new Font(family,
sl@391
    72
              baseSize * width / 16.0f, GraphicsUnit.Pixel);
sl@391
    73
            this.smallFont = new Font(family,
sl@391
    74
              0.75f * baseSize * width / 16.0f, GraphicsUnit.Pixel);
sl@391
    75
sl@391
    76
            this.bitmap = new Bitmap(width, height, PixelFormat.Format32bppArgb);
sl@391
    77
            this.graphics = Graphics.FromImage(this.bitmap);
sl@391
    78
sl@391
    79
            if (Environment.OSVersion.Version.Major > 5)
sl@391
    80
            {
sl@391
    81
                this.graphics.TextRenderingHint = TextRenderingHint.ClearTypeGridFit;
sl@391
    82
                this.graphics.SmoothingMode = SmoothingMode.HighQuality;
sl@391
    83
            }
sl@391
    84
        }
sl@391
    85
sl@391
    86
        public ISensor Sensor
sl@391
    87
        {
sl@391
    88
            get { return sensor; }
sl@391
    89
        }
sl@391
    90
sl@391
    91
        public Color Color
sl@391
    92
        {
sl@391
    93
            get { return color; }
sl@391
    94
            set
sl@391
    95
            {
sl@391
    96
                this.color = value;
sl@391
    97
                this.darkColor = Color.FromArgb(255,
sl@391
    98
                  this.color.R / 3,
sl@391
    99
                  this.color.G / 3,
sl@391
   100
                  this.color.B / 3);
sl@391
   101
                Brush brush = this.brush;
sl@391
   102
                this.brush = new SolidBrush(this.color);
sl@391
   103
                if (brush != null)
sl@391
   104
                    brush.Dispose();
sl@391
   105
                Brush darkBrush = this.darkBrush;
sl@391
   106
                this.darkBrush = new SolidBrush(this.darkColor);
sl@391
   107
                if (darkBrush != null)
sl@391
   108
                    darkBrush.Dispose();
sl@391
   109
            }
sl@391
   110
        }
sl@391
   111
sl@391
   112
        public void Dispose()
sl@391
   113
        {
sl@391
   114
sl@391
   115
            if (brush != null)
sl@391
   116
                brush.Dispose();
sl@391
   117
            if (darkBrush != null)
sl@391
   118
                darkBrush.Dispose();
sl@391
   119
            pen.Dispose();
sl@391
   120
            graphics.Dispose();
sl@391
   121
            bitmap.Dispose();
sl@391
   122
            font.Dispose();
sl@391
   123
            smallFont.Dispose();
sl@391
   124
        }
sl@391
   125
sl@391
   126
        private string GetString()
sl@391
   127
        {
sl@391
   128
            if (!sensor.Value.HasValue)
sl@391
   129
                return "-";
sl@391
   130
sl@391
   131
            switch (sensor.SensorType)
sl@391
   132
            {
sl@391
   133
                case SensorType.Voltage:
sl@391
   134
                    return string.Format("{0:F1}", sensor.Value);
sl@391
   135
                case SensorType.Clock:
sl@391
   136
                    return string.Format("{0:F1}", 1e-3f * sensor.Value);
sl@391
   137
                case SensorType.Load:
sl@391
   138
                    return string.Format("{0:F0}", sensor.Value);
sl@391
   139
                case SensorType.Temperature:
sl@391
   140
                    if (unitManager.TemperatureUnit == TemperatureUnit.Fahrenheit)
sl@391
   141
                        return string.Format("{0:F0}",
sl@391
   142
                          UnitManager.CelsiusToFahrenheit(sensor.Value));
sl@391
   143
                    else
sl@391
   144
                        return string.Format("{0:F0}", sensor.Value);
sl@391
   145
                case SensorType.Fan:
sl@391
   146
                    return string.Format("{0:F1}", 1e-3f * sensor.Value);
sl@391
   147
                case SensorType.Flow:
sl@391
   148
                    return string.Format("{0:F1}", 1e-3f * sensor.Value);
sl@391
   149
                case SensorType.Control:
sl@391
   150
                    return string.Format("{0:F0}", sensor.Value);
sl@391
   151
                case SensorType.Level:
sl@391
   152
                    return string.Format("{0:F0}", sensor.Value);
sl@391
   153
                case SensorType.Power:
sl@391
   154
                    return string.Format("{0:F0}", sensor.Value);
sl@391
   155
                case SensorType.Data:
sl@391
   156
                    return string.Format("{0:F0}", sensor.Value);
sl@391
   157
                case SensorType.Factor:
sl@391
   158
                    return string.Format("{0:F1}", sensor.Value);
sl@391
   159
            }
sl@391
   160
            return "-";
sl@391
   161
        }
sl@391
   162
sl@391
   163
        private Icon CreateTransparentIcon()
sl@391
   164
        {
sl@391
   165
            string text = GetString();
sl@391
   166
            int count = 0;
sl@391
   167
            for (int i = 0; i < text.Length; i++)
sl@391
   168
                if ((text[i] >= '0' && text[i] <= '9') || text[i] == '-')
sl@391
   169
                    count++;
sl@391
   170
            bool small = count > 2;
sl@391
   171
sl@391
   172
            graphics.Clear(Color.Black);
sl@391
   173
            TextRenderer.DrawText(graphics, text, small ? smallFont : font,
sl@391
   174
              new Point(-2, small ? 1 : 0), Color.White, Color.Black);
sl@391
   175
sl@391
   176
            BitmapData data = bitmap.LockBits(
sl@391
   177
              new Rectangle(0, 0, bitmap.Width, bitmap.Height),
sl@391
   178
              ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);
sl@391
   179
sl@391
   180
            IntPtr Scan0 = data.Scan0;
sl@391
   181
sl@391
   182
            int numBytes = bitmap.Width * bitmap.Height * 4;
sl@391
   183
            byte[] bytes = new byte[numBytes];
sl@391
   184
            Marshal.Copy(Scan0, bytes, 0, numBytes);
sl@391
   185
            bitmap.UnlockBits(data);
sl@391
   186
sl@391
   187
            byte red, green, blue;
sl@391
   188
            for (int i = 0; i < bytes.Length; i += 4)
sl@391
   189
            {
sl@391
   190
                blue = bytes[i];
sl@391
   191
                green = bytes[i + 1];
sl@391
   192
                red = bytes[i + 2];
sl@391
   193
sl@391
   194
                bytes[i] = color.B;
sl@391
   195
                bytes[i + 1] = color.G;
sl@391
   196
                bytes[i + 2] = color.R;
sl@391
   197
                bytes[i + 3] = (byte)(0.3 * red + 0.59 * green + 0.11 * blue);
sl@391
   198
            }
sl@391
   199
sl@391
   200
            return IconFactory.Create(bytes, bitmap.Width, bitmap.Height,
sl@391
   201
              PixelFormat.Format32bppArgb);
sl@391
   202
        }
sl@391
   203
sl@391
   204
        private Icon CreatePercentageIcon()
sl@391
   205
        {
sl@391
   206
            try
sl@391
   207
            {
sl@391
   208
                graphics.Clear(Color.Transparent);
sl@391
   209
            }
sl@391
   210
            catch (ArgumentException)
sl@391
   211
            {
sl@391
   212
                graphics.Clear(Color.Black);
sl@391
   213
            }
sl@391
   214
            graphics.FillRectangle(darkBrush, 0.5f, -0.5f, bitmap.Width - 2, bitmap.Height);
sl@391
   215
            float value = sensor.Value.GetValueOrDefault();
sl@391
   216
            float y = 0.16f * (100 - value);
sl@391
   217
            graphics.FillRectangle(brush, 0.5f, -0.5f + y, bitmap.Width - 2, bitmap.Height - y);
sl@391
   218
            graphics.DrawRectangle(pen, 1, 0, bitmap.Width - 3, bitmap.Height - 1);
sl@391
   219
sl@391
   220
            BitmapData data = bitmap.LockBits(
sl@391
   221
              new Rectangle(0, 0, bitmap.Width, bitmap.Height),
sl@391
   222
              ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);
sl@391
   223
            byte[] bytes = new byte[bitmap.Width * bitmap.Height * 4];
sl@391
   224
            Marshal.Copy(data.Scan0, bytes, 0, bytes.Length);
sl@391
   225
            bitmap.UnlockBits(data);
sl@391
   226
sl@391
   227
            return IconFactory.Create(bytes, bitmap.Width, bitmap.Height,
sl@391
   228
              PixelFormat.Format32bppArgb);
sl@391
   229
        }
sl@391
   230
sl@391
   231
        public void Update()
sl@391
   232
        {
sl@391
   233
 
sl@391
   234
sl@391
   235
            switch (sensor.SensorType)
sl@391
   236
            {
sl@391
   237
                case SensorType.Load:
sl@391
   238
                case SensorType.Control:
sl@391
   239
                case SensorType.Level:
sl@391
   240
                    //notifyIcon.Icon = CreatePercentageIcon();
sl@391
   241
                    break;
sl@391
   242
                default:
sl@391
   243
                    //notifyIcon.Icon = CreateTransparentIcon();
sl@391
   244
                    break;
sl@391
   245
            }
sl@391
   246
sl@391
   247
sl@391
   248
            string format = "";
sl@391
   249
            switch (sensor.SensorType)
sl@391
   250
            {
sl@391
   251
                case SensorType.Voltage: format = "\n{0}: {1:F2} V"; break;
sl@391
   252
                case SensorType.Clock: format = "\n{0}: {1:F0} MHz"; break;
sl@391
   253
                case SensorType.Load: format = "\n{0}: {1:F1} %"; break;
sl@391
   254
                case SensorType.Temperature: format = "\n{0}: {1:F1} °C"; break;
sl@391
   255
                case SensorType.Fan: format = "\n{0}: {1:F0} RPM"; break;
sl@391
   256
                case SensorType.Flow: format = "\n{0}: {1:F0} L/h"; break;
sl@391
   257
                case SensorType.Control: format = "\n{0}: {1:F1} %"; break;
sl@391
   258
                case SensorType.Level: format = "\n{0}: {1:F1} %"; break;
sl@391
   259
                case SensorType.Power: format = "\n{0}: {1:F0} W"; break;
sl@391
   260
                case SensorType.Data: format = "\n{0}: {1:F0} GB"; break;
sl@391
   261
                case SensorType.Factor: format = "\n{0}: {1:F3} GB"; break;
sl@391
   262
            }
sl@391
   263
            string formattedValue = string.Format(format, sensor.Name, sensor.Value);
sl@391
   264
sl@391
   265
            if (sensor.SensorType == SensorType.Temperature &&
sl@391
   266
              unitManager.TemperatureUnit == TemperatureUnit.Fahrenheit)
sl@391
   267
            {
sl@391
   268
                format = "\n{0}: {1:F1} °F";
sl@391
   269
                formattedValue = string.Format(format, sensor.Name,
sl@391
   270
                  UnitManager.CelsiusToFahrenheit(sensor.Value));
sl@391
   271
            }
sl@391
   272
sl@391
   273
            string hardwareName = sensor.Hardware.Name;
sl@391
   274
            hardwareName = hardwareName.Substring(0,
sl@391
   275
              Math.Min(63 - formattedValue.Length, hardwareName.Length));
sl@391
   276
            string text = hardwareName + formattedValue;
sl@391
   277
            if (text.Length > 63)
sl@391
   278
                text = null;
sl@391
   279
sl@391
   280
sl@391
   281
        }
sl@391
   282
    }
sl@391
   283
}