Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / Languages / C#

SYSInfo: System info desktop tool

4.92/5 (142 votes)
10 Aug 2015GPL319 min read 312.2K   17.2K  
Displays system information like free disk space and free memory on the desktop.

Introduction

This tool displays information about system resources and settings. It uses WMI instrumentation and Windows API for the queries. At the moment, the following system information is available for display:

  • Free physical memory
  • Free virtual memory
  • Free paging area
  • Free disk space (text or bar graph)
  • IP-addresses
  • Subnet mask
  • MAC-addresses
  • Default gateway
  • Network throughput (text and graph)
  • Host name
  • User
  • Boot date
  • OS version
  • Service Pack
  • CPU usage (text and graph)
  • Top 5 processes (memory usage)
  • Top 5 processes (CPU usage)
  • Disk usage (text and graph)
  • Battery status (text and graph)

Further features:

  • Freely positionable on the desktop
  • Different background settings (transparent/gradient/texture)
  • Support for loading background images
  • Support for manipulating background image colors
  • Modifiable font settings
  • Modifiable refresh time
  • The HDD bar graph includes a simple directory browser
  • Displaying active network connections with options like tracert, whois, close port

Background

This program is based on my first program here: WMIInfo. It's now almost 2 years ago that I started it. During that time, many ideas came up in my mind about how to extend and enhance the program. As I made many changes to the original program and also used different methods than just WMI instrumentation, I decided to give the program a new, more common name... I still have to say (like I did the first time here), you shouldn't expect too much with regard to the code - though I hope my coding has improved Wink | <img src= . And surely, any suggestions, corrections, or improvements are very welcome!

Using the Program

The first time you start the program, you have to set up the information to be displayed.

Image 2

 

 

The right row shows the available functions. You can add them to the Active Function list by double-clicking, or remove them from the list also by double-clicking.

 

 

You can assign individual font types and colors to each function by unchecking "global". Again, the function you want to assign a different font / color has to be selected in the Active Functions list. Assign the font / color by clicking the arrow-button next to the font-button.

  • Order: The functions will be displayed in the order in which they show up in the list. You can change the order with the arrow buttons on the bottom of the form.
  • Titles: You can add an individual title to most of the active functions. Just select the function, write a title in the left title field, and assign the title by clicking the arrow button beside it.
  • Text colors and font type: Text color and font type apply to the whole form when "global" is checked.
  • Refresh rate: The refresh rate refers to the form and some functions. It's a global setting for how often the controls of the form are refreshed. Nevertheless, the "usage" functions have their own refresh rate setting.
  • Background gradient: This applies to the gradient for the background color of the whole form. You can assign two colors and the angle for the gradient. The background itself is selected by the context menu of the form - I'll refer to that later below.
  • 'Aero'-glass: This applies to Vista through Win8 with DWM ('Aero') enabled. If you have the 'aero effect' enabled in the 'background' settings, you can change here the color of the glass.
    Selecting 'transparent' sets the background color to the transparency key of the form. In Vista/Win7 it will result in the usual glass look. In Win8 it results in a real transparent look - but renders much better than the 'normal' transparency on coloured backgrounds.
    • textured: the glass-effect is overlayed by a texture (see 'background' tab)
    • gradient: the glass-effect is overlayed by a gradient (see above 'background gradient')
    • transparency: the level of transparency of the selected texture/gradient

Extended Settings

Image 3

 

 

The extended settings refer to the usage functions like CPU usage, network usage, and disk usage. All these functions have a little graph that shows the usage over a certain time span, and is updated at a given refresh rate. The refresh rate is in milliseconds, and the time span in seconds.

 

Keep in mind that a higher refresh rate (e.g a smaller value) consumes more CPU power.

Image 4

For Win7 and Vista, the text shows the CPU number followed by the core number, and its actual speed followed by the actual usage.

Image 5

