/// <summary>
        /// Paints <see cref="TrafficStat"/> on a NotifyIcon. It needs native Windows
        /// function to destroy the icon. The size of the graph matches small icon size
        /// as provided by .NET runtime.
        /// </summary>
        public void Paint(NotifyIcon icon, TrafficStat stat)
        {
            Paint(NotifyIconBitmap, stat);
            var hicon = NotifyIconBitmap.GetHicon();

            icon.Icon = Icon.FromHandle(hicon);
            DestroyIcon(hicon);
        }
        /// <summary>
        /// Paints <see cref="TrafficStat"/> on a PictureBox. The size of the graph
        /// matches the size of the PictureBox.
        /// </summary>
        public void Paint(PictureBox graph, TrafficStat stat)
        {
            if (graph.Width <= 0 || graph.Height <= 0)
            {
                // Always be resilient to strange states.
                // We don't want the repeat of FreeMeter, do we?
                return;
            }
            Bitmap bitmap = graph.Image as Bitmap;

            if (bitmap == null || bitmap.Size != graph.Size)
            {
                bitmap = new Bitmap(graph.Width, graph.Height);
            }
            Paint(bitmap, stat);
            graph.Image = bitmap;
        }
        /// <summary>
        /// Paints <see cref="TrafficStat"/> on an arbitrary Bitmap.
        /// </summary>
        public void Paint(Bitmap bitmap, TrafficStat stat)
        {
            Graphics graphics = Graphics.FromImage(bitmap);

            try
            {
                graphics.Clear(ClearColor);

                int     amount         = bitmap.Width;
                float[] downloadTotals = stat.Total(Stat.Download, amount);
                float[] uploadTotals   = stat.Total(Stat.Upload, amount);

                // It's a buggy state if this happens.
                if (downloadTotals.Length != uploadTotals.Length)
                {
                    throw new TrafficMeasureException("uneven upload/download totals");
                }

                // However, it's perfectly fine to get lesser amount of totals than requested.
                int realAmount = downloadTotals.Length;
                // Totals length may be shorter than the graph width, but we still want
                // the graph bars to stick to the right edge.
                for (int idx = 0, drawPos = bitmap.Width - realAmount; idx < realAmount; ++idx, ++drawPos)
                {
                    float download = downloadTotals[idx];
                    float upload   = uploadTotals[idx];

                    float biggerTotal;
                    Pen   biggerPen;
                    float lowerTotal;

                    if (download > upload)
                    {
                        biggerTotal = download;
                        lowerTotal  = upload;
                        biggerPen   = DownloadPen;
                    }
                    else
                    {
                        biggerTotal = upload;
                        lowerTotal  = download;
                        biggerPen   = UploadPen;
                    }

                    // We're drawing from bottom up, so from graph.Height to 0.
                    graphics.DrawLine(biggerPen,
                                      drawPos, bitmap.Height,
                                      drawPos, GetDrawY1(biggerTotal, bitmap.Height));
                    // This bar will always be smaller.
                    graphics.DrawLine(BothPen,
                                      drawPos, bitmap.Height,
                                      drawPos, GetDrawY1(lowerTotal, bitmap.Height));
                    // Draw scale text.
                }
                if (CanPaintScale(bitmap))
                {
                    graphics.DrawString(ScaleText, TextFont, TextBrush, 1, 1);
                }
            }
            finally
            {
                graphics.Dispose();
            }
        }
 /// <summary>
 /// Initiates the monitoring system. Can be called again to reset the monitoring history.
 /// </summary>
 public void Start()
 {
     TrafficGrabber.RefreshNics();
     TrafficStat = new TrafficStat();
 }