The text always starts with the name of the network connection and its actual speed setting. (I'm not quite sure, but I think the speed for the wireless connections is reduced by the router when not in use over a certain time.)

The throughput graph shows the sent and received bytes per second. This graph is auto-scaled as you won't see much when scaled to the maximum possible speed. The graph for received bytes is light blue, while for sent bytes is turquoise.

'Disable Adapter' holds a list of your network devices. You may disable them here to not show up in the tool window.

As an additional feature, double clicking the network label opens a window showing the active network connections:

Image 6

LEFT clicking an remote address opens a context menu with the options:

  • trace route
  • trace route with resolving the ip-address - this might be very slow!
  • getting the whois info - the query is processed by the "GeekTools Whois Proxy" - it automatically queries the related top level domain services
  • terminating the connection either by closing the remote port or by closing the connection

LEFT clicking a PID or process gives you the option to terminate the process.

This tool is still a little bit buggy as for example when sorting the list by clicking the header, the returned value of an selected entry is still the value of the original field...

  • Disk usage: Shows the read and write usage of a hard disk or a removable device like a USB stick.

The first line shows the drive number followed by its partitions.

Image 7

The y-scale of the graph is set to ~100Mbytes/sec.

  • HDD-Bar: The HDD-bar is an alternative to the free disk space text display.

Image 8

You can assign three colors for the thresholds of 0-50, 50-75, and 75-100%. It may be a little bit confusing, but these thresholds refer to the used space - while the text values refer to the free space.

An additional feature of the HDD-bar is a little file browser. You can open it by left clicking on the bar:

Image 9

It acts like the Windows file browser: double click opens files and folders, right click opens the context menu. Shift and Ctrl keys are also supported.

You can test your settings with the Test button. 'Restore' restores the settings to the last saved state. Apply the settings and close the form with the 'Apply' button.

Background Settings

Image 10

I've implemented some little image manipulating: You can load an image as background for the tool and manipulate the colors.
Most image file types are supported.
Don't forget to use only small images!
The color manipulation is done by the colormatrix class. Here's a good example.

  • Context menu:

Image 11

  • "refresh" refreshes the form controls
  • "settings": "change" opens the settings dialog - "delete" restores the initial settings
  • "language" changes the language of the control (English/German available)
  • "border" adds a border to the form -- (thin/thick/AeroSpecial) available -- enable/disable by clicking on "border"
  • "background" options: transparent / aero / gradient / texture (blue / grey)
  • "locked" at moment disables movement of the form

Image 12

Image 13

Image 14

Image 15

Transparent Aero glass effect (Vista/7) Gradient Texture and thick border

Points of Interest

First of all, I'd like to say thanks to all the programmers out there who enabled me to write this program because they shared their ideas and code! To mention some of them:

Inspiration for the file browser and shell context menu:

Finally, I want to mention some basic concepts and interesting ideas I found out. I can't go too much into the details as it would go far beyond the scope of this article.

In my first program WMIInfo, I only made use of one label for displaying the system info. But as I wanted to use graphs and bars, I had to change the concept for displaying the info. At the moment, I have 20 predefined labels on the form which are placeholders for the functions.

As I made more and more use of dynamically created controls, I found these labels could be created dynamically when needed. But it is too much effort in my opinion at the moment...

When starting the program, we load the stored settings from the settings file.

VARIABLE = Properties.Settings.Default.[Name of property]

There is a global array for the functions (iFunction[]) and a global array for the label controls (cLabel[]).

The active functions have a value greater than -1, and provide the order of appearance. The index of the function array refers to the function itself:

Index Function
0 free memory
1 free virtual memory
2 free paging memory
3 free disk space
4 network (settings and usage)
5 hostname
6 username
7 boot date
8 OS version
9 service pack
10 CPU usage
11 top 5 processes (memory usage)
12 top 5 processes (CPU usage)
13 disk usage
14 battery status

In order to display a graph instead of a text label, I made use of panels. The panels get a text label and a graph control assigned. The panel itself replaces the label in the control array. I found out that I can assign controls to a label, which I think is funny. But the drawback is that the autosize property doesn't work for these controls.

The raw workflow of the program is like follows:

  • Load settings
  • Initiate arrays for labels and functions
  • Initiate selected functions
  • Process the functions periodically

WMI Queries

The processing of the WMI data is like this:

C#
string query = "SELECT * FROM Win32_OperatingSystem";
ManagementObjectSearcher seeker = new ManagementObjectSearcher(query);
ManagementObjectCollection oReturnCollection = seeker.Get();
foreach (ManagementObject m in oReturnCollection)
{
    VARIABLE = m["NAMEOFPROPERTY"];
    (...)
}

For the top 5 processes, I used a LINQ query:

C#
var query = (from p in System.Diagnostics.Process.GetProcesses()
             orderby p.PrivateMemorySize64 descending
             select p)
    .Skip(0)
    .Take(5)
    .ToList();
string s = "",t = "";
foreach (var item in query)
{
    s += item.ProcessName  + "\r\n";
    t += CalcSize(item.PrivateMemorySize64.ToString(), 1)  + "\r\n";
}

Classes

As I started using classes, I made global references to classes. Meanwhile, I found out that I could assign a class to a panel control and refer to it later without a global reference. Don't know if this is a better way....

I made the classes mostly independent... some have references to timer settings - if you replace these, you should be able to use them independently of this project.

Classes in this project:

To get the adapter names, you need to query Win32_NetworkAdapterConfiguration like this:

C#
string[] s = new string[0];
string query = "SELECT * FROM Win32_NetworkAdapterConfiguration " + 
               "WHERE IPEnabled = TRUE";
ManagementObjectSearcher seeker = new ManagementObjectSearcher(query);
ManagementObjectCollection oReturnCollection = seeker.Get();
foreach (ManagementObject m in oReturnCollection)
{
    try
    {
        Array.Resize(ref s, i + 1);
        s[i] = Networkadapter(m);//get name of adapter from registry
        i++;
    }
    catch
    { }
}

You can get the names from the Registry like this:

C#
public string Networkadapter(ManagementObject m)
{
    RegistryKey rK = Registry.LocalMachine;
    string s = "";
    s = m["SettingID"].ToString();
    RegistryKey rSub = rK.OpenSubKey("SYSTEM\\CurrentControlSet\\Control" + 
                "\\Network\\{4D36E972-E325-11CE-BFC1-08002BE10318}\\" + 
                s + "\\Connection");
    s = rSub.GetValue("Name").ToString();
    return s;
}

Finally, you can init the label and the graph for each adapter in a loop with:

C#
for (int k = 0; k < monitor.Adapters.Length; k++)
{
    netLoad[k] = new NetworkWorkload(s[k], monitor.Adapters[k]);
    monitor.Adapters[k].init();
    pNet.Controls.Add(netLoad[k].Label); //add the label control to a panel
    pNet.Controls.Add(netLoad[k].NetGraphControl); //add the graph control to a panel
}

where netload[] is an array of Networkload class, and pNet is a panel control containing the label and the graph.

If the network configuration changes, e.g., when dis-/connecting the WLAN or LAN, you need to re-init the monitors. With the event NetworkChange.NetworkAddressChanged += new NetworkAddressChangedEventHandler(AddressChangedCallback);, you can detect changes.

  • CPUProcess: CPU usage - Top 5 list of processes
    • Init with processlist pList = new processlist();
    • Retrieve list with System.Collections.IList iList = pList.top5_list;
  • CPUWorkload: Displays CPU usage as text and graph
    • Init with CPUWorkload CWL = new CPUWorkload({bool bGraph}, {bool bText});
    • Retrieve the text in a label control: CWL.Label
    • Retrieve the graph: CWL.CPUGraphControl
  • DiskUsage: throughput of disks as text and graph
    • Init with DiskUsage du = new DiskUsage("part of the name of the physical partition - like C:")
    • Retrieve the text in a label control: du.Label
    • Retrieve the graph: du.DiskGraphControl
  • NetworkAdapter/ NetworkMonitor/ NetworkWorkload: Network throughput as text and graph
    • Init the adapter with NetworkMonitor monitor = new NetworkMonitor({Array of networkadapter names from registry});

Windows API Stuff

It was quite interesting for me to discover the possibilities of using the Windows API. Though implementing the file browser was quite hard, it also was a great joy as it worked. Smile | <img src= " />

Here are a few nice little helpers.

Disk Change Notification

In order to receive notifications of hardware events, you can override window messages:

C#
private const UInt32 WM_DEVICECHANGE = 0x0219;
private const UInt32 DBT_DEVICEARRIVAL = 0x8000;
private const UInt32 DBT_DEVICEREMOVECOMPLETE = 0x8004;
protected override void WndProc(ref Message m)
{
    if (iFunction[13] > -1 && m.Msg == WM_DEVICECHANGE)    {
        if (m.WParam.ToInt32() == DBT_DEVICEARRIVAL || 
            m.WParam.ToInt32() == DBT_DEVICEREMOVECOMPLETE)
        {
            Action action = _diskusage_init;
            this.BeginInvoke(action);
        }
    }
    base.WndProc(ref m);
}

First, I ran into some problems when calling the method "_diskusage_init()" directly here. It gave me some strange messages of a disconnected COM object. By Googling, I found that it was a thread invoke problem. I solved this with these two lines:

C#
Action action = _diskusage_init;
this.BeginInvoke(action);

Instead of these, I first used the "traditional" delegate method. But then I came to the idea of trying it like this, as I've used the "ExecuteThreadSafe" method by Marcell Spies at other places.

C#
public static class ControlExtensions
{
    public static void ExecuteThreadSafe(this Control control, Action action)
    {
        if (control.InvokeRequired)
        {
            control.BeginInvoke(action);
        }
        else
        {
            action.Invoke();
        }
    }
}

Interestingly, the runtime even didn't "know" that it has to be invoked, because I had the same error when calling it with this.ExecuteThreadSafe(_diskusage_init);. So I forced it without querying InvokeRequired. This still leaves the question of why we need to declare a global delegate and a delegate method when the same is done with "Action", which is also a delegate.

Aero Glass Effect (Vista and Higher)

With Vista, Microsoft introduced the DesktopWindowManager (DWM) with some nice effects like Aero Glass blurring the background of the form. To make this work, Aero and transparency has to be enabled for the system. First, you need to import some methods from dwmapi.dll:

C#
[System.Runtime.InteropServices.DllImport("dwmapi.dll", PreserveSig = false)]
public static extern bool DwmIsCompositionEnabled();
[System.Runtime.InteropServices.DllImport("dwmapi")]
private static extern int DwmEnableBlurBehindWindow(
            System.IntPtr hWnd, ref DWM_BLURBEHIND pBlurBehind);
[System.Runtime.InteropServices.DllImport("gdi32.dll")]
static extern IntPtr CreateRectRgn(int x1, int y1, int x2, int y2);
public struct DWM_BLURBEHIND
{
    public int dwFlags;
    public bool fEnable;
    public System.IntPtr hRgnBlur;HRGN
    public bool fTransitionOnMaximized;
}

As this form is not static, but dynamically fits its size to changes like new disk drive or network connection, the rendering of the glass effect has to be initialized each time the form resizes - at least this is the way I managed to make it work; there's probably a better solution.

C#
private void Form1_Resize(object sender, EventArgs e)
{
    //Check to see if composition is Enabled / enable
    // background blurring if selected
    if (System.Environment.OSVersion.Version.Major >= 6 && 
        DwmIsCompositionEnabled())
    {
        //the rectangle region of the effect
        IntPtr hr = CreateRectRgn(0, 0, this.Width, this.Height);
        DWM_BLURBEHIND dbb;
        //bool - activate / deactivate the effect
        dbb.fEnable = bAero;
        dbb.dwFlags = 1 | 2;
        dbb.hRgnBlur = hr;
        dbb.fTransitionOnMaximized = true;
        DwmEnableBlurBehindWindow(this.Handle, ref dbb);
        this.Invalidate();
        System.Runtime.InteropServices.Marshal.Release(dbb.hRgnBlur);
    }
    else
    {
        this.Invalidate();
    }
}

When the effect is en-/disabled, you need to recreate the form to apply the change properly:

C#
this.RecreateHandle();

With Win8 microsoft changed a lot of things - by chance I found out that DwmEnableBlurBehindWindow hasn't been removed or disabled. It's not exactly the same glass effect as in Win7 as there are no shades.

In order to make it work we need another API call:

[DllImport("dwmapi.dll")]
 public static extern void DwmExtendFrameIntoClientArea(IntPtr hWnd, Margins pMargins);

[StructLayout(LayoutKind.Sequential)]
 public class Margins
 { public int cxLeftWidth, cxRightWidth, cyTopHeight, cyBottomHeight;}

So I had to extend the resize event a little bit:

if ((System.Environment.OSVersion.Version.Minor >= 2)|(bFrameChecked&&!bFrameType&&bAeroFrame))
DwmExtendFrameIntoClientArea(Handle, new Margins { cxLeftWidth = -1, cxRightWidth = -1, cyTopHeight = -1, cyBottomHeight = -1 });

Again by chance I found out that applying this to a window with 'thick border' and aero enabled in Win7 it results in a nice shaped glassy tile - therefor I added the option 'Aero special' in the border menu.

After playin' a while with aero I added the 'gradient' and 'textured' feature.

The implementation of the gradient feature is quite simple: you just need to add/adjust the alpha channel to the gradient colors

if (bAero & bAeroGradient)
{ 
    c1 = Color.FromArgb((byte)(fAeroTransparency * (float)255),c1);
    c2 = Color.FromArgb((byte)(fAeroTransparency * (float)255),c2);
}  

The texture feature needs a little bit more work. I found a nice method by Jan Romell. The code loops over every pixel and changes the alpha channel. This works for all images with non indexed colors.

C#
ImageBack = ChangeImageOpacity(ImageBack, fAeroTransparency);

So the background image's transparency is set before the 'e.Graphics.DrawImage' command.

Transparent Border

I struggled a bit with drawing rounded shapes or borders. I first tried some ideas with rounded rectangles and clipping, but the result wasn't as expected. Finally, I found several articles about overriding CreateParams and manipulating the form style, and ended up with this quite simple method:

C#
//Window with a thin caption. Does not appear in the taskbar or in the Alt-Tab palette
public const int WS_EX_TOOLWINDOW = 0x00000080;
public const int WS_THICKFRAME = 0x800000; //window with a "sizing" border
public const int WS_BORDER = 0x00040000; //window with a thin-line border

protected override CreateParams CreateParams
{
    get
    {
        new System.Security.Permissions.SecurityPermission(
            System.Security.Permissions.SecurityPermissionFlag.UnmanagedCode).Demand();
        CreateParams cp = base.CreateParams;
        if (bFrameChecked)
        {
            cp.Style |= bFrameType ? WS_THICKFRAME : WS_BORDER;
        }
        cp.ExStyle |= WS_EX_TOOLWINDOW;
        return cp;
    }
}

By setting WS_EX_TOOLWINDOW, the app doesn't show up in the ALT-TAB list and also not in the applist of Task Manager.

This leads me to transparency in general: in order to make the form transparent, you first need to set SetStyle(ControlStyles.SupportsTransparentBackColor, true); to enable transparency.

Then you need to select a certain color for transparency in the form properties and set the background color of the form to the selected color. The drawback of this method is that whenever this color appears in your controls, it will be transparent!

C#
this.BackColor = System.Drawing.Color.FromArgb(2, 2, 2);
this.TransparencyKey = System.Drawing.Color.FromArgb(2, 2, 2);

Another drawback is, if you disable any borders of the form like I did here, you won't be able to move it anymore. Wink | <img src= " /> The solution is to make the background opaque when entering the form and then to call mouse events when pushing the mouse button and moving the mouse.

Moving a Transparent Borderless Form

C#
private Point m_offset;
private Point m_Pos;
private void EM_MouseMove(object sender, MouseEventArgs e)
{
    if (e.Button == MouseButtons.Left)
    {
        m_Pos = Control.MousePosition;
        m_Pos.Offset(m_offset.X, m_offset.Y);
        Location = m_Pos;
    }
}
private void EM_MouseDown(object sender, MouseEventArgs e)
{
    int x1,x2,y1,y2,dx,dy;
    x1 = Location.X;
    y1 = Location.Y;
    x2 = -MousePosition.X;
    y2 = -MousePosition.Y;
    dx = x1 + x2;
    dy = y1 + y2;
    m_offset = new Point(dx,dy);
}

Some Things that Don't Work Properly

The different classes for usage and with a graph are running in background tasks. Therefore the controls of the form probably won't show up in the right position immediately when testing or applying the settings as the classes might not be fully initialized when the form is updated. It corrects itself with the next refresh. Nevertheless, sometimes you have to refresh it manually as a workaround.

When the background is set to transparent, the text doesn't render nicely on a desktop with many different colors like it is in a picture. I think it has to do with the transparency of the text labels and anti-aliasing as you can see small artifacts of the form-background color around the letters.

EDIT: As mentioned above, in Win8 having the 'Aero effect' enabled and the background color set to the transparency key, the text renders really nice.

XP

I've tested the program on XP and found out that some WMI classes aren't available, like Win32_PerfFormattedData_Counters that I used for getting the CPU details. Therefore, I had to do a workaround by querying the OS version and using different WMI-classes for the query (like Win32_PerfFormattedData_PerfOS_Processor for the CPU usage, and Win32_Processor for the CPU details).

Finally, it showed up that querying "Win32_Processor" takes quite long and eats up a lot of CPU power. So, if you use XP, I would suggest disabling the CPU text when showing the CPU usage. Interestingly, I had to switch to the same class on a quad core machine (running Win7) as it always showed zero for the current CPU speed, while on a dual core, it's working without problems - anyone has any idea why this happens (might be because the quad is a 64 bit processor)?

History

  • 8 Sep 2010: SYSInfo 1.0
  • 19 Sep 2010:
    • Added battery status on request from sam.hill.
    • Fixed the settings dialog showing wrong language when changing language after settings were made.
    • Added a "locked" option on request from JF2015. (Still working on a 'true' lock option.)
    • Removed the app from ALT-TAB list on request from JF2015.
    • Added a 'delete' option in context menu - settings. In case the settings file is screwed up, you can now restore the initial settings by this.
  • 25 Sep 2010:
    • Added a "active connections" form with several options like 'whois', 'tracert' and 'close port':
      The form opens by double clicking on the network label

      Image 19

      For the active connections, I used a class from http://www.codeproject.com/KB/IP/iphlpapi2.aspx by Warlib.

    • Added support for loading background images and color manipulation:

      Image 20

      Image 21

      (I've added some textures for testing in the demo folder.)
  • 3 Jan 2013:
    • Some Bugfixes e.g. unhandled exception when a drive reports '0' as free space (mainly CDs)
    • extended tooltips for the filebrowser
    • Added 'aero' glass support for Win8
    • Added a color option for the 'aero' glass background
  • 6 Jan 2013:
    • changed the NeutralResourcesLanguage to 'english' - so You won't be bothered with 'German' if the UI falls back to the neutral language Wink | <img src= " src="http://www.codeproject.com/script/Forums/Images/smiley_wink.gif" />
  • 7 Jan 2013:
    • changed default language in settings.settings to 'EN-gb'
    • added a list for hiding/disabling HDDs - might be useful when cardreaders installed
  • 13 Jan 2013
    • After playin' a while with the 'aero' stuff in win8 I finally added a few options:
      Image 23
      • textured: the glass-effect is overlayed by a texture
      • gradient: the glass-effect is overlayed by a gradient
      • transparency: make the overlay transparent - well, this is the main feature
I didn't try it on win7, yet - so I really can't say @moment how it looks there or if it even works...maybe tomorrow @office on the secretary's pc Wink | <img src= " src="http://www.codeproject.com/script/Forums/Images/smiley_wink.gif" />
  • 30 Jan 2013
    • minor bugfix for the filebrowser - wrong property has been selected when rightclicking on a file
  • 28 Feb 2014
    • minor bugfixes
    • added option "total" for CPU usage graph&text display / so it shows only the average usage and not all the single cores
    • tried a workaround for the new "behaviour" of win8 regarding the logged startup time
    • changed the scale for diskusage graph from fixed value to "auto"
  • 18 Apr 2014
    • Bugfix: on some systems, the app freezes because of a timing problem with the RPC service. I think its even worse with windows 8x. Probably they changed something with the handling of the calls...?
      Therefore I added a lock for all the wmi queries:

      private ReaderWriterLockSlim dcLock = new ReaderWriterLockSlim();

      if (dcLock.TryEnterWriteLock(50))
      (...)

      I've watched it a couple of days and it seems to work now....
    • Added a zip-file preview for the folder browser - extracting is not implemented, yet.
    •  
  • 28 Oct 2014
    • minor update - the whois service provider "whois-server(s).net" seems no longer to accept queries - switched to "whois.ripe.net"
      btw. does anyone know a good & free whois service provider like ripe? Ripe is really fast, but it does not host all records....
  • 04 Aug 2015
    • changed design for the disklevel-bars:

      Image 25
       
    • added a level-bar for free system memory
    • added a true lock option:
      The app spawns a new window on lowest level behind desktop icons.
      Therefore its no longer moveable or accessible.
      Tested with win7,8,10

      MANY thanks to Gerald Degeneve who finally made this possible! Take a look a his article: "Draw Behind Desktop Icons in Windows 8"
      • If You have fontscaling activated (like on small high res screens) this might be buggy.
        You could try to disable the dpi-scaling in the compatibility settings of the program (SYSInfo.exe)
         

    • Added an icon to notification area - in order to access the app when in locked state:

      Image 26
       
    • added a "save settings" option
    • some bugfixes like app crash when changing the language, or when using the filebrowser
    • extended the function calls when 'refresh' option is selected - now everything should be refreshed
      There's still a problem with refreshing when the networkadapters change - therefore this should do a workaround
       
  • 07 Aug 2015
    • Made some cosmetic fixes
      • the settings window will open now near the screen center (on high res displays with dpi scaling the top of the window moved outside the screen)
      • new background for the graphs
      • scaling of the bars should be uniform now

        I'm still working on solving the dpi scaling problem on high res displays
        As mentioned above, You should also try to disable the dpi-scaling in the compatibility settings of the app.
         
  • 10 Aug 2015
    • Added 'dpi-awareness' for fixing scaling issues on small high-res displays. (https://msdn.microsoft.com/library/windows/desktop/ff684173(v=vs.85).aspx)
      To disable dpi-autoscaling of the OS You have to add an app-manifest with the option <dpiAware>true</dpiAware>
      DPI scaling is calculated like this: 96 dpi is the default. So when having a display with 144 dpi set You simply divide 144 by 96 and multiply the result with the desired size.
      In my code it looks like this:
      private int DPIScaling(int iPixel)
      {
          Graphics graphics;
          graphics = Graphics.FromHwnd(this.Handle);
          var dpiX = graphics.DpiX;
          var dpiY = graphics.DpiY;
      
          if (dpiX > 0)
              return (int)((float)iPixel * (dpiX / 96.0));
          else
              return iPixel;
      
      }
      
    • Added an 'hide' option as suggested by Youregi
       

License

This article, along with any associated source code and files, is licensed under The GNU General Public License (GPLv3